pax_global_header00006660000000000000000000000064144663522600014522gustar00rootroot0000000000000052 comment=0f2d4cfffada6f8448a2cb27995b38eb4271044f dlt-daemon-2.18.10/000077500000000000000000000000001446635226000137175ustar00rootroot00000000000000dlt-daemon-2.18.10/.clang-format000066400000000000000000000051131446635226000162720ustar00rootroot00000000000000--- Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: false AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: false BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: true AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false BeforeCatch: false BeforeElse: true IndentBraces: false BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|isl|json)/)' Priority: 3 - Regex: '.*' Priority: 1 IndentCaseLabels: false IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBlockIndentWidth: 4 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: true SortIncludes: true SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 TabWidth: 4 UseTab: Never ... dlt-daemon-2.18.10/.github/000077500000000000000000000000001446635226000152575ustar00rootroot00000000000000dlt-daemon-2.18.10/.github/workflows/000077500000000000000000000000001446635226000173145ustar00rootroot00000000000000dlt-daemon-2.18.10/.github/workflows/cmake-ctest.yml000066400000000000000000000033271446635226000222440ustar00rootroot00000000000000name: CMake on: push: branches: [ "master" ] pull_request: branches: [ "master" ] env: BUILD_TYPE: Release WITH_DLT_COVERAGE: ON BUILD_GMOCK: OFF jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Prepare submodule run: | git submodule init git submodule update - name: Configure CMake run: | cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ -DWITH_DLT_COVERAGE=${{env.WITH_DLT_COVERAGE}} \ -DBUILD_GMOCK=${{env.BUILD_GMOCK}} - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - name: Test working-directory: ${{github.workspace}}/build run: ctest -C ${{env.BUILD_TYPE}} - name: Install dependencies run: sudo apt-get install lcov - name: Generate lcov report working-directory: ${{github.workspace}} run: bash util/dlt_coverage_report/lcov_report_generator.sh build -xe - name: Archive coverage results uses: actions/upload-artifact@v3 with: name: dlt_coverage_report path: ${{github.workspace}}/dlt_lcov_report - name: Upload lcov report if: github.ref == 'refs/heads/master' run: | git config user.name github-actions git config user.email github-actions@github.com git checkout -b dlt_coverage_report git submodule deinit -f googletest rm -rf .git/modules/googletest git rm -f googletest git add --all git commit -m "Upload lcov report for dlt-daemon" git push -f origin dlt_coverage_report dlt-daemon-2.18.10/.github/workflows/codeql-analysis.yml000066400000000000000000000050261446635226000231320ustar00rootroot00000000000000# For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. name: "CodeQL" on: push: branches: [master] pull_request: # The branches below must be a subset of the branches above branches: [master] schedule: - cron: '0 9 * * 1' jobs: analyze: name: Analyze runs-on: ubuntu-latest strategy: fail-fast: false matrix: # Override automatic language detection by changing the below list # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] language: ['cpp'] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - name: Checkout repository uses: actions/checkout@v2 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. - run: git checkout HEAD^2 if: ${{ github.event_name == 'pull_request' }} # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 dlt-daemon-2.18.10/.gitignore000066400000000000000000000003261446635226000157100ustar00rootroot00000000000000Release/ Debug/ build/ automotive-dlt.spec automotive-dlt.pc config.h include/dlt/dlt_version.h include/dlt/dlt_user.h .project .cproject .settings .idea/ *~ *.o *.out *.swp cmake-build-debug/ .vscode/ googletest/ dlt-daemon-2.18.10/.gitmodules000066400000000000000000000001341446635226000160720ustar00rootroot00000000000000[submodule "googletest"] path = googletest url = https://github.com/google/googletest.git dlt-daemon-2.18.10/.travis.yml000066400000000000000000000006521446635226000160330ustar00rootroot00000000000000language: c dist: xenial compiler: gcc script: - cmake -DWITH_DLT_TESTS=ON -DWITH_TESTSCRIPTS=ON -DWITH_DLT_UNIT_TESTS=ON -DWITH_SYSTEMD=ON -DWITH_SYSTEMD_JOURNAL=ON CMakeLists.txt - make - sudo make install - ./.travis/gtest_dlt_all.sh - ./src/tests/dlt-test-user addons: apt: packages: - cmake-data - cmake - libdbus-1-dev - build-essential - systemd - libsystemd-dev dlt-daemon-2.18.10/AUTHORS000066400000000000000000000011661446635226000147730ustar00rootroot00000000000000Copyright (C) 2015 BMW AG. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. Alexander Wenzel Christian Muck Mikko Rapeli Jeremiah C. Foster Stefan Seefeld Noor Ahsan Eckhard Diezel Mohammed AL Dardoun Lassi Marttala Simon Brandner Copyright (c) 2019 MBition GmbH, Andreas Seidl dlt-daemon-2.18.10/Android.bp000066400000000000000000000136461446635226000156340ustar00rootroot00000000000000/** * Copyright (C) 2019 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ cc_defaults { name: "dlt_defaults", vendor: true, local_include_dirs: [ "include/dlt", ], generated_headers: ["dlt_version_header", "dlt_user_header"], cflags: [ "-DDLT_DAEMON_USE_UNIX_SOCKET_IPC", "-DDLT_LIB_USE_UNIX_SOCKET_IPC", "-DCONFIGURATION_FILES_DIR=\"/vendor/etc\"", "-DDLT_USER_IPC_PATH=\"/dev/socket\"", ] + [ "-Wno-unused-parameter", "-W", "-Wall", ], } // Generate dlt_version.h without Cmake genrule { name: "dlt_version_header", tool_files: ["util/create_dlt_version_h.py"], srcs: [ "CMakeLists.txt", "cmake/dlt_version.h.cmake", ], cmd: "$(location util/create_dlt_version_h.py) $(in) $(out)", out: ["dlt_version.h"], } // Generate dlt_user.h without Cmake genrule { name: "dlt_user_header", tool_files: ["util/create_dlt_user_h.py"], srcs: [ "include/dlt/dlt_user.h.in", ], cmd: "$(location util/create_dlt_user_h.py) $(in) $(out)", out: ["dlt_user.h"], } prebuilt_etc { name: "dlt-daemon-configuration", vendor: true, src: "src/daemon/dlt.conf", filename_from_src: true, } cc_binary { name: "dlt-daemon", defaults: ["dlt_defaults"], init_rc: [ "src/daemon/dlt-daemon.rc", ], local_include_dirs: [ "src/daemon", "src/gateway", "src/lib", "src/shared", "src/offlinelogstorage", ], srcs: [ "src/daemon/dlt-daemon.c", "src/daemon/dlt_daemon_client.c", "src/daemon/dlt_daemon_common.c", "src/daemon/dlt_daemon_connection.c", "src/daemon/dlt_daemon_event_handler.c", "src/daemon/dlt_daemon_offline_logstorage.c", "src/daemon/dlt_daemon_serial.c", "src/daemon/dlt_daemon_socket.c", "src/daemon/dlt_daemon_unix_socket.c", "src/gateway/dlt_gateway.c", "src/lib/dlt_client.c", "src/shared/dlt_common.c", "src/shared/dlt_config_file_parser.c", "src/shared/dlt_multiple_files.c", "src/shared/dlt_offline_trace.c", "src/shared/dlt_protocol.c", "src/shared/dlt_user_shared.c", "src/offlinelogstorage/dlt_offline_logstorage.c", "src/offlinelogstorage/dlt_offline_logstorage_behavior.c", ], shared_libs: [ "libc", "libutils", "libcutils", ], required: ["dlt-daemon-configuration"], } cc_library_shared { name: "libdlt", defaults: ["dlt_defaults"], local_include_dirs: [ "src/lib", "src/shared", ], export_include_dirs: [ "include/dlt", ], export_generated_headers: [ "dlt_version_header", "dlt_user_header" ], srcs: [ "src/lib/dlt_client.c", "src/lib/dlt_env_ll.c", "src/lib/dlt_filetransfer.c", "src/lib/dlt_user.c", "src/shared/dlt_common.c", "src/shared/dlt_multiple_files.c", "src/shared/dlt_protocol.c", "src/shared/dlt_user_shared.c", ], } cc_binary { name: "dlt-example-user", defaults: ["dlt_defaults"], srcs: [ "src/examples/dlt-example-user.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-receive", defaults: ["dlt_defaults"], srcs: [ "src/console/dlt-receive.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-logd-converter", defaults: ["dlt_defaults"], srcs: [ "src/android/dlt-logd-converter.cpp", ], init_rc: [ "src/android/dlt-logd-converter.rc", ], cflags: [ "-Wextra", "-Wpedantic", "-std=c++14", ], shared_libs: [ "libdlt", "liblog", "libjsoncpp", ], include_dirs: [ "system/logging/liblog/include", "external/jsoncpp/include", ], } cc_binary { name: "dlt-control", defaults: ["dlt_defaults"], srcs: [ "src/console/dlt-control-common.c", "src/console/dlt-control.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-convert", defaults: ["dlt_defaults"], srcs: [ "src/console/dlt-convert.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-test-non-verbose", defaults: ["dlt_defaults"], srcs: [ "src/tests/dlt-test-non-verbose.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-test-logstorage", defaults: ["dlt_defaults"], srcs: [ "src/tests/dlt-test-logstorage.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-test-multi-process", defaults: ["dlt_defaults"], srcs: [ "src/tests/dlt-test-multi-process.c", ], shared_libs: [ "libc", "libdlt", ], } cc_binary { name: "dlt-logstorage-ctrl", defaults: ["dlt_defaults"], local_include_dirs: [ "systemd/3rdparty/", "src/console", "src/console/logstorage", ], srcs: [ "src/console/dlt-control-common.c", "src/console/logstorage/dlt-logstorage-common.c", "src/console/logstorage/dlt-logstorage-ctrl.c", ], shared_libs: [ "libc", "libdlt", ], } // vim: ft=python dlt-daemon-2.18.10/CMakeLists.txt000066400000000000000000000466401446635226000164710ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright(C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License(MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # Set minimum Cmake version and setup policy behavior cmake_minimum_required(VERSION 3.3) if(${CMAKE_VERSION} VERSION_GREATER "3.20" OR ${CMAKE_VERSION} VERSION_EQUAL "3.20") cmake_policy(SET CMP0115 OLD) endif() project(automotive-dlt VERSION 2.18.10) mark_as_advanced(CMAKE_BACKWARDS_COMPATIBILITY) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) include(GNUInstallDirs) # Set version parameters set(DLT_VERSION_STATE STABLE) execute_process(COMMAND git describe --tags WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE DLT_REVISION ERROR_VARIABLE GIT_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE) if(DLT_REVISION MATCHES "^$") set(PRINT_REVISION "Git revision unavailable") else(DLT_REVISION MATCHES "") string(REPLACE "-" "_" DLT_REVISION ${DLT_REVISION}) set(PRINT_REVISION ${DLT_REVISION}) endif() # set default build type, if not defined by user if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose build type: Debug, Release, RelWithDebInfo, MinSizeRel." FORCE) message(STATUS "Build type not defined. Using default build type 'RelWithDebInfo'.") endif() # Set of indiviual options option(BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON) option(WITH_SYSTEMD "Set to ON to create unit files and systemd check on dlt-daemon startup" OFF) option(WITH_SYSTEMD_WATCHDOG "Set to ON to use the systemd watchdog in dlt-daemon" OFF) option(WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX "Set to ON to trigger systemd watchdog of dlt-daemon only when a message was received since the last trigger" OFF) option(WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_DLT_SYSTEM "Set to ON to trigger systemd watchdog of dlt-system only when a message was received since the last trigger" OFF) option(WITH_SYSTEMD_JOURNAL "Set to ON to use the systemd journal in dlt-system" OFF) option(WITH_SYSTEMD_SOCKET_ACTIVATION "Set to ON to use systemd socket activation" OFF) option(WITH_DOC "Set to ON to build documentation target" OFF) option(WITH_MAN "Set to ON to build man pages" OFF) option(WITH_CHECK_CONFIG_FILE "Set to ON to create a configure file of CheckIncludeFiles and CheckFunctionExists" OFF) option(WITH_TESTSCRIPTS "Set to ON to run CMakeLists.txt in testscripts" OFF) option(WITH_GPROF "Set -pg to compile flags" OFF) option(WITH_DLTTEST "Set to ON to build with modifications to test User-Daemon communication with corrupt messages" OFF) option(WITH_DLT_SHM_ENABLE "EXPERIMENTAL! Set to ON to use shared memory as IPC. EXPERIMENTAL!" OFF) option(WITH_DLT_ADAPTOR "Set to ON to build src/adaptor binaries" OFF) option(WITH_DLT_ADAPTOR_STDIN "Set to ON to build src/adaptor/stdin binaries" OFF) option(WITH_DLT_ADAPTOR_UDP "Set to ON to build src/adaptor/udp binaries" OFF) option(WITH_DLT_CONSOLE "Set to ON to build src/console binaries" ON) option(WITH_DLT_CONSOLE_WO_CTRL "Set to ON not to build control commands under src/console" OFF) option(WITH_DLT_CONSOLE_WO_SBTM "Set to ON not to build dlt-sortbytimestamp under src/console" OFF) option(WITH_DLT_CONSOLE_RECEIVE "Set to OFF to skip building dlt_receive" ON) option(WITH_DLT_CONSOLE_CONVERT "Set to OFF to skip building dlt_convert" ON) option(WITH_DLT_CONSOLE_CONTROL "Set to OFF to skip building dlt_control" ON) option(WITH_DLT_CONSOLE_PASSIVE_NODE_CTRL "Set to OFF to skip building dlt_passive_node_ctrl" ON) option(WITH_DLT_EXAMPLES "Set to ON to build src/examples binaries" ON) option(WITH_DLT_FILETRANSFER "Set to ON to build dlt-system with filetransfer support" OFF) option(WITH_DLT_SYSTEM "Set to ON to build src/system binaries" OFF) option(WITH_DLT_DBUS "Set to ON to build src/dbus binaries" OFF) option(WITH_DLT_TESTS "Set to ON to build src/test binaries" ON) option(WITH_DLT_UNIT_TESTS "Set to ON to build gtest framework and tests/binaries" OFF) option(WITH_DLT_COVERAGE "Set to ON to generate coverage report for dlt-daemon source code" OFF) option(WITH_DLT_QNX_SYSTEM "Set to ON to build QNX system binary dlt-qnx-system" OFF) option(WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK "Set to ON to enable fallback to syslog if dlt logging to file fails" OFF) option(WITH_DLT_NETWORK_TRACE "Set to ON to enable network trace (if message queue is supported)" ON) option(WITH_DLT_LOG_LEVEL_APP_CONFIG "Set to ON to enable default log levels based on application ids" OFF) set(DLT_IPC "FIFO" CACHE STRING "UNIX_SOCKET,FIFO") set(DLT_USER "covesa" CACHE STRING "Set user for process not run as root") set(DLT_QNX_SLOG_ADAPTER_WAIT_BUFFER_TIMEOUT_MS "100" CACHE STRING "Timeout in milliseconds to wait before messages are dropped when input buffer is full") option(WITH_DLT_PKGCONFIG "Set to ON to generate pkgconfig .pc files" ON) option(WITH_DLT_CXX11_EXT "Set to ON to build C++11 extensions" OFF) option(WITH_DLT_COREDUMPHANDLER "EXPERIMENTAL! Set to ON to build src/core_dump_handler binaries. EXPERIMENTAL" OFF) option(WITH_DLT_LOGSTORAGE_CTRL_UDEV "PROTOTYPE! Set to ON to build logstorage control application with udev support" OFF) option(WITH_DLT_LOGSTORAGE_GZIP "Set to ON to build logstorage control application with gzip compression support" OFF) option(WITH_DLT_USE_IPv6 "Set to ON for IPv6 support" ON) option(WITH_DLT_KPI "Set to ON to build src/kpi binaries" OFF) option(WITH_DLT_FATAL_LOG_TRAP "Set to ON to enable DLT_LOG_FATAL trap(trigger segv inside dlt-user library)" OFF) option(WITH_UDP_CONNECTION "Set to ON to enable dlt UDP multicast SUPPORT" OFF) option(WITH_LIB_SHORT_VERSION "Set to ON to build library with only major number in version" OFF) option(WITH_DLT_DISABLE_MACRO "Set to ON to build code without Macro interface support" OFF) option(WITH_LEGACY_INCLUDE_PATH "Set to ON to add /dlt to include paths for the CMake config file, in addition to only " ON) option(WITH_EXTENDED_FILTERING "Set to OFF to build without extended filtering. Using json filter files is only supported for Linux based system with json-c and QNX." OFF) option(WITH_DLT_DAEMON_VSOCK_IPC "Set to ON to enable VSOCK support in daemon" OFF) option(WITH_DLT_LIB_VSOCK_IPC "Set to ON to enable VSOCK support in library (DLT_IPC is not used in library)" OFF) set(DLT_VSOCK_PORT "13490" CACHE STRING "VSOCK port number for logging traffic.") set(DLT_WRITEV_TIMEOUT_SEC "1" CACHE STRING "Set sec timeout for writev to prevent blocking indefinitely") set(DLT_WRITEV_TIMEOUT_USEC "0" CACHE STRING "Set usec timeout for writev to prevent blocking indefinitely") # RPM settings set(COVESA_RPM_RELEASE "1") # ${DLT_REVISION}") set(LICENSE "Mozilla Public License Version 2.0") # Build, project and include settings find_package(Threads REQUIRED) if(WITH_DLT_LOGSTORAGE_GZIP) set(ZLIB_LIBRARY "-lz") find_package(ZLIB 1.2.9 REQUIRED) elseif(WITH_DLT_COREDUMPHANDLER OR WITH_DLT_FILETRANSFER) set(ZLIB_LIBRARY "-lz") find_package(ZLIB REQUIRED) else() set(ZLIB_LIBRARY "") endif() if(WITH_DLT_DBUS) find_package(PkgConfig REQUIRED) pkg_check_modules(DBUS REQUIRED dbus-1) endif() include_directories( ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR}/include/dlt ${PROJECT_SOURCE_DIR}/include/dlt ${PROJECT_SOURCE_DIR}/src/shared ${PROJECT_SOURCE_DIR}/src/core_dump_handler ${PROJECT_SOURCE_DIR}/src/offlinelogstorage ${PROJECT_SOURCE_DIR}/src/lib ${PROJECT_SOURCE_DIR}/src/daemon ${PROJECT_SOURCE_DIR}/src/console ${PROJECT_SOURCE_DIR}/src/gateway ${PROJECT_SOURCE_DIR}/systemd/3rdparty ) add_definitions(-D_GNU_SOURCE) add_definitions(-DDLT_WRITEV_TIMEOUT_SEC=${DLT_WRITEV_TIMEOUT_SEC}) add_definitions(-DDLT_WRITEV_TIMEOUT_USEC=${DLT_WRITEV_TIMEOUT_USEC}) add_definitions(-DDLT_QNX_SLOG_ADAPTER_WAIT_BUFFER_TIMEOUT_MS=${DLT_QNX_SLOG_ADAPTER_WAIT_BUFFER_TIMEOUT_MS}) if(NOT DLT_IPC STREQUAL "UNIX_SOCKET" AND NOT DLT_IPC STREQUAL "FIFO") message(FATAL_ERROR "${DLT_IPC} is not a valid value for DLT_IPC") endif() add_definitions(-DDLT_DAEMON_USE_${DLT_IPC}_IPC) if(WITH_DLT_DAEMON_VSOCK_IPC) add_definitions(-DDLT_DAEMON_VSOCK_IPC_ENABLE) endif() if(NOT WITH_DLT_LIB_VSOCK_IPC) add_definitions(-DDLT_LIB_USE_${DLT_IPC}_IPC) else() add_definitions(-DDLT_LIB_USE_VSOCK_IPC) endif() if(WITH_DLT_DAEMON_VSOCK_IPC OR WITH_DLT_LIB_VSOCK_IPC) add_definitions(-DDLT_VSOCK_PORT=${DLT_VSOCK_PORT}) endif() if(NOT DLT_USER_IPC_PATH) set(DLT_USER_IPC_PATH "/tmp") endif() add_definitions(-DDLT_USER_IPC_PATH="${DLT_USER_IPC_PATH}") if(WITH_DLTTEST) add_definitions(-DDLT_TEST_ENABLE) endif() if(WITH_DLT_UNIT_TESTS) add_definitions(-DDLT_UNIT_TESTS) endif() if(WITH_DLT_SHM_ENABLE) add_definitions(-DDLT_SHM_ENABLE) endif() if(WITH_DLT_USE_IPv6) add_definitions(-DDLT_USE_IPv6) endif() if(WITH_DLT_QNX_SYSTEM AND NOT "${CMAKE_C_COMPILER}" MATCHES "nto-qnx|qcc|ntoaarch64-gcc|ntox86_64-gcc") message(FATAL_ERROR "Can only compile for QNX with a QNX compiler, but found '${CMAKE_C_COMPILER}'.") endif() if(WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK) add_definitions(-DWITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK) endif() if(WITH_DLT_LOGSTORAGE_GZIP) add_definitions(-DDLT_LOGSTORAGE_USE_GZIP) endif() if(WITH_GPROF) add_compile_options(-pg) endif() if(WITH_DLT_COVERAGE) add_definitions(-DWITH_DLT_COVERAGE) set(WITH_DLT_UNIT_TESTS ON) if(WITH_DLT_UNIT_TESTS) add_definitions(-DDLT_UNIT_TESTS) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") endif() add_compile_options( $<$:-std=gnu99> $<$:-std=gnu++14> -Wall -Wextra # -pedantic -Wno-variadic-macros -Wno-strict-aliasing ) if(WITH_DOC STREQUAL "OFF") set(PACKAGE_DOC "#") else() set(PACKAGE_DOC "") endif() if(BUILD_SHARED_LIBS) set(CMAKE_STATIC_LIB_PATH "") else() set(CMAKE_STATIC_LIB_PATH "-L\$\{libdir\}/static") endif() if(WITH_DLT_PKGCONFIG) configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.spec.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.spec) configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc @ONLY) install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT devel) endif() if(WITH_DLT_CXX11_EXT AND WITH_DLT_PKGCONFIG) configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-c++.pc.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-c++.pc @ONLY) install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-c++.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT devel) endif() set(CONFIGURATION_FILES_DIR ${CMAKE_INSTALL_FULL_SYSCONFDIR}) add_definitions(-DCONFIGURATION_FILES_DIR="${CONFIGURATION_FILES_DIR}") add_subdirectory(cmake) if(WITH_DLT_NETWORK_TRACE) # Message queue if(HAVE_MQUEUE_H AND HAVE_FUNC_MQOPEN AND HAVE_FUNC_MQCLOSE AND HAVE_FUNC_MQUNLINK AND HAVE_FUNC_MQSEND AND HAVE_FUNC_MQRECEIVE) add_definitions(-DDLT_NETWORK_TRACE_ENABLE) set(DLT_NETWORK_TRACE_ENABLE 1) else() message(STATUS "Disable network trace interface since message queue is not supported") endif() else() message(STATUS "Network trace interface disabled") endif() if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX OR WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_DLT_SYSTEM OR WITH_SYSTEMD_JOURNAL OR WITH_SYSTEMD_SOCKET_ACTIVATION) find_package(PkgConfig REQUIRED) execute_process(COMMAND pkg-config --modversion systemd OUTPUT_VARIABLE SYSTEMD_VERSION) string(REPLACE "\n" "" SYSTEMD_VERSION ${SYSTEMD_VERSION}) if(WITH_SYSTEMD) add_definitions(-DDLT_SYSTEMD_ENABLE) endif() if(WITH_SYSTEMD_WATCHDOG) add_definitions(-DDLT_SYSTEMD_WATCHDOG_ENABLE) endif() if(WITH_SYSTEMD_JOURNAL) add_definitions(-DDLT_SYSTEMD_JOURNAL_ENABLE) endif() if(WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX) add_definitions(-DDLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE) endif() if(WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_DLT_SYSTEM) add_definitions(-DDLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYTSTEM) endif() if(WITH_SYSTEMD_SOCKET_ACTIVATION) if(NOT DLT_IPC STREQUAL "UNIX_SOCKET") message(FATAL_ERROR "WITH_SYSTEMD_SOCKET_ACTIVATION is only supported for UNIX_SOCKET") endif() add_definitions(-DDLT_SYSTEM_SOCKET_ACTIVATION_ENABLE) endif() set(systemd_SRCS ${PROJECT_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c) set(SYSTEMD_UNITDIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system" CACHE PATH "Set directory to install systemd unit files") add_subdirectory(systemd) else() set(systemd_SRCS "") endif() if(WITH_DLT_LOGSTORAGE_CTRL_UDEV) add_definitions(-DDLT_LOGSTORAGE_CTRL_UDEV_ENABLE) endif() if(WITH_DLT_FATAL_LOG_TRAP) add_definitions(-DDLT_FATAL_LOG_RESET_ENABLE) endif() if(WITH_DLT_FILTER_BACKEND_PROP) add_definitions(-DHAS_PROPRIETARY_FILTER_BACKEND) endif() if(WITH_EXTENDED_FILTERING) if(("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") OR ("${CMAKE_SYSTEM_NAME}" MATCHES "Android")) find_package(PkgConfig REQUIRED) pkg_check_modules(JSON REQUIRED json-c) set(DLT_JSON_LIBRARY ${JSON_LIBRARIES}) elseif("${CMAKE_SYSTEM_NAME}" MATCHES "QNX") set(DLT_JSON_LIBRARY json) else() message(FATAL_ERROR "OS doesn't support extended filtering. Please build without cmake option '-DWITH_EXTENDED_FILTERING=OFF'") endif() add_definitions(-DEXTENDED_FILTERING) else() set(DLT_JSON_LIBRARY "") endif() if (WITH_DLT_LOG_LEVEL_APP_CONFIG) add_definitions(-DDLT_LOG_LEVEL_APP_CONFIG) endif() add_subdirectory(doc) add_subdirectory(src) add_subdirectory(include) add_subdirectory(testscripts) if(WITH_DLT_UNIT_TESTS) find_package(GTest) if(NOT GTEST_FOUND) add_subdirectory(googletest) endif() enable_testing() add_subdirectory(tests) endif() message(STATUS) message(STATUS "-------------------------------------------------------------------------------") message(STATUS "Build for Version ${PROJECT_VERSION} build ${DLT_REVISION} version state ${DLT_VERSION_STATE}") message(STATUS "WITH_SYSTEMD = ${WITH_SYSTEMD}") message(STATUS "WITH_SYSTEMD_WATCHDOG = ${WITH_SYSTEMD_WATCHDOG}") message(STATUS "WITH_SYSTEMD_JOURNAL = ${WITH_SYSTEMD_JOURNAL}") message(STATUS "WITH_DOC = ${WITH_DOC}") message(STATUS "WITH_MAN = ${WITH_MAN}") message(STATUS "WITH_DLT_ADAPTOR = ${WITH_DLT_ADAPTOR}") message(STATUS "WITH_DLT_ADAPTOR_UDP = ${WITH_DLT_ADAPTOR_UDP}") message(STATUS "WITH_DLT_CONSOLE = ${WITH_DLT_CONSOLE}") message(STATUS "WITH_DLT_CONSOLE_WO_CTRL = ${WITH_DLT_CONSOLE_WO_CTRL}") message(STATUS "WITH_DLT_CONSOLE_WO_SBTM = ${WITH_DLT_CONSOLE_WO_SBTM}") message(STATUS "WITH_DLT_EXAMPLES = ${WITH_DLT_EXAMPLES}") message(STATUS "WITH_DLT_SYSTEM = ${WITH_DLT_SYSTEM}") message(STATUS "WITH_DLT_FILETRANSFER = ${WITH_DLT_FILETRANSFER}") message(STATUS "WITH_DLT_DBUS = ${WITH_DLT_DBUS}") message(STATUS "WITH_DLT_TESTS = ${WITH_DLT_TESTS}") message(STATUS "WITH_DLT_UNIT_TESTS = ${WITH_DLT_UNIT_TESTS}") message(STATUS "WITH_DLT_COVERAGE = ${WITH_DLT_COVERAGE}") message(STATUS "WITH_DLT_SHM_ENABLE = ${WITH_DLT_SHM_ENABLE}") message(STATUS "WITH_DLTTEST = ${WITH_DLTTEST}") message(STATUS "WITH_DLT_PKGCONFIG = ${WITH_DLT_PKGCONFIG}") message(STATUS "WITH_DLT_CXX11_EXT = ${WITH_DLT_CXX11_EXT}") message(STATUS "WITH_DLT_COREDUMPHANDLER = ${WITH_DLT_COREDUMPHANDLER}") message(STATUS "WITH_DLT_KPI = ${WITH_DLT_KPI}") message(STATUS "WITH_DLT_FATAL_LOG_TRAP = ${WITH_DLT_FATAL_LOG_TRAP}") message(STATUS "WITH_CHECK_CONFIG_FILE = ${WITH_CHECK_CONFIG_FILE}") message(STATUS "WITH_TESTSCRIPTS = ${WITH_TESTSCRIPTS}") message(STATUS "WITH_GPROF = ${WITH_GPROF}") message(STATUS "WITH_DLT_USE_IPv6 = ${WITH_DLT_USE_IPv6}") message(STATUS "DLT_USER = ${DLT_USER}") message(STATUS "BUILD_SHARED_LIBS = ${BUILD_SHARED_LIBS}") message(STATUS "TARGET_CPU_NAME = ${TARGET_CPU_NAME}") if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL) message(STATUS "SYSTEMD_VERSION = ${SYSTEMD_VERSION}") message(STATUS "SYSTEMD_UNITDIR = ${SYSTEMD_UNITDIR}") message(STATUS "WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX = ${WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX}" ) message(STATUS "WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_DLT_SYSTEM = ${WITH_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_DLT_SYSTEM}" ) endif() message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR = ${CMAKE_HOST_SYSTEM_PROCESSOR}") message(STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}") message(STATUS "WITH_DLT_LOGSTORAGE_CTRL_UDEV = ${WITH_DLT_LOGSTORAGE_CTRL_UDEV}") message(STATUS "WITH_DLT_LOGSTORAGE_GZIP = ${WITH_DLT_LOGSTORAGE_GZIP}") message(STATUS "DLT_IPC = ${DLT_IPC}(Path: ${DLT_USER_IPC_PATH})") message(STATUS "WITH_DLT_DAEMON_VSOCK_IPC = ${WITH_DLT_DAEMON_VSOCK_IPC}") message(STATUS "WITH_DLT_LIB_VSOCK_IPC = ${WITH_DLT_LIB_VSOCK_IPC}") message(STATUS "DLT_VSOCK_PORT = ${DLT_VSOCK_PORT}") message(STATUS "WITH_UDP_CONNECTION = ${WITH_UDP_CONNECTION}") message(STATUS "WITH_DLT_QNX_SYSTEM = ${WITH_DLT_QNX_SYSTEM}") message(STATUS "WITH_DLT_NETWORK_TRACE = ${WITH_DLT_NETWORK_TRACE}") message(STATUS "WITH_LIB_SHORT_VERSION = ${WITH_LIB_SHORT_VERSION}") message(STATUS "WITH_LEGACY_INCLUDE_PATH = ${WITH_LEGACY_INCLUDE_PATH}") message(STATUS "WITH_EXTENDED_FILTERING = ${WITH_EXTENDED_FILTERING}") message(STATUS "WITH_DLT_DISABLE_MACRO = ${WITH_DLT_DISABLE_MACRO}") message(STATUS "WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK = ${WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK}" ) message(STATUS "WITH_DLT_LOG_LEVEL_APP_CONFIG = ${WITH_DLT_LOG_LEVEL_APP_CONFIG}" ) message(STATUS "Change a value with: cmake -D=") message(STATUS "-------------------------------------------------------------------------------") message(STATUS) dlt-daemon-2.18.10/COPYING000066400000000000000000000006441446635226000147560ustar00rootroot00000000000000 # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. dlt-daemon-2.18.10/LICENSE000066400000000000000000000405261446635226000147330ustar00rootroot00000000000000Mozilla Public License Version 2.0 ================================== 1. Definitions -------------- 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions -------------------------------- 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities ------------------- 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation --------------------------------------------------- If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination -------------- 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ************************************************************************ * * * 6. Disclaimer of Warranty * * ------------------------- * * * * Covered Software is provided under this License on an "as is" * * basis, without warranty of any kind, either expressed, implied, or * * statutory, including, without limitation, warranties that the * * Covered Software is free of defects, merchantable, fit for a * * particular purpose or non-infringing. The entire risk as to the * * quality and performance of the Covered Software is with You. * * Should any Covered Software prove defective in any respect, You * * (not any Contributor) assume the cost of any necessary servicing, * * repair, or correction. This disclaimer of warranty constitutes an * * essential part of this License. No use of any Covered Software is * * authorized under this License except under this disclaimer. * * * ************************************************************************ ************************************************************************ * * * 7. Limitation of Liability * * -------------------------- * * * * Under no circumstances and under no legal theory, whether tort * * (including negligence), contract, or otherwise, shall any * * Contributor, or anyone who distributes Covered Software as * * permitted above, be liable to You for any direct, indirect, * * special, incidental, or consequential damages of any character * * including, without limitation, damages for lost profits, loss of * * goodwill, work stoppage, computer failure or malfunction, or any * * and all other commercial damages or losses, even if such party * * shall have been informed of the possibility of such damages. This * * limitation of liability shall not apply to liability for death or * * personal injury resulting from such party's negligence to the * * extent applicable law prohibits such limitation. Some * * jurisdictions do not allow the exclusion or limitation of * * incidental or consequential damages, so this exclusion and * * limitation may not apply to You. * * * ************************************************************************ 8. Litigation ------------- Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous ---------------- This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License --------------------------- 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice ------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. dlt-daemon-2.18.10/README.md000066400000000000000000000266111446635226000152040ustar00rootroot00000000000000# Diagnostic Log and Trace [![Build Status](https://github.com/COVESA/dlt-daemon/actions/workflows/cmake-ctest.yml/badge.svg)]( https://github.com/COVESA/dlt-daemon/actions/workflows/cmake-ctest.yml) [![CodeQL](https://github.com/COVESA/dlt-daemon/actions/workflows/codeql-analysis.yml/badge.svg?branch=master)](https://github.com/COVESA/dlt-daemon/actions/workflows/codeql-analysis.yml) [![Page-build-deployment](https://github.com/COVESA/dlt-daemon/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/COVESA/dlt-daemon/actions/workflows/pages/pages-build-deployment) **Code coverage reports online** 📄 [LCOV - code coverage report](https://COVESA.github.io/dlt-daemon/dlt_lcov_report/index.html) # Diagnostic Log and Trace Welcome to COVESA Diagnostic Log and Trace (DLT). If you are familiar with DLT and want to know what's new, check the [Release Notes](ReleaseNotes.md). **New to DLT? Great! Welcome aboard.** We prepared a brief [overview](#overview) for you as well as some information on how to [get started](#get-started) immediately. After you made yourself familiar with the basic mechanics of DLT, you can [learn more](#learn-more) about advanced concepts and features. ## Overview COVESA DLT provides a log and trace interface, based on the standardised protocol specified in the [AUTOSAR standard 4 DLT](https://www.autosar.org/fileadmin/standards/R22-11/CP/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf). It is used by other COVESA components but can serve as logging framework for other applications without relation to COVESA. The most important terms and parts are depicted in the following figure. Please refer to [Glossary](doc/dlt_glossary.md) for a full overview over DLT-specific terms. ![alt text](doc/images/dlt_overview.png "DLT Overview") - A **DLT User** essentially is an application that serves its respective (not DLT-related) purpose and produces DLT log messages. It utilizes the DLT library to craft and transmit these messages. - The **DLT Library** provides a convenient API to DLT Users (i.e. applications) to create DLT log messages and hand them over to the DLT Daemon. If the latter is not avilable, the library will cache the messages in a ring buffer so they don't get lost immediately. - The **DLT Daemon** is the DLT communication interface of an ECU. It collects and buffers log messages from one or more DLT users running on the ECU and provides them to DLT clients upon their request. The daemon also accepts control messages from the clients to adjust the daemon's or the aplications' behaviour. - A **DLT Client** receives and consumes the log messages from DLT Users by fetching them from DLT Daemons. It may also issue control messages to control the behaviour of a DLT Daemon or its connected DLT Users. A DLT client can even transmit user-defined data to a DLT User through so-calles injection messages. This is only the simplest of all use cases that you will further pursue in the [Get Started](#get-started) section. Once you want to [learn more](#learn-more), you will find that the repository contains advanced features utilizing several adaptors and console utilities as well as test applications. ## Get Started In this section, you can learn how to [build and install](#build-and-install) DLT. Then you can choose to [run a DLT demo](#run-a-dlt-demo) setup or to start by [developing your own DLT-featured application](#develop-your-own-dlt-featured-application). ### Build and install The following packages need to be installed in order to be able to build and install DLT daemon: - cmake - zlib - dbus - json-c (only required for dlt-receives extended filtering) On Ubuntu those dependencies can be installed with the following command: ```bash sudo apt-get install cmake zlib1g-dev libdbus-glib-1-dev build-essential optional: sudo apt-get install libjson-c-dev # in case you want to use dlt-receives extended filtering ``` Then proceed to download DLT if you haven't already. We recommend cloning the repository, but downloading and extracting a zip-archive is fine as well. ```bash cd /path/to/workspace git clone https://github.com/COVESA/dlt-daemon.git ``` To build and install the DLT daemon, follow these steps: ```bash cd /path/to/workspace/dlt-daemon mkdir build cd build cmake .. make optional: sudo make install optional: sudo ldconfig # in case you executed make install ``` CMake accepts a plethora of [build options](doc/dlt_build_options.md) to configure the build to suit your needs. ### Run a DLT demo In case you haven't had a look at the brief [overview](#overview), now would be the perfect occasion to learn about the most important terms and to get an idea where data is buffered. Then go on with our guide on [how to set up a DLT demo setup](doc/dlt_demo_setup.md). ### Develop your own DLT-featured application Now that you have seen DLT in action, you probably want to develop your own applications using DLT. You will find everything you need in our ["DLT for Application Developers" guide](doc/dlt_for_developers.md). A hint: If you want to read the API documentation, you have to build it locally at the moment. The API documentation is generated with _doxygen_. To build it, run cmake with the ```-DWITH_DOC=ON``` option, e.g.: ```bash mkdir build cd build cmake -DWITH_DOC=ON .. make doc ``` ### Build DLT debian package To build the DLT debian package for your own purpose, follow these steps: ```bash dpkg-buildpackage -us -uc ``` ## Learn more Once you got your feet wet with developing your first application, you might want to learn more. Find out about DLT's [advanced topics](#advanced-topics), learn how to [configure, control and interface](#configure-control-and-interface) DLT or study its internals by checking out the [design specifications](./doc/dlt_design_specification.md). ### Advanced Topics The COVESA DLT implementation is capable of by far more than to "just" send log message. You will get an overview of advanced features in this section. Follow the links to learn more about the respective concept. | Document | Description | |----|----| | [Build Options](./doc/dlt_build_options.md) | The CMake build system provides a large amount of build options. They let you turn on or off certain features and provide alternative implementation details. | | [LogStorage](doc/dlt_offline_logstorage.md) | The DLT Daemon as well as the DLT libary provide buffers for caching log data during absence of a consumer. However, some use cases require to write large amounts of log message e.g. to mass storages for long term storage or because no other means of exfiltrating the log data is available. | | [MultiNode](doc/dlt_multinode.md) | A DLT Daemon can run as a gateway to connect multiple passive nodes. Each passive node has its owns DLT Applications and runs its own daemon. The gateway node connects to all of them, collects the logs and routes them to the DLT Client. | | [Extended Network Trace](doc/dlt_extended_network_trace.md) | Normal DLT messages are limited in size. To overcome this limitation the feature network trace message allows the user to send or truncate messages which would not fit into a normal DLT message. | | [DLT Filetransfer](doc/dlt_filetransfer.md) | Although not originally designed for this, files can be transmitted over DLT. A corresponding DLT Client (e.g. DLT Viewer) can receive and decode them accordingly. | | [DLT KPI](doc/dlt_kpi.md) | Valueable status information about the monitored system can be read via DLT as well. The information under `/proc` of the target system is at your hands easily. | | [DLT Core Dump Handler](/doc/dlt_cdh.md) | This tool collects and extracts debug information then utilize [DLT Filetransfer](doc/dlt_filetransfer.md) to transfer the information to client. | ### Configure, Control and Interface There is still lots to discover about DLT. If you turn on the generation of manpages with the cmake option ```-DWITH_MAN=ON``` you can learn how to configure DLT to exactly suit your needs, how to control the behvaiour of running instances and how to interface DLT with existing system through provided adaptors. The man pages are generated with *pandoc*, which also needs *asciidoc* as dependency. Build manpages (initally or because something changed) with e.g. ```bash mkdir build cd build cmake -DWITH_MAN=ON .. make generate_man ``` | Document | Description | |----|----| | *Configuration* || |[dlt-daemon(1)](doc/dlt-daemon.1.md) | How to start DLT-Daemon | |[dlt.conf(5)](doc/dlt.conf.5.md) | Configure the DLT framework to reflect your use case| | *Control running instances of DLT*|| |[dlt-receive(1)](doc/dlt-receive.1.md)| Receive DLT messages from daemon and print or store the log messages. | |[dlt-control(1)](doc/dlt-control.1.md)| Send control messages to daemon. | |[dlt-logstorage-ctrl(1)](doc/dlt-logstorage-ctrl.1.md)| Send a trigger to daemon to connect/disconnect certain logstorage device, or send a demand to sync data the internal buffer into logstorage file. | |[dlt-passive-node-ctrl(1)](doc/dlt-passive-node-ctrl.1.md)| Send a trigger to daemon to connect/disconnect passive daemon. | | *Interfacing DLT* || |[dlt-system(1)](doc/dlt-system.1.md) | DLT-System provides a way to directly access system logs via DLT | |[dlt-system.conf(5)](doc/dlt-system.conf.5.md) | Configure DLT-System | |[dlt-adaptor-stdin(1)](doc/dlt-adaptor-stdin.1.md)| Adaptor for forwarding input from stdin to daemon. | |[dlt-adaptor-udp(1)](doc/dlt-adaptor-udp.1.md)| Adaptor for forwarding received UDP messages to daemon. | |[dlt-convert(1)](doc/dlt-convert.1.md)| Convert DLT files into human readable format. | |[dlt-sortbytimestamp(1)](doc/dlt-sortbytimestamp.1.md)| Read log messages from DLT file, sort by timestamp, and store them again. | |[dlt-qnx-system(1)](doc/dlt-qnx-system.md) | Access system logs in QNX with DLT | ## Contribution Start working, best practice is to commit smaller, compilable pieces during the work that makes it easier to handle later on. If you want to commit your changes, create a [Pull Request](https://github.com/covesa/dlt-daemon/pulls) in Github. Please make sure to follow the [Rules for commit messages](https://at.projects.covesa.org/wiki/display/PROJ/Rules+for+Commit+Messages) ### Coding Rules This project is now using clang-format as replacement of uncrustify. For convenience, any code changes will be harmonized before commit by hooks/pre-commit. - Install clang-format - Install pre-commit script by: ```bash cp scripts/pre-commit.sample .git/hooks/pre-commit ``` - Configuration: .clang-format For reference to clang-format, you can check with: [Configurator](https://zed0.co.uk/clang-format-configurator/) ## Known issues List of open issues can be found on [Github](https://github.com/COVESA/dlt-daemon/issues) - DLT library: Usage of dlt\_user\_log\_write\_float64() and DLT\_FLOAT64() leads to "Illegal instruction (core dumped)" on ARM target. - DLT library: Nested calls to DLT\_LOG\_ ... are not supported, and will lead to a deadlock. - For Non linux platforms [eg: QNX] IPC supported is UNIX\_SOCKET. For Linux Platforms both IPC FIFO and UNIX\_SOCKET are supported ## Software/Hardware Developed and tested with Ubuntu Linux 16 64-bit / Intel PC ## License Full information on the license for this software is available in the "LICENSE" file. Full information on the license for the cityhash code is available in "COPYING" file in src/core\_dump\_handler/cityhash\_c. ## Contact Methner, Michael , Le Van, Khanh ![alt text](doc/images/covesa-logo.png "COVESA logo") dlt-daemon-2.18.10/ReleaseNotes.md000066400000000000000000001645041446635226000166440ustar00rootroot00000000000000# Diagnostic Log and Trace - Release Notes Back to [README.md](../README.md) ## Version 2.18.10 STABLE ## Changes ### 2.18.10 ## What's Changed * Update ReleaseNotes and version to v2.18.9 by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/468 * Update status badges on README.md by @michael-methner in https://github.com/COVESA/dlt-daemon/pull/467 * logstorage: Adds option to write logs in gzip format by @LiquidityC in https://github.com/COVESA/dlt-daemon/pull/442 * Re-Initialize internal logging in daemon mode only by @lvklevankhanh in https://github.com/COVESA/dlt-daemon/pull/459 * Remove use of DLT_LOG in signal handler by @michael-methner in https://github.com/COVESA/dlt-daemon/pull/472 * Update gtest_dlt_daemon_multiple_files_logging.cpp by @LocutusOfBorg in https://github.com/COVESA/dlt-daemon/pull/481 * Update AUTOSAR standard link by @lucafrance in https://github.com/COVESA/dlt-daemon/pull/480 * cmake: set version to 2.18.9 by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/478 * Fix macro code to use boolean value in while instruction (false) by @michael-methner in https://github.com/COVESA/dlt-daemon/pull/469 * dlt_user_shared: Add timeout to writev by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/385 * build: add static lib only if necessary by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/479 * Update CMakeLists.txt by @LocutusOfBorg in https://github.com/COVESA/dlt-daemon/pull/482 * watchdog: improve dlt watchdog by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/470 * log-level-config: add option to configure log levels by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/474 * gtest_dlt_daemon_gateway: dlt-daemon run without dlt_passive.conf file by @lti9hc in https://github.com/COVESA/dlt-daemon/pull/487 * dlt_unit_test: Fix and improve quality of unit tests by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/494 * dlt-qnx-system improvement by @lvklevankhanh in https://github.com/COVESA/dlt-daemon/pull/495 * gtest: Init submodule and update version by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/497 * dlt-qnx-system: prevent message loss in high load situations by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/490 * Fix compile error stringop-truncation with GCC 9.4 by @michael-methner in https://github.com/COVESA/dlt-daemon/pull/499 * Update README.md by @lvklevankhanh in https://github.com/COVESA/dlt-daemon/pull/503 * dlt-coverage: Add coverage report generator for dlt by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/501 * dlt-system: move journal reading to its own thread by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/471 * Switch from GENIVI to COVESA by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/511 * Update CMakeLists.txt: set required std version to gnu++14 by @LocutusOfBorg in https://github.com/COVESA/dlt-daemon/pull/504 * cmake: Policy CMP0115 set to OLD behavior for dlt-daemon with cmake >= 3.20 by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/510 * fix usage of pthread_cond_timedwait by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/491 * DLT Upstream for minor release by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/515 * cmake: disable network trace by @alexmohr in https://github.com/COVESA/dlt-daemon/pull/477 * doc: add COVESA logo image by @minminlittleshrimp in https://github.com/COVESA/dlt-daemon/pull/516 **Full Changelog**: https://github.com/COVESA/dlt-daemon/compare/v2.18.9...v2.18.10 ### 2.18.9 * dlt-user: fix crash with certain strings (#463) * dlt_multiple_files: remove superfluous mode bits and add header file to header list (#462) * Android: Add new feature in Android bp (#461) * cmake: remove duplicated option message (#454) * house-keeper: remove infinite wait (#438) * dlt-logd-converter: Fix getting log level from log msg (#456) * dlt-logd-converter: fixes android 12 compilation (#445) * logfile: exhance internal dlt logging by introducing size limits (#369) * This changes a mispatch from fcb676a7 to install the udp binary correctly. (#449) * Installs dlt.conf on android (#446) * dlt-connection: add socket timeout (#439) * Fix memory leak (#441) * Check for negative index in dlt_file_message (#437) * dlt-user: fix potential non closed socket in init/free (#435) * dlt-convert: Fix memory leak by calling dlt_file_free (#434) * dlt-user: Fix crashes in dlt_free during dlt_init (#362) * Update contacts and removed mailing lists (#431) * Updates for Coding Styles (#425) * gateway: Fix Node handling and ECUid checks (#429) * filetransfer: fix filesize divisible by blocksize case (#383) * client: Fix Get Log Info response conversion method (#422) * cmake: network trace enable toggle (#424) * dlt-system: Fix buffer overflow detection on 32bit targets (#398) * dlt-receive: set host interface and allow multiple udp multicast addresses (#420) * Fix for Resource and Memory Leak (#418) * dlt_daemon_client: Fix Control Msg ECUId comparison with active Gateway (#414) * Avoid memory corruption behind buffer wp in function dlt_getloginfo_conv_ascii_to_id (#411) * dlt_common: change output of message for log initialization (#412) * internal-logging: Fix issues with file logging (#378) * systemd: add support for socket activation via systemd (#401) * Update maintainer (#410) * dlt_daemon_client: Fix change loglevel of application (#408) * dlt_client:Block in connect() (#409) * dlt-gateway: Fix crash on invalid ip (#381) * Update dlt_for_developers.md (#405) * logstorage: Truncate ECUid in Logstorage filter to prevent crash (#402) * dlt_common.c: Change default logging_mode (#406) * dlt-daemon-connection: Start up even if not all bindings are valid (#380) * enforce-trace-limit: ContextLogLevel is now enforced in the daemon (#382) * automotive-dlt.pc: add the path to find the static library (#387) * systemd: install adaptor-udp service for adaptor=on (#393) * Fix handle returned value (#384) * README: Update link to github actions (#392) * Update for CI (#389) * Fix a double-free bug. (#376) * Issue-ID: make-adaptor-configurablecmake: Add option to enable each adaptor by itself (#364) * Fix the target name in documentation (#372) * cmake: Add options to enable/disable each dlt console tool (#363) * filetransfer: Fix getFileCreationDate2 stat check (#361) * tests: Deplicate unused files and variables (#359) * Fix DLT User/Client tests (#357) * lib: Correct VARI usage in dlt_user_log_write_uint (#356) * filetransfer: Return error if no free space (#354) * Support for Cygwin toolchain. (#351) * dlt-system: fix invalid free by removing unused TempDir (#350) * fix -Wformat issues reported by clang (#349) * Forcibly the severity level set (#346) * daemon: Do not exit when accept returns ECONNABORTED (#347) * dlt-system : fix invalid free with ConfigurationFileName (#342) * dlt-daemon: Only create directories if they do not exist yet (#340) * fixes compilation issue with clang (#339) * dlt-daemon: create sockets using "android way" (#333) * dlt-system: fix a libc buffer overflow detection on 32bit targets (#337) ### 2.18.8 * lib: Fix wrong type alert from lgtm * gtest_dlt_daemon_gateway: fix gtest build failed * lib: generate dlt library internal log file * tests: add stdlib to dlt_cpp_extension * dlt_user: Make dlt_init thread safe * remove clang-tidy analyzer warnings: incompatible pointer type * debian: improve debian build package * dlt-control-common: shutdown and close socket * dlt_common: improve function description * gtest: Bring-in changes * gtest: Rework WORKING_DIRECTORY * gtest: Correct data amount in gtest_dlt_common * cmake: Set empty to systemd_SRCS * gtest: Refactor tests/CMakeLists.txt * lib: Add SOCK_CLOEXEC to socket * daemon: Create parent directory for unix socket * cmake: Correct added subdirectories * console: Add cmake options for control and timestamp * tests: Adapt to DLT_DISABLE_MACRO * header: Adapt to DLT_DISABLE_MACRO * include: Refactor CMakeLists.txt * gtest: Change script name to gtest_dlt_daemon_offline_log.sh * daemon: Enable to use FIFO on QNX * tests: Add new test case with given buffer * tests: Enable macro disabling * lib: Add new interfaces with given buffer * Implemention of tests for the dlt-qnx-system module * lib: Add MaxFileSize handling * client: pthread_join for deinit * doc: update initial log level document * dlt-system: Fix memory leak in dlt-system config * dlt_common: remove duplicate stdbool header * dlt-control: Add option to config port * system: use signalfd for dlt-system * console: provides args option to enable send/receive serial header * fix malformed printf format strings (#295) * cmake: Set WITH_LEGACY_INCLUDE_PATH to ON as default (#334) * Make the legacy include path a CMake option (#332) * daemon: Call dlt_daemon_configuration_load() properly (#330) * dlt_user: Use pthread_setname_np() if available (#326) * libdlt: Add legacy include path in exported CMake config file (#327) * lib: Set TYLE to 1 for BOOL type (#320) * file-transfer: Abort file transfer if get serial number failed * dlt_user.c: fixing casting wrong type * dlt-sortbytimestamp: Remove duplicated conditional statements code * dlt-convert: Remove duplicated conditional statements code * doc: Minor fix in dlt_for_developers.md (#321) * dlt-control-common.c: Fix build failure due to out-of-bound write -Werror=stringop-truncation * Extend include path in *.pc file (#319) ### 2.18.7 * dlt_common: correct read/write position * Update document and fix conversion warning * dlt_common: Increment size after memcpy() * Using dlt_vlog in verbose option in dlt_client.c * dlt-logstorage-ctrl: Improve option force to sync * Do not use Cpack * Debian packaging * Update dlt-system.conf documentation * dlt_user: correct handling return value * Update dlt-system-syslog with IPv6 * Alternative solutions for json-c dependency * dlt-receive:Fix compiler warning * daemon: Improve signal handler for timers * dlt-doc:Fix generating HTML documentation and man pages * Apply uncrustify for src/daemon/* and src/lib/* * Update uncrustify * dlt-receive: Implemented gtest for extended filtering * dlt-receive: Enabled more filtering by using json filter files * dlt_receive: handle exception in signal handler. * dlt message header broken * Add missing string functions (#309) * gtest: Find system-provided external gtest (#301) * Make nonverbose mode non exclusive (#300) * Merge pull request from GHSA-7cqp-2hqj-mh3f * daemon: check the conf inputs * Export cmake config file (#289) * Better formatting of RAWD (#291) * fix bad funcion cast in dlt_user_log_out_error_handling (#294) * Contact information update (#299) * dlt-receive: Add option to configure port of dlt receive (#293) * Add verbose mode attribute handling (#292) * Resolving broken link in README (#297) * fscanf() uses dynamic formatting to prevent buffer overflow (#288) * Make dlt pipe only readable by user (#285) * dlt_client_main_loop running in an infinite loop restricts graceful exit of DLT Client code (#284) ### 2.18.6 * Update releaseNotes and version to v2.18.6 * doc: Limitation to SIGUSR1 usage on Android * gtest_dlt_common: fix seg fault when using memcpy(). * example: Added customization of CxtID and AppID * other: fix remaining conversion warnings * library: fix conversion warnings * tests: fix conversion warnings * daemon: fix conversion warnings * shared: fix conversion warnings * logstorage: fix conversion warnings * console :fix conversion warnings * gateway: fix compile warnings * readme: cpack document for debian package * CMakeList: implement cpack for debian package * dlt-receive: flush stdout buffer by signal * gtest: Include necessary header * doc: Update doc for the maintain logstorage loglevel implementation * logstorage: Implement general config to maintain logstorage loglevel * daemon: Correct order of runtime config load. * libdlt: Use SIGUSR1 for thread on Android * dlt-daemon: log levels are not controlled * dlt-daemon: complete logstorage path with '/' * libdlt: Use poll to avoid CPU high load * libdlt: Flush all data in atexit_handler * dlt-convert: replace system() by dlt_execute_command() * dlt_common: Execute system command using execvp * logstorage: snprintf return check * logstorage: Update unit test * logstorage: Add debug logs * logstorage: Modify rearranging file * logstorage: Handle wrap-around * libdlt: support short version * design doc: update spec for new environment variable * doc: update disable injection msg for developer * libdlt: disable injection msg via env var * doc: Rewrote the DLT user documentation. * daemon: Alternative of timerfd in QNX * bug-fix: fix invalid file descriptor check * dlt_user: fix invalid poll timeout * README: Switch from travis-ci.org to travis-ci.com * Add support for logging with VSOCK (#255) * Use dlt_defaults for dlt-logd-converter in Android.bp (#271) * dlt-control.c: return -1 on error (#259) * Check size of ring buffer (#269) * dlt_common: Fix buffer overflow in dlt_filter_load (#275) * dlt-daemon: Adds an option to disable injection mode (#266) * Add message length check * Init logd crash buffer * Avoid memory access errors with 4-chars context ids (#250) * dlt_client.c: remove misleading error message (#258) * Fix overflow for -d argument in dlt-example-user (#270) * dlt-daemon.c: exit early on error (#261) * Remove nonexistent file from Android.bp (#264) * dlt-control.c: initialize dltdata via struct literal (#257) * dlt-common.c: ensure null terminated string (#256) * Make it easier to use libdlt when building DLT as a CMake subproject (#254) * Simplify setting of CONFIGURATION_FILES_DIR in CMakeLists.txt (#247) * Create codeql-analysis.yml (#252) * Modify CMAKE_C_COMPILER check for QNX to accept "qcc" (#246) * dlt_offline: fix build failures with gcc-10 (#245) * Implement DLTClient for UDP multicast (#240) * Revert "dlt_offline: fix build failures with gcc-10" * dlt_offline: fix build failures with gcc-10 * sd-daemon.c: Fix build with newer glibc and musl libc * dlt_user.c: fix the lack of DLT_NETWORK_TRACE_ENABLE definition ### 2.18.5 * Update releaseNotes and version to v2.18.5 * slog2 adapter on QNX * Update gtest_dlt_all.sh to detect core dump * dlt-daemon.c: fix printf format %d to %ld that formats a long * doc/CMakeList.txt: replace dlt_design_specification.txt to .md * network trace: Fix macro usage * limit logspam in gateway on client overflow * Android.bp: fix dlt_user.h genrule * logstorage: Issue with more than 2 filters * remove unused feature * gtest_dlt_daemon_gateway: correct comparison operator syntax * set DLT_NETWORK_TRACE_ENABLE by cmakedefine * doc: Update dlt_offline_logstorage.md * UT: Fix segfault in logstorage test * logstorage: support all stragegies * update cmake VERSION variables * simplify and fix android version script * execute unittests with cmake * dlt_design_specification: update content * dlt_design_specification: convert from .txt to .md format * logstorage: fix syncbehaviour * daemon: Fix smoketest * unittest: Update according to API's changes * offline storage: Improvement log messages at bottom * common: Isolate FIFO/Unix socket * libdlt: Relocate dltFifoBaseDir setting * doc: md file for dlt_gateway.conf * network trace: Include necessary headers * network trace: Add mqueue verification * Unittest for new api * Remove duplicate definition of DLT_CONVERT_TEXTBUFSIZE * Improve performance of DLT file parsing * relocation dlt_check_envvar() and update dlt_init() functions * Redirect stdout to stderr * Unittest: Update testcase * gateway: Improvement of handling Gateway config * daemon: Avoid spamming message buffer overflow * gateway: Support infinite loop of retry * gateway: Configurable interval time * tests: remove unused zlib include * disable android services by default * logstorage: Add NULL check of IDs * snprintf ret > 0 is not always an error * fix some gcc9 compiler warnings * fix clang warnings about GNU stuff * android logd forwarder * fix gateway config element search * doc: update a note for logstorage with wildcard * daemon: logstorage with wildcards * Limit log messages on full buffer * Android: Enable Android build * logstorage: Filter section handling * doc: Logstorage non-verbose filter * correct errno usage in dlt_stop_threads * shared: Read DLT header until it's found * Use ssize_t for bytes_written * Fix dlt-sortbytimestamp * Remove DLT_PACKED redefinition guard in dlt_common.h * rename definition PACKED to DLT_PACKED * daemon: Remove empty line in daemon log * Revert "dlt_common: Fix buffer overflow in dlt_buffer_get (#215)" * FIX: prevent usage of uninitialized message queue handle * Add unit tests for new sized string functions * Add documentation for new sized string functions * Add macro wrappers for new sized string functions * Minor optimization * Add functions for writing strings with known sizes * Add helper function for writing strings with known sizes * Fixed empty internal message in dlt-daemon.c (#225) * common: Fix uint64 type (#217) * dlt_common: Fix buffer overflow in dlt_buffer_get (#215) * FIX: Check validity of `file` pointer before usage. * doc/dlt_for_developers.md: Fix wrong DLT include directive * Remove naming of variadic macro parameters * sys/poll.h: deprecate old sys/poll.h include header, now glibc/musl wants poll.h being included directly. This fixes a build failure on musl systems with strict c hardening flags * dlt-test-init-free: fix build failure with strict compiler flags, due to uint being undefined. This is actually an "int" type, looking at the test implementation * dlt_user.h: fix build when musl is the libc implementation, by adding a missing include for pthread_t reference: * dlt.conf: suppress the warnings udp multicast (#197) * dlt_daemon_socket: leave while socket binds fails * dlt_user: init DltContextData before use * dlt-daemon: fix resource leak * console: fix memleak of dlt-logstorage-list * BugFix: SEGFAULT when using AppArmor (#192) * Fix compiler warnings: pointer of type ‘void *’ used in arithmetic (#196) * Change the DLT_CHECK_RCV_DATA_SIZE macro to an internal function (#191) * Fix a potential memory leak in file transfer (#126) * Provide DLT_GET_APPID macro (#187) (#188) * dlt-offline-trace: fix bug and hardcode (#174) (#186) * Avoided Seg fault in dlt_message_payload (#179) (#181) * Improvement: Make ZLib dependency optional (#182) * fix the dlt offline trace file name creation (#178) * libdlt: fix memory leak * Removed unused headers(epoll) in UDP connection * Fix: Propper usage of LoggingMode: "uncrustification" * Fix: Propper usage of LoggingMode in ".../dlt-runtime.cfg" * libdlt: reattachment and improvement in dlt thread (#171) * dlt-system: Call tzset before localtime_r (#165) * Update cmakelist, fix build due to copy-paste error (#170) * Bugfix: dlt-system-journal * Proper setup and error checking of pthread_create * udp: Disable WITH_UDP_CONNECTION as default * doxygen improvement * doc: Modify markdown doc generation * doc: Update dlt_for_developers.md * cmake improvement for Logstorage console * cmake add component for libdlt.so * parser: Change maximum number of config section * common: Remove unused structure * dlt_common: Use defined macro * libdlt: calculate resend buffer memory * lib: Disable extended header in non verbose mode by env var * shm: Resend dlt msg when client connect * lib: Remove else nothing * network trace: Do not allow DLT usage in forked child * lib: Assign fd after it's closed * console: Add get sw version control msg * console: Tool to merge multiple DLT files * dlt-test: Add message length option * Add user custom timestamp interface ### 2.18.4 * Update ReleaseNotes and version to v2.18.4 * dlt-daemon: correct errno usage * dlt-daemon: fix bug binding invalid ipv6 address as default * Add option in dlt.conf for bindAddress to specific IPs (#130) * protocol: Remove non supported user service ID (#159) * libdlt: truncate the log message if it is too long (#156) (#157) * UDP Multicast implementation (#155) * doc: Remove unused images * daemon: fix compile error with DLT_IPC="UNIX_SOCKET" (#153) * using POSIX shared memory APIs (#90) (#151) * Revert "Add option in dlt.conf for bindAddress to specific IPs (#130)" * Add option to set owner group of daemon FIFO (#122) * Add option in dlt.conf for bindAddress to specific IPs (#130) * dlt-system-journal: fixed localtime compile error * Correct sa findings * logstorage: fix compile error * doxygen: Align variable for apid and ctid * doxygen: Remove licence * doxygen: Get rid of warnings * doc: Use pandoc to generate HTML from markdown * doc: Improve README.md * doc: Create missing markdown documents * doc: Documentation update * cmake: Allow build as a subproject (#145) * fix config path for dlt-dbus * define DLT_PATH_MAX for max path buffer length * cmake-improvements (#135) * libdlt: Use posix nanosleep (#144) * doc: Improve markdown documents * doc: Improve dlt_for_developers.md * fix the warning of strncat size * fix warning of self assign * dlt-convert: fix warning of wrong conversion * Travis: Run Travis on Xenial 16.04 * Travis: Modify install package * cleanup: Use dlt_vlog() * Fix alerts from lgtm * lgtm: Add code analysis platform * dlt-test: Improve context ID * dlt-test: Add options * libdlt: Remove commented out code * Remove dlt_forward_msg * libdlt: compare dlt_ll_ts to NULL * network trace: Define package ID macro * daemon: Loop for client fds * daemon: Remove bytes_sent * daemon: Don't remove unregistered context * daemon: Don't assign fd after free * test: Add manual interruption in dlt-test-stress * gtest: Logstorage unit test update * Logstorage: Correct behavior in sync message cache * Logstorage: Sync behavior bug fix * Logstorage: Fix write msg cache ### 2.18.3 * Update ReleaseNotes and version to v2.18.3 * Travis CI: Run unit test (#132) * libdlt: Fix compiler warnings * Unit test: Fix compiler warnings * Unit test fix * Do not install systemd service files for binaries that are not built (#129) * lib: unlock buffer on termination * dlt-receive: Fix crash without arguments * dlt-control: Bug fix for broken get log info * Logging: Error message modification * dlt-daemon: fix internal logging to file after daemonize * Offline logstorage: Fix storage handle NULL check during cleanup * Fix compiler warnings * POSIX: Replace usleep with nanosleep * unix socket: IPC code isolation * lib: daemon: Fix sem lock potential issue * socket: Remove unnecessary header * dlt-daemon: unlink application socket * ipc: close socket if connect failed ### 2.18.2 * Update ReleaseNotes and version to v2.18.2 * Size of Resend buffer less than or equal to DLT_USER_BUF_MAX_SIZE res… (#116) * Fixed memory leak when receiving network traces of 0xFFFF length * Contact information update (#118) * lib: Add mq_close/mq_unlink conditions * doc: Do not allow DLT usage in forked child (#95) * doc: Raise an awareness of log level sync * dlt_offline_logstorage: fix multiple file creation error (#85, #94) * doc: Fix PANDOC_TOOL condition * Travis CI: Fix link in README.md (#106, #108) ### 2.18.1 * doc: Move all man pages to markdown files (#102) * Fix linking problem with tests when systemd enabled (#103) * libdlt: Do not allow DLT usage in forked child (#95) * Travis CI: build with systemd enabled (#97) * Make dlt-convert more responsive when watching a file * Travis CI: fix - add new line to .travis.yml * Build and test status added * Add the Travis CI script ### 2.18.0 * fix broken/missing links in documentation * CMake: Set default configuration * Code beautification using uncrustify * Documentation update * dlt-daemon: Output current number of connections as default * Remove unnecessary reference to zlib in .pc file * Cleanup of unit test fixes * gtest: Modification to offline logstorage * libdlt: Add error handling * exit DLT daemon if /dev/null open fails during fork * Improvement - use dup2 in place of dup in daemon fork * Remove one-instance-lock mechanism * daemon: Add exit trigger * UnitTest: Updates * Made socket send reliable * lib: socket: Flush all data before closing socket * buffer: Code cleanup * buffer: Improve logging * Removed log level change callback notification while context register done with ll_ts API * Logging: avoided missing of log level change callback * Injection: New callback with private data Added new injection callback with private data as argument * Fixed compiler error with previous commit * Dynamic allocation of msg buffer * cmake: systemd: fix hardcoded user in dlt-dbus.service (Issue #36) * rename #define STATIC to DLT_STATIC * Use poll in the dlt-daemon for POSIX compliance * dlt-client: logging: Extended the receiver buffer size * dlt-control: update get log info * Protocol: DLT Service ID Enum instead of defines * Gateway Improvements * Log storage - Updates (#82) * Fflush stdout in the intenal logger (#81) * dlt-daemon: per ECU list of user information (#80) * Add dlt-sortbytimestamp utility plus documentation (#73) * Fix compiler warning PR #77 * Fix compilation with glibc 2.28 (#77) * Fix gcc 8 build (#74) * dlt-daemon: fixed linked-list element remove (#71) * Update dlt_user.c (#66) * dlt-daemon: Fix no state transition to BUFFER state (#65) * file parser: Replace hash functions with list (#67) * libdlt: Avoid busy loop in error case of mq_receive() (#59) * dlt-daemon: Output signal number at exit (#68) * dlt-daemon: Improve error logging on accept() failure (#69) * dlt-daemon: Avoid to output duplicated application registration message (#63) * dlt-daemon: Not output Context un-/registration DLT message by default (#62) * dlt-daemon: Continue to send log level / connection status even if error occurs (#61) * IPC: Unix socket added (#43) * Introduce controlling entire system trace status feature from dlt-control (#57) * dlt-daemon: Lower log level of logs not to output unintentional warning (#58) * dlt-daemon: Fix infinite loop on set log level using wildcards (#55) * dlt-daemon: Fix repeated output of marker message (#54) * dlt-control: Fix Setting default trace status issue (#53) * Fix ForceContextLogLevelAndTraceStatus handling in dlt_daemon_client.c (#50) * minor compiler warning gcc 7.x (#30) * improve error reporting in dlt_daemon_socket (#41) * Fix SEGV dlt_offline_trace.c (#32) * fix PR #26 socket_sendreliable data_send update * Prevention for occasional corrupted messages (#26) * README: Update contact information ### 2.17.0 * Fix for initialization of buffer settings in DLT user library. * fix various memory leaks * some-minor-fixes * Minor fixes: corrected typo in CMakeLists.txt - WTIH_DLT_ADAPTOR, removed character from merge * Data stuck in receiver buffer when dlt_daemon_user_send_log_level() fails * Update dlt_user.h * Add short explanation for DLT log level * Prevent buffer overflow for mount point path in dlt_logstorage_open_log_file * journald adaptor: test with sudo privileges * cmake: fix unit tests compilation with systemd * Input parameter check & Error message modification * Tell cmake to use [README.md](README.md) instead of README to fix doc generation * dlt-system-process-handling: fix warning * dlt_daemon_connection_types: fix build warnings * Updated README * dlt-adaptor-udp, dlt-adaptor-stdin: implement get of verbosity level from input * Added Description in dlt-system.conf * dlt-client: fix dlt_client_cleanup memory handling * CMake Option: Trigger segmentation fault in case of FATAL log * Daemon connection handling fixes * Added Description in dlt-system.conf * dlt-client: fix dlt_client_cleanup memory handling * CMake Option: Trigger segmentation fault in case of FATAL log * dlt-daemon: Fix use after free potential issue * Event handling: Fix connection destroy bug * Remove duplicate README * daemon: check payload length before cast to struct * Added missing build steps to INSTALL * pkg-config: fix library directory. ### 2.16.0 * doc: Documenatation update * Systemd-journal-test: Add WITH_DLT_UNIT_TEST flag when building sources * Smoketest: Offline Logstorage * Smoketest: Multinode * Unit Test: Event handling * Provision to test static function * Unit Test: MultiNode * Unit Test: Multinode Unit test preparation script * CMake: Add option to build unit test binaries * dlt-system-filetransfer: fix bug caused by malloc assert * Environment variables for library ringbuffer * DLT_PTR macro: Improve implementation and function API added * MultiNode: Specify config file location in dlt.conf * dlt-client: Use correct port on connect * process user message: Fix bound handling * dlt-system-filetransfer: Fix compiler warnings * Remove C99 style comments in include directory * Dlt-Receive: Use PRIxxx macros for printf variables * Offine logstorage: Remove duplicated source file * Fix: Memory for context description is not freed * Fix: dlt-daemon overwrites ECU ID even if user log message already has the ECU ID that is not default value * Add: Configuration of option of get log info response during context registration * Add: Configuration of daemon FIFO size * Fix: Handle of /tmp/dlt never reset if dlt-daemon is killed during output user buffer * Add: Debug log for file transfer feature of dlt-system. * Fix: Segfault in checking buffer usage * Fix: File Transfer acceleration * Fix: File name is broken when file is transferred on 64 bit OS. * Fix: Memory leak issue in dlt-dbus * Add dlt_user_is_logLevel_enabled API * [README.md](README.md) formatting changes * Adding GitHub flavored markdown for README. * Fixed D-Bus tracing not working anymore * Fixed not working default log level. * Fixed not returning the correct number of lost messages at exit. * dlt-daemon: Free DltDaemon structure on exit * CommonControl: Fix for commands not working with unix socket * CommonControl: Unix socket path and ecuid parsing for control applications * dlt-control: Provision to control entire system log level * DLT_PTR: User macro to print pointers * dlt-daemon: Fix user log handler return value * dlt-daemon: Connection activation rework * dlt-daemon: receiver rework * Fix connection handling of serial interface * Offline trace: Make search more precise * MultiNode: Add support for mandatory configurations * MultiNode: Add support for SerialHeader conf * MultiNode: Add support for port configuration * MultiNode: Send control messages after connection * MultiNode: Send serialheader if specified in dlt.conf * Offline logstorage: On Demand triggering for syncing Logstorage cache and support long options * Offline logstorage: Fix to resetting of Syncbehavior value * Offline logstorage: Refactor filter storage functionality to support general properties * Offline logstorage: Fixed extended header size check condition * Offline logstorage: Fix invalid filter configuration handling * Added abnormal unit tests to check DLT_RETURN_USER_BUFFER_FULL * DLT_RETURN_USER_BUFFER_FULL is returned when user buffer full * Revert truncation of string or raw block ### 2.15.0 * Fixed bug with truncation of string or raw block * Updated man pages and README * Truncate string or raw block if length exceeds maximum message length * Fixed a bug in dlt-system filetransfer * dlt-system filetransfer waits for a client to connect * Fixed compilation for older versions of gcc * Fixed core pattern to use correct dlt-cdh install path * Fixed CMakeLists to build core dump handler * Replaced Type=Simple with Type=simple in cmkake files for .service files * Added systemd install dir parameter * Added option to specify user for non-root processes * Added dlt-kpi component to log various KPI information to dlt-daemon ### 2.14.1 * MultiNode: Reconnection after connection loss * Fix injection message handling ### 2.14.0 * Fix fork()-handler in libdlt * Set default log-levels in dlt.conf * Fix register context before application is registered * Fixed compiler warnings about format issues in dlt-system-journal.c by replacing llu with PRIu64 * Make IP version compile time configurable * Implemented Dlt MultiNode to connect DLT Daemons running on different operating systems * Daemon shutdown: fixed memory leaks and missing removal of created sockets * DltLogstorage: reduce writing to internal storage device as much as possible * Control appliction to support offline log storage trigger implemented * Offline log storage to internal and external devices implemented * Unix socket control interface implemented * Parse INI files for Offline Logstorage, Multinode and potentially other DLT extensions implmented * Linking library systemd instead of systemd-journal systemd-id128 if systemd version >= 209 * Event handling has been reworked in order to use epoll and restructure the code * Fixed include paths in dlt_user_manual.txt and dlt_cheatsheet.txt ### 2.13.0 * Added core dump handler code * Purged all warnings for -Wall -Wextra with gcc 4.9.1 * Set DLT_USER_BUF_MAX_SIZE to 1390 to prepare UDP message transport * dlt-test-client and dlt-test-filetransfer have global failed test counter so they can return 1 on failure * Using DLT_USER_BUF_MAX_SIZE in dlt-test-client.c truncated check * Set path to /usr/local/share/ in dlt-test-filetransfer.c * Added programme to test repeated calls of dlt_init and dlt_free * DLT daemon improvement - dlt_init()-check * DLT daemon improvement - parameter value range check * Adapt unit tests to check for enum return values * Changed C version to gnu99 and C++ version to gnu++0x * Fixed bug in INTERNAL-mode connection * Use the best possible timestamp for all system journal entries * Make timeout in at_exit handler configurable * Allow multiple instances of dlt-daemon * Add C++ extension which uses variadic templates from C++ 11 (disabled by default) * Allow registration of contexts before application is registered * Add env-var to set initial log-levels * Allow applications to fork() * Fixed file permissions * Added offline logstorage implementation which can be used instead of the already available offline trace functionality ### 2.12.1 * Removed all trailing whitespaces * Replaced all tabs with spaces in all files in include folder * Rework of addon tests filtetransfer, systemd-journal and system-logger * Fix compilation warnings and possible misuse of snprint * Rework of unit tests * Fix installation paths on x86_64 (lib64 instead of lib) ### 2.12.0 * Added unit and functional tests * Fixed copyright doxygen comments * Updated license headers to latest COVESA license policy * Renamed and cleanup further files to comply with licensing requirements * dlt-control: Check for return values * dlt-daemon: Explicitly set the default loggingLevel to LOG_INFO * dlt-daemon: Explicitly set the default loggingMode to DLT_LOG_TO_CONSOLE * Fixing MIN and MAX defines for base integer types * Unified all line endings to UNIX style * Adding gtest framework v1.7.0 * Remove absolute installation paths so that DLT can be installed at any location (not only "/usr"). * Add Service ID Last entry to avoid further modifications in dependent code * Change daemon state handling to have all traces in online trace even when offline trace is active * Fix content of offline trace * Open daemon connection in atexit function * Change loglevel of Request-Resend message * Fix daemon state handling with offline trace * Fix watchdog timeout * Reworked internal output * DLT MISRA conform changes * Made zlib dependent on DLT_SYSTEM * Doxygen paths are now determined by CMake. * Add the IPv6 support * Workaround for duplicated log messages in offline trace file issue * Fix PREFIX. Works now with the default PREFIX (/usr/local/) and with the user PREFIX (e.g. /temp/test_with_pref). PREFIX Fix for filetransfer directory (PREFIX/share/) * Fixed typo in include guard * Resolves BUG-206: Install prefix should be configurable * Adding support for new macros to the daemon. New macros: DLT_HEX8(VAR) 8bits variable displayed in hexadecimal with "0x" prefix DLT_HEX16(VAR) 16bits displayed in hexadecimal with "0x" prefix DLT_HEX32(VAR) 32bits displayed in hexadecimal with "0x" prefix DLT_HEX64(VAR) 64bits displayed in hexadecimal with "0x" prefix DLT_BIN8(VAR) 8bits variable displayed in binary with "0b" prefix DLT_BIN16(VAR) 16bits variable displayed in binary with "0b" prefix * Fixed network trace test * Fix dlt_user_log_write_start_id return value * Added new API to send marker message from application. * New Callback function in DLT library, called when log level of context is changed ### 2.11.0 * New macros for Format of Hex and Binary. * Enable dbus trace when adaptor starts up. * Added configuration of dbus filter. * Fixed segmented messages arguments to standard. * First implementation of DLT DBus adapter. * DLT_CSTRING implementation non verbose mode. * Added new examples which can be manually build against DLt library. * Send ECU Id if enabled and added library API to change. * Send timestamp can be disabled by new API. * Send session/process id by default and add configuration API. * Send extended header in non verbose mode by default and add new API to change setting. * Make daemon buffer size configurable ### 2.10.0 * Bug 184 - /tmp/dltpipes directory does not exist before dlt-daemon is started, logging disabled * Updated authors information. * Fixed missing variable declaration when systemd not enabled. * Fixed: all possible malloc, sprintf and strcpy problems * Fixed: Creation of dltpipes directory is too late. * Cygwin port: cygwin patch, signal handling patch and cppcheck and install lib dll to correct location on Windows. * Fixed compiler warnings with 32Bit gcc compiler. * Fixed: Fixed offline trace and new send functions issues * Fixed: Bug 172 - DLT system crashes because of wrong journald adaptor implementation * DLT Common API Wrapper. * Removed dlt_free from example and test applications, already called from exit handler. * Fixed missing dlt_receiver_remove in dlt_daemon_process_user_xxx functions. * Use LIB_SUFFIX as lib installation path. * Fixed serial port not working anymore. * Added log output of created socket/port In init phase 2 - socket creation * Defined return value for dlt_message_read(). * Cleanup of send return values.Further cleanup of send restructure. * Moved daemon client functions to new source file. * Centralised send function to client.Introduced connection state to dlt daemon. * Removed check of double registration of contexts in user library, already checked by daemon. * When using DLT in console mode on a 64-bit machine, timestamps are corrupted due to an address of a 32-bit value being cast to a 64-bit pointer. * Bug 3 - Cmake does not check for zlib for dlt-daemon compilation. * Added new control message timezone. * Fixed deadlock after wrong merge.. * Fix potential buffer overflow in offline trace. * Fix deadlock in dlt_user_log_reattach_to_daemon(void). * Fixed possible crash when runtime configurations files are corrupted. * Environement variables added to configure internal logging in library. * Reduce Timeout between filetransfer packets. * Close socket when send fails. * Replace threads by timing fds for ecu version, timing packets and watchdog. * Added conntection info and unregister context control messages. * Configurable Timeout on send. * Added further checks to dlt_buffer. * atexit handler fix. * Add threadnames to libdlt threads. * Security fix on DLT pipes. * Reduce usage of SEM_LOCK in application library and reset pointers. * Fix: Systemd Journal Adapter provides corrupted output. * Fix: Install Example service file only when example enabled ### 2.9.1 * Implementation of command line tool dlt-control. * Fix file transfer bug. * Bug 44 - Don't print "Buffer full" message from DLT daemon for each trace. * Yocto fix in build builds. * Fixed: security issue in dlt-system-shell regarding strncpy. * Fixed: Security Issue by Command Injection in DLT System. * systemd/CMakeLists: Remove SYSTEMD_CONFIGURATIONS_FILES_DIR existance check. * Bug 85 - Include of dlt.h leads to compiler warning. * Bug 84 - Adding utf8 support to dlt-daemon, dlt-viewer. Modified patch, originally provided by Stefan Vacek. * systemd journal support added. * spec file does not package man files when cmake is run with -DWITH_DOC=OFF * added length check for paths of files to be transferred * Semaphores and Pointer passing insteasd by value and otehr coverity issue fixes * Fixed several issues in DLT filetransfer. * added creation date and a simple hash on the file name for to improve the uniqueness of getFileSerialNumber * modified filetransfer to be more robust in restarting transfers * Remove dangling DLT_SEM_FREE from dlt_user_queue_resend * Unifed ECU version sending functions * Refinements due to problems reported by static code analysis * Spec file does no more package man files when cmake is run with -DWITH_DOC=OFF * Made the APID strings in dlt-test-multi-process counting from 00-99 * Added creation date and a simple hash on the file name for to improve the uniqueness of getFileSerialNumber * File Transfer: improved robustness in case of restarted ECU/dlt-system with interrupted transfers ### 2.9.0 * Changed documentation and man pages into asciidoc format. * Increased buffer sizes for DLT user library and DLT daemon * [GDLT-120]: truncated and Segmented network tracing * [GDLT-137]: Automatically try resending of user buffer after FIFO full * [GSWD-85]: Added authors file ### 2.8.0 * [GDLT-115]: Encapsulate user macros * Fix register app and register context was not stored in buffer when FIFO is full. Other controll messages still not saved in buffer. * Create new fifo only when same application registers with different pid.' * Do not register appliction again, if already registered. * Fixed filetransfer not checking buffer fill level. ### 2.7.0 * [GDLT-24] Fixing compiler warnings * [GDLT-94] Optional sending periodic software version messages. See man pages for more informations * [GENDLT-26] Check for description length sanity * [GENDLT-24] Crash on invalid injection message fixed * [GDLT-93] Add -Wextra flags for compilation Fixed all the warnings that * [GDLT-90] Optional: systemd watchdog concept in dlt-system and dlt-daemon * [GDLT-67] Re-implemented dlt-system. Read full commit message for more information ### 2.6.2 * [GDLT-89] Fixed daemon doesn't sent the persistent log level * [GDLT-88] Fixed wrong initalization order using offline trace function ### 2.6.1 * Add _GNU_SOURCE Definition to be able to use O_CLOEXEC * Added important SEM_FREE in the daemon and closing fd in the filetransfer * [GDLT-3] Fixed missing semaphore around dlt_buffer_push3 * [GDLT-86] Fixed dlt_free uses absolute file path /tmp and not DLT_USER_DEFINE define * [D4099] Check for duplicate file handles, and clean them up if found * [GDLT-85] Pipes opened multiple times for the same application pid fixed * [GDLT-82] Child process inherits file descriptors openend by their parent fixed * [GDLT-84] Instead of calling the injection callback, store a pointer to it and the required parameter data fixed * [GDLT-70] Check for malloc failures and return errors where applicable * [GDLT-47] Avoid discarding old contexts if no new memory can be allocate * [GDLT-69] Fixed bug in dlt-test-multi-process shares context between threads ### 2.6.0 * [GDLT-75] Use old style directory check on startup * [GENDLT-21] Move mcnt from DltContextData to DltContext * [GENDLT-15] Fixes to previous integrations from review * [GENDLT-15] Safe re-allocations for databuffer * [GENDLT-15] use the correct TEXTBUFSIZE * [GENDLT-15] Optimize usege of strlen. Improved log level handling * [GENDLT-15] Avoid buffer overrun with snprintf() * [GENDLT-15] Check return value of dlt_user_log_write_start(_id) correctly * [GENDLT-15] Reduce the number of applications if allocation fails * [GENDLT-15] Make dlt_user_log_write_start inline * [GENDLT-15] Improve errore checking in dlt_user_log_write_start_id * [GENDLT-15] Use databussersize to avoid reallocations * [GENDLT-15] Rename buffer size constant to avoid confusion * [GENDLT-15] Better error handling when writing to FIFO * [GENDLT-15] Remove duplicate msg initialization. * [GENDLT-15] Optimize away multiple uses of strlen for one check * [GDLT-4] Improve queue handling, allow for other messages while transferring a large file * [GDLT-4] Limit maximum file queue to 256 files * [GDLT-4] First working version of inotify for file transfer * [GDLT-2] First test for filetransfer change * [GDLT-2] Change to gzip wrapper format. Change file signature creation to account for file size, as inode number maybe duplicate when deleting and creating new files * [GDLT-2] Fix bug while reading the options * [GDLT-2] Allow for enabling/disabling compression for the separate directories * [GDLT-2] Check if the file is already compressed * [GDLT-2] Link with libz, fix a typo * [GDLT-2] zlib based compression for dlt-system * Cleaned some warnings generated from removing stale old code ### 2.5.2 * Change to Mozilla Public License Version 2.0 ### 2.5.1 * Fixed bug with comparinson between signed and unsigned integer and protection for a buffer overflow. * Modified library for new test cases to corrupt data - related to the bug fix for testing signed and unsigned integer * [GENDLT-20] Fixed bug to use old cmake version for copy file * Replaced dlt-test-filetransfer-image.png with an own created image * [GENDLT-21] Fixed bug: Message Counter (MCNT) should be increased but is always 0 ### 2.5.0 * [GDLT-53] Man pages installation included * .cproject and .project file for Eclipse included * Update of doxygen documentation and generation * Rework of root CMake project file, e.g. structure and compile options * [GENDLT-16] Create variable in dlt-system.conf to configure the timeout of the filetransfer * [GDLT-37] Extend automated test tools for parallel process/threads tests * [GSW-138] API Extension to resend the log messages in the user buffer * [GDLT-36] Prefixing of dlt_version.h fixed * [GDLT-31] Tracefile content stored different under Ubuntu 64 bit version compared to Ubuntu/Win 32 Bit version fixed * [GDLT-35] Compile warnings fixed * [GSW-137] Wrong include gives error on compailing against dlt fixed ### 2.4.2 * Added dynamic increasable ringbuffers to user lib and daemon. * dlt-system filetransfer now recovers when file is deleted during filetransfer. * Added check of file size when starting and deleting files during filetransfer * Added chekc of shm buffer availability when push to shm * Create abstraction of shm buffer management. * Fixed buffer overflow problem in buffer library. * Disabled share memory by default - disabled completely shared memory if not enabled. ### 2.4.1 * Added dynamic increasable ringbuffers to user lib and dlt-daemon. * Created abstraction of shm buffer management. * dlt-system filetransfer now recovers when file is deleted during filetransfer. * Added check of file size when starting and deleting files during filetransfer. * Added check of shm buffer availability when push to shm. ### 2.4.1 * Added internal logging facility to stdout, syslog or local file, configurable in configuration file. * Added deamonise and signal handlers to dlt-system. * Added manual pages. * Added new API dlt_check_library_version() function. * Fifo or SHM mode can be changed by compiler switch. * Replaced SHM implementation. * Fixed shared memory problem in DLT library during startup, if application is started before daemon. * Fixed syslog adapter in dlt-system. * Reverted API changes in dlt_register_app() function. * DLT user library does not set the stack size of the receiver thread anymore. ### 2.4.0 * New config files /etc/dlt.conf and /etc/dlt-system.conf must be adapted to the needs * New DLT user lib API dlt_get_log_state() to get DLT client state * New DLT user lib API to manage flow control (needed for bulk data logging) * New DLT user lib API dlt_set_log_mode() to enable/disable internal/external trace * New application dlt-system (filtransfer, proc file system logger,syslog udp adapter included) * [GSW-66] File transfer over DLT. * [GSW-43] Performance improvement for bulk data over DLT. * [GSW-61] Replace command line parameter by configuration file * [GSW-13] Support for keep-alive messages as configuration parameter * [GSW-60] Extended offline DLT Trace memory handling. * Removed filter implementation ### 2.3.0 * [GSW-16] Systemd configuration for syslog to DLT dapater * [GSW-62] DLT Library version check * [GSW-28] Directory where persistent data is stored is not configurable * [GSW-59] Statically allocated large array * Added init script for Ubuntu * Optional adding of gprof compile flags * sprintf with float64 fails on ARM platform; disabled this function on QRM platform. ### 2.2.0 * Moved build process completely to cmake * Added commandline parameter -u to set ring buffer size * Reduced cpu consumption needed by applications using DLT library * Increased default ringbuffer size to 10024 bytes * Changed delay in receiver routine to 100ms ### 2.1.0 * DLT Viewer (QT) * New dlt viewer (QT-based) implementated * Moved to seperate project, see extra Release Notes for DLT Viewer (QT) * DLT Viewer (WX) - Deprecated * Old dlt viewer (WX) is removed now from package generation * Moved to seperate project * Removed filtering of messages during writing to a file * DLT library: * Functions dlt_file_read_raw() and dlt_file_read_header_raw() added * Added support for raw messages in nonverbose mode * Injection tables are now dynamically allocated * Contexts are now dynamically allocated * Added seperate file for platform float types (dlt_float_types.h) and used this types. Attention: This file must be adapted to each target platform. * Removed signal handlers from dlt_user.c; SIGPIPE signal is ignored; atexit() handler still exists * Function dlt_forward_msg() added * DLT daemon: * Small optimization in get_log_info() for one searched application with one searched context, which is existing in the context table of the dlt daemon * Optional syncing to serial header added * Support for keep-alive messages, realized as seperate thread * General: * Combined dlt-test-user-multi and dlt-test-many to dlt-test-stress * Extended dlt-test-client * Added stress test3 to dlt-test-stress * Added help to dlt-test-stress, printed if no test was selected * Added dlt-test-internal * Removed plugin support from dlt_receive and dlt_convert * Extended documentation * dlt viewer (wx): Fixed minor bug, it's possible now to compile the dlt viewer (wx) again under mingw under Windows * DLT test programs: Fixed minor bug in dlt-test-user, test3f: Wrong counter was used * Removed DLT_LOG calls in injection functions due to problems (application hangs) ### 2.0.5 * DLT viewer: * The default log level is now shown, if already known * Renamed Filter->New.. to Filter->Delete all filter * Enhanced performance * DLT library: * On crash or termination of application using the DLT library, the registered context and application IDs are removed properly (and are deregistered from DLT daemon) * dlt_register_context_ll_ts() and Macro therefore added * dlt_message_payload() has now additional type DLT_OUTPUT_ASCII_LIMITED * dlt_message_header_flags() added * DLT daemon: * Support for dlt_register_context_ll_ts() added * Enhanced support for get_log_info (all modes, 1 app all contexts, 1 app 1 context, all apps all contexts) * Added -r option, for automatic sending context information to dlt client; if no client connection is available, this information is stored in history buffer in dlt daemon * Several internal performance optimizations: * dlt_daemon_context_find(), dlt_daemon_application_find(): Now O(log n) instead O(n) * Several functions optimized * Unnecessary functions removed * General: * Moved definition of struct DltUser from dlt_user_private.h to dlt_user.h * dlt.h includes now dlt_common.h * Extended dlt-test-user and dlt-test-client applications * DLT daemon/DLT library: Fixed bug in Filter Delete * DLT daemon: Fixed bug in dlt daemon which leads to a crash, when starting/stoping application, then sending new log level to context of this (now not running) application. * DLT daemon: Fixed bug in unregister application * DLT daemon: Fixed bug in reattach to daemon * DLT library: Fixed bug in send function * DLT viewer: Fixed bug in set default log level ### 2.0.4 * License has changed from ADRLPD to ADRLRM * DLT viewer: * Support for non-verbose mode (as FIBEX plugin) * DLT library: * Support for non-verbose mode (as FIBEX plugin) * dlt_message_print_* functions added * Semaphore calls added to enable multi-threading * Changed injection interface from direct usage to callback * Requested log level and trace status is set immediately in dlt_set_application_ll_ts_limit() * Implemented receiver thread in DLT library (used for setting of log level/trace status and for injection handling) * Added signal-handler and atexit-handler for cleanup (calls dlt_free()) * General: * Added implementation of clientlib and testclient for Windows * Both adaptors sends now log messages with log level DLT_LOG_INFO * Multi-threading example in src/tests/dlt-test-user-multi added * DLT viewer: Right mouse button for loading plugin descriptions (MOST-/Fibex-XML File) is now working (also in Windows) * DLT library: Fixed bug in dlt_print_mixed_string() * DLT library: Fixed bug in dlt_daemon_contexts_get_next_con_id() * DLT daemon: dlt_daemon_process_user_message_unregister_application() also removes now all corresponding contexts * DLT daemon: Added security check to dlt_daemon_control_get_log_info() in order to avoid crash which occured under special circumstances * DLT daemon: Register app now opens the connection to the DLT library, unregister app closes the connection (was before in register context) * Added -lrt to package config file * Resolved dependency from dlt_client.h to dlt_common.h -> dlt_common.h is now public ### 2.0.3 * DLT viewer: * Reduced load if idle * Modified behaviour of settings in dlt-viewer * Always open tmpfile in dlt-viewer if nothing other is specified * File->Clear added * DLT daemon: * Added several checks within code * DLT library: * Added several checks within code * Enhanced local print modes: a environment variable now can be used to control local print mode: Variable: DLT_LOCAL_PRINT_MODE Values : "AUTOMATIC" (local print only, if dlt-daemon connection is not available at startup of program using DLT library) "FORCE_ON" (always do local print) "FORCE_OFF" (never do local print) * A client library for writing console client applications (Linux) is now available. dlt-receiver and dlt-test-client uses this new library code * General: * Added seperate file for DltMostMessageHeader type * Added seperate file for DLT protocol values * Relaxed checks for passing trace messages to plugin handler * Tested and improved MOST plugin * Support for float (32 Bit) and double (64 Bit) values * Code fragments for winclientlib and wintestclient added * DLT library: Fixed bug in DLT_IMPORT_CONTEXT * DLT library: Fixed bug in dlt_plugin_print() and dlt_most_payload() * DLT daemon and library: Fixed bug in handling of description strings * DLT viewer: Fixed bug in RMB Click for loading plugin description * General: Fixed parsing and printing of MOST messages * Several small bugs fixed ### 2.0.2 * DLT viewer: * Showing timestamp * Compiles now with MS Visual C++ * Support for loading multiple descriptions of plugins is now possible (*) * Plugin description can be loaded individually by Right-mouse-button (*) * DLT daemon: * Overflow message is now stored in history buffer, if necessary * DLT library: * Ring-buffer for injection messages implemented * History Buffer for Startup + Overflow implemented * Setting of maximum logged log level/trace status for application triggered by application is now possible * Optional local output of Log message is now possible * General: * Support for ARTIS Box implemented (all, without GUI) * Support for timestamp in standardheader extras added * Support for ECU ID in standardheader extras added; this value can be overwritten by the DLT daemon * DLT viewer: * Store and load application and context description fixed * Fixed crash on termination of Windows version * DLT console utilities: * Fixed printing of filter ids * General: * Big Endian/Little Endian support tested and fixed * Fixed writing and reading of locally created dlt files * Several smaller bugs fixed ### 2.0.1 * Full support for serial connection between DLT daemon and DLT Viewer * Several small bugs fixed in DLT Viewer ### 2.0.0 * Initial Release of new DLT daemon Version 2 including the new DLT Client DLT Viewer * Initial Release dlt-daemon-2.18.10/automotive-dlt-c++.pc.in000066400000000000000000000003221446635226000201700ustar00rootroot00000000000000exec_prefix=@CMAKE_INSTALL_PREFIX@ includedir=${exec_prefix}/include Name: DLT C++ Description: Diagnostic Log and Trace C++ extensions Version: @PROJECT_VERSION@ Requires: automotive-dlt Cflags: -std=gnu++0x dlt-daemon-2.18.10/automotive-dlt-config.cmake.in000066400000000000000000000016151446635226000215510ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2021, Martin Willers # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # Config file for the Genivi::dlt package. # This file exports the Genivi::dlt CMake target which should be passed to the # target_link_libraries command. # # In addition, the following variable is defined: # @PROJECT_NAME@_FOUND - TRUE if headers and library were found include(CMakeFindDependencyMacro) find_dependency(Threads) @PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") check_required_components(@PROJECT_NAME@) dlt-daemon-2.18.10/automotive-dlt.pc.in000066400000000000000000000015001446635226000176210ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${exec_prefix}/include Name: DLT Description: Diagnostic Log and Trace Version: @PROJECT_VERSION@ Requires: Libs: -L${libdir} @CMAKE_STATIC_LIB_PATH@ -ldlt -lrt -lpthread @ZLIB_LIBRARY@ Cflags: -I${includedir}/dlt -I${includedir} -DDLT_@PROJECT_VERSION_MAJOR@_@PROJECT_VERSION_MINOR@ dlt-daemon-2.18.10/automotive-dlt.spec.in000066400000000000000000000072501446635226000201610ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### Name: @PROJECT_NAME@ Version: @PROJECT_VERSION@ Release: @COVESA_RPM_RELEASE@ Summary: %{name} - Diagnostic Log and Trace Group: System Environment/Base Vendor: BMW Group AG License: @LICENSE@ Source0: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: pkg-configure BuildRequires: cmake %description This component provides a standardised log and trace interface, based on the standardised protocol specified in the AUTOSAR standard 4.0 DLT. This component can be used by COVESA components and other applications as logging facility providing - the DLT shared library - the DLT daemon, including startup scripts - the DLT daemon adaptors - the DLT client console utilities - the DLT test applications %package doc Summary: %{name} - Diagnostic Log and Trace: Documentation Group: Documentation %description doc This component provides the documentation for %{name}. %package devel Summary: %{name} - Diagnostic Log and Trace: Development files Group: Development/Libraries Requires: %{name} = %{version}-%{release} Provides: pkgconfig(%{name}) %description devel This component provides the development libraries and includes for %{name}. %package c++-devel Summary: %{name} - Diagnostic Log and Trace: Development files Group: Development/Libraries Requires: %{name} = %{version}-%{release}-devel Provides: pkgconfig(%{name}-c++) %description c++devel This component adds a C++ extension for %{name}. %prep %setup -q %build rm -rf build mkdir -p build cd build #../configure --host=@HOST_TYPE@ --prefix=%{_prefix} #make cmake .. -DCMAKE_INSTALL_PREFIX=/usr make %install rm -rf $RPM_BUILD_ROOT cd build mkdir -p $RPM_BUILD_ROOT%{_bindir} make install DESTDIR=$RPM_BUILD_ROOT #/usr/bin/install -c -m 755 testscripts/Meego/dlt-daemon $RPM_BUILD_ROOT/etc/init.d %pre %post /sbin/ldconfig %postun /sbin/ldconfig %clean rm -rf $RPM_BUILD_ROOT %files #/etc/init.d/dlt-daemon /etc/dlt-system.conf /etc/dlt.conf /usr/share/dlt-filetransfer/dlt-test-filetransfer-file /usr/share/dlt-filetransfer/dlt-test-filetransfer-image.png %{_libdir}/libdlt.so.@PROJECT_VERSION_MAJOR@ %{_libdir}/libdlt.so.@PROJECT_VERSION@ %{_libdir}/libdlt.so %{_bindir}/dlt-system %{_bindir}/dlt-convert %{_bindir}/dlt-sortbytimestamp %{_bindir}/dlt-receive %{_bindir}/dlt-adaptor-stdin %{_bindir}/dlt-adaptor-udp %{_bindir}/dlt-test-client %{_bindir}/dlt-test-user %{_bindir}/dlt-test-stress %{_bindir}/dlt-test-stress-client %{_bindir}/dlt-test-stress-user %{_bindir}/dlt-test-filetransfer %{_bindir}/dlt-test-multi-process %{_bindir}/dlt-test-multi-process-client %attr(0755,root,root) %{_bindir}/dlt-daemon %{_bindir}/dlt-example-user %{_bindir}/dlt-example-user-func %{_bindir}/dlt-example-filetransfer %files doc @PACKAGE_DOC@%{_mandir}/man1/dlt-convert.1.gz @PACKAGE_DOC@%{_mandir}/man1/dlt-sortbytimestamp.1.gz @PACKAGE_DOC@%{_mandir}/man1/dlt-daemon.1.gz @PACKAGE_DOC@%{_mandir}/man1/dlt-receive.1.gz @PACKAGE_DOC@%{_mandir}/man1/dlt-system.1.gz @PACKAGE_DOC@%{_mandir}/man5/dlt-system.conf.5.gz @PACKAGE_DOC@%{_mandir}/man5/dlt.conf.5.gz %files devel %{_includedir}/dlt/*.h %{_libdir}/pkgconfig/@PROJECT_NAME@.pc %files c++-devel %{_includedir}/dlt/*.hpp %{_libdir}/pkgconfig/@PROJECT_NAME@-c++.pc dlt-daemon-2.18.10/cmake/000077500000000000000000000000001446635226000147775ustar00rootroot00000000000000dlt-daemon-2.18.10/cmake/CMakeLists.txt000066400000000000000000000102111446635226000175320ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # Run CheckIncludeFiles and CheckFunctionExists include(TestBigEndian) TEST_BIG_ENDIAN( DLT_BIGENDIAN ) if( DLT_BIGENDIAN ) add_definitions( -DBYTE_ORDER=BIG_ENDIAN ) else ( DLT_BIGENDIAN ) add_definitions( -DBYTE_ORDER=LITTLE_ENDIAN ) endif ( DLT_BIGENDIAN ) INCLUDE(CheckIncludeFiles) CHECK_INCLUDE_FILES( arpa/inet.h HAVE_ARPAINET_H) CHECK_INCLUDE_FILES( fcntl.h HAVE_FCNTL_H) CHECK_INCLUDE_FILES( float.h HAVE_FLOAT_H) CHECK_INCLUDE_FILES( limits.h HAVE_LIMITS_H) CHECK_INCLUDE_FILES( netdb.h HAVE_NETDB_H) CHECK_INCLUDE_FILES( netinet/in.h HAVE_NETINETIN_H) CHECK_INCLUDE_FILES( stddef.h HAVE_STDDEF_H) CHECK_INCLUDE_FILES( stdint.h HAVE_STDINT_H) CHECK_INCLUDE_FILES( stdlib.h HAVE_STDLIB_H) CHECK_INCLUDE_FILES( string.h HAVE_STRING_H) CHECK_INCLUDE_FILES( sys/ioctl.h HAVE_SYSIOCTL_H) CHECK_INCLUDE_FILES( sys/socket.h HAVE_SYSSOCKET_H) CHECK_INCLUDE_FILES( sys/time.h HAVE_SYSTIME_H) if( WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD ) set(CMAKE_REQUIRED_INCLUDES "${PROJECT_SOURCE_DIR}/systemd/3rdparty/") CHECK_INCLUDE_FILES( sd-daemon.h HAVE_SYSTEMD_H) endif ( WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD ) CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES( sys/ipc.h HAVE_SYSIPC_H) CHECK_INCLUDE_FILES( netdb.h HAVE_NETDB_H) CHECK_INCLUDE_FILES( ctype.h HAVE_CTYPE_H) CHECK_INCLUDE_FILES( signal.h HAVE_SIGNAL_H) CHECK_INCLUDE_FILES( syslog.h HAVE_SYSLOG_H) CHECK_INCLUDE_FILES( sys/stat.h HAVE_SYSSTAT_H) CHECK_INCLUDE_FILES( linux/stat.h HAVE_LINUXSTAT_H) CHECK_INCLUDE_FILES( sys/uio.h HAVE_SYSUIO_H) CHECK_INCLUDE_FILES( termios.h HAVE_TERMIOS_H) CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES( mqueue.h HAVE_MQUEUE_H) INCLUDE(CheckFunctionExists) CHECK_FUNCTION_EXISTS( clock_gettime HAVE_FUNC_CLOCKGETTIME) CHECK_FUNCTION_EXISTS( floor HAVE_FUNC_FLOOR) CHECK_FUNCTION_EXISTS( fork HAVE_FUNC_FORK) CHECK_FUNCTION_EXISTS( gethostbyname HAVE_FUNC_GETHOSTBYNAME) CHECK_FUNCTION_EXISTS( gettimeofday HAVE_FUNC_GETTIMEBYDAY) CHECK_FUNCTION_EXISTS( inet_ntoa HAVE_FUNC_INETNTOA) CHECK_FUNCTION_EXISTS( malloc HAVE_FUNC_MALLOC) CHECK_FUNCTION_EXISTS( memmove HAVE_FUNC_MEMMOVE) CHECK_FUNCTION_EXISTS( memset HAVE_FUNC_MEMSET) CHECK_FUNCTION_EXISTS( mkfifo HAVE_FUNC_MKFIFO) CHECK_FUNCTION_EXISTS( select HAVE_FUNC_SELECT) CHECK_FUNCTION_EXISTS( socket HAVE_FUNC_SOCKET) CHECK_FUNCTION_EXISTS( strchr HAVE_FUNC_STRCHR) CHECK_FUNCTION_EXISTS( strerror HAVE_FUNC_STRERROR) CHECK_FUNCTION_EXISTS( strstr HAVE_FUNC_STRSTR) CHECK_FUNCTION_EXISTS( strtol HAVE_FUNC_STRTOL) # Message queue find_library(RT_LIBRARY rt) if(RT_LIBRARY) include(CheckLibraryExists) CHECK_LIBRARY_EXISTS( ${RT_LIBRARY} mq_open mqueue.h HAVE_FUNC_MQOPEN) CHECK_LIBRARY_EXISTS( ${RT_LIBRARY} mq_close mqueue.h HAVE_FUNC_MQCLOSE) CHECK_LIBRARY_EXISTS( ${RT_LIBRARY} mq_unlink mqueue.h HAVE_FUNC_MQUNLINK) CHECK_LIBRARY_EXISTS( ${RT_LIBRARY} mq_send mqueue.h HAVE_FUNC_MQSEND) CHECK_LIBRARY_EXISTS( ${RT_LIBRARY} mq_receive mqueue.h HAVE_FUNC_MQRECEIVE) else() CHECK_FUNCTION_EXISTS( mq_open HAVE_FUNC_MQOPEN) CHECK_FUNCTION_EXISTS( mq_close HAVE_FUNC_MQCLOSE) CHECK_FUNCTION_EXISTS( mq_unlink HAVE_FUNC_MQUNLINK) CHECK_FUNCTION_EXISTS( mq_send HAVE_FUNC_MQSEND) CHECK_FUNCTION_EXISTS( mq_receive HAVE_FUNC_MQRECEIVE) endif() if(CMAKE_THREAD_LIBS_INIT) CHECK_LIBRARY_EXISTS(${CMAKE_THREAD_LIBS_INIT} pthread_setname_np pthread.h HAVE_FUNC_PTHREAD_SETNAME_NP) else(CMAKE_THREAD_LIBS_INIT) CHECK_FUNCTION_EXISTS(pthread_setname_np HAVE_FUNC_PTHREAD_SETNAME_NP) endif(CMAKE_THREAD_LIBS_INIT) if(WITH_CHECK_CONFIG_FILE) configure_file(${PROJECT_SOURCE_DIR}/cmake/config.h.cmake ${PROJECT_BINARY_DIR}/include/dlt/config.h) endif(WITH_CHECK_CONFIG_FILE) configure_file(${PROJECT_SOURCE_DIR}/cmake/dlt_version.h.cmake ${PROJECT_BINARY_DIR}/include/dlt/dlt_version.h @ONLY) dlt-daemon-2.18.10/cmake/config.h.cmake000066400000000000000000000037071446635226000175030ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ // DO NOT EDIT! GENERATED AUTOMATICALLY! // cmakedefine01 sets #define [0|1] if variable is defined in cmake // variable is set by CHECK_INCLUDE_FILES and CHECK_FUNCTION_EXISTS #cmakedefine01 HAVE_SYSTEMD_H #cmakedefine01 HAVE_ARPAINET_H #cmakedefine01 HAVE_FCNTL_H #cmakedefine01 HAVE_FLOAT_H #cmakedefine01 HAVE_LIMITS_H #cmakedefine01 HAVE_NETDB_H #cmakedefine01 HAVE_NETINETIN_H #cmakedefine01 HAVE_STDDEF_H #cmakedefine01 HAVE_STDINT_H #cmakedefine01 HAVE_STDLIB_H #cmakedefine01 HAVE_STRING_H #cmakedefine01 HAVE_STRINGS_H #cmakedefine01 HAVE_SYSIOCTL_H #cmakedefine01 HAVE_SYSSOCKET_H #cmakedefine01 HAVE_SYSTIME_H #cmakedefine01 HAVE_SYSTEMD_H #cmakedefine01 HAVE_UNISTD_H #cmakedefine01 HAVE_SYSIPC_H #cmakedefine01 HAVE_NETDB_H #cmakedefine01 HAVE_CTYPE_H #cmakedefine01 HAVE_SIGNAL_H #cmakedefine01 HAVE_SYSLOG_H #cmakedefine01 HAVE_SYSSTAT_H #cmakedefine01 HAVE_LINUXSTAT_H #cmakedefine01 HAVE_SYSUIO_H #cmakedefine01 HAVE_TERMIOS_H #cmakedefine01 HAVE_UNISTD_H #cmakedefine01 HAVE_FUNC_BZERO #cmakedefine01 HAVE_FUNC_CLOCKGETTIME #cmakedefine01 HAVE_FUNC_FLOOR #cmakedefine01 HAVE_FUNC_FORK #cmakedefine01 HAVE_FUNC_GETHOSTBYNAME #cmakedefine01 HAVE_FUNC_GETTIMEBYDAY #cmakedefine01 HAVE_FUNC_INETNTOA #cmakedefine01 HAVE_FUNC_MALLOC #cmakedefine01 HAVE_FUNC_MEMMOVE #cmakedefine01 HAVE_FUNC_MEMSET #cmakedefine01 HAVE_FUNC_MKFIFO #cmakedefine01 HAVE_FUNC_SELECT #cmakedefine01 HAVE_FUNC_SOCKET #cmakedefine01 HAVE_FUNC_STRCHR #cmakedefine01 HAVE_FUNC_STRERROR #cmakedefine01 HAVE_FUNC_STRSTR #cmakedefine01 HAVE_FUNC_STRTOL dlt-daemon-2.18.10/cmake/dlt_version.h.cmake000066400000000000000000000025031446635226000205570ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /* DO NOT EDIT! GENERATED AUTOMATICALLY! */ #ifndef __DLT_VERSION_H_ #define __DLT_VERSION_H_ #define _DLT_PACKAGE_VERSION_STATE "@DLT_VERSION_STATE@" #define _DLT_PACKAGE_VERSION "@PROJECT_VERSION@" #define _DLT_PACKAGE_MAJOR_VERSION "@PROJECT_VERSION_MAJOR@" #define _DLT_PACKAGE_MINOR_VERSION "@PROJECT_VERSION_MINOR@" #define _DLT_PACKAGE_PATCH_LEVEL "@PROJECT_VERSION_PATCH@" #define _DLT_PACKAGE_REVISION "@DLT_REVISION@" #ifdef DLT_SYSTEMD_ENABLE #define _DLT_SYSTEMD_ENABLE "+SYSTEMD" #else #define _DLT_SYSTEMD_ENABLE "-SYSTEMD" #endif #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE #define _DLT_SYSTEMD_WATCHDOG_ENABLE "+SYSTEMD_WATCHDOG" #else #define _DLT_SYSTEMD_WATCHDOG_ENABLE "-SYSTEMD_WATCHDOG" #endif #ifdef DLT_TEST_ENABLE #define _DLT_TEST_ENABLE "+TEST" #else #define _DLT_TEST_ENABLE "-TEST" #endif #ifdef DLT_SHM_ENABLE #define _DLT_SHM_ENABLE "+SHM" #else #define _DLT_SHM_ENABLE "-SHM" #endif #endif dlt-daemon-2.18.10/debian/000077500000000000000000000000001446635226000151415ustar00rootroot00000000000000dlt-daemon-2.18.10/debian/changelog000066400000000000000000000002371446635226000170150ustar00rootroot00000000000000dlt-daemon (2.18.7) unstable; urgency=low * Initial release -- Bui Nguyen Quoc Thanh Mon, 11 Jan 2021 09:00:00 +0800 dlt-daemon-2.18.10/debian/compat000066400000000000000000000000011446635226000163360ustar00rootroot000000000000009dlt-daemon-2.18.10/debian/control000066400000000000000000000042561446635226000165530ustar00rootroot00000000000000Source: dlt-daemon Section: utils Priority: extra Maintainer: Advanced Driver Information Technology Build-Depends: debhelper (>= 9), cmake, pandoc, libdbus-1-dev, pkg-config, zlib1g-dev, libsystemd-dev Package: dlt-daemon Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Diagnostic Log and Trace daemon This component provides a standardised log and trace interface, based on the standardised protocol specified in the AUTOSAR standard 4.0 DLT. This component can be used by COVESA components and other applications as logging facility providing . The DLT daemon is the central component in COVESA, which gathers all logs and traces from the DLT user applications. The logs and traces are stored optionally directly in a file in the ECU. The DLT daemon forwards all logs and traces to a connected DLT client. The DLT client can send control messages to the daemon, e.g. to set individual log levels of applications and contexts or get the list of applications and contexts registered in the DLT daemon. Package: libdlt2 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Diagnostic Log and Trace daemon - Library DLT library is used by apps that need to log to a DLT daemon directly and by apps that want to read logs from DLT daemon. Package: libdlt-dev Section: libdevel Architecture: any Depends: libdlt2 Description: Diagnostic Log and Trace daemon - Headers DLT library is used by apps that need to log to a DLT daemon directly and by apps that want to read logs from DLT daemon. This package provides development files. Package: dlt-tools Architecture: any Depends: libdlt2, ${shlibs:Depends}, ${misc:Depends} Description: Diagnostic Log and Trace daemon - Tools This package includes tools to connect to and experiment with DLT daemon. Most usefully this includes 'dlt-receive' to connect to a (remote) DLT server and save all logs to a DLT file and 'dlt-system' that injects system logs into the DLT server. Package: dlt-examples Architecture: any Depends: libdlt2, ${shlibs:Depends}, ${misc:Depends} Description: Diagnostic Log and Trace daemon - Examples This package includes example binaries to demonstrate several use cases. dlt-daemon-2.18.10/debian/copyright000066400000000000000000000003061446635226000170730ustar00rootroot00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: dlt-daemon Source: https://github.com/COVESA/dlt-daemon Files: * Copyright: BMW AG et al License: MPL-2.0+ dlt-daemon-2.18.10/debian/dlt-daemon.install000066400000000000000000000004511446635226000205550ustar00rootroot00000000000000INSTALL_PREFIX_PATH/bin/dlt-daemon INSTALL_PREFIX_PATH/etc/dlt_gateway.conf INSTALL_PREFIX_PATH/etc/dlt.conf INSTALL_PREFIX_PATH/share/man/man1/dlt-daemon.1.gz INSTALL_PREFIX_PATH/share/man/man5/dlt.conf.5.gz INSTALL_PREFIX_PATH/share/man/man5/dlt_gateway.conf.5.gz lib/systemd/system/dlt.service dlt-daemon-2.18.10/debian/dlt-examples.install000066400000000000000000000000461446635226000211300ustar00rootroot00000000000000INSTALL_PREFIX_PATH/bin/dlt-example-* dlt-daemon-2.18.10/debian/dlt-tools.install000066400000000000000000000015021446635226000204500ustar00rootroot00000000000000INSTALL_PREFIX_PATH/etc/dlt-dbus.conf INSTALL_PREFIX_PATH/etc/dlt-kpi.conf INSTALL_PREFIX_PATH/etc/dlt-system.conf INSTALL_PREFIX_PATH/bin/dlt-adaptor-* INSTALL_PREFIX_PATH/bin/dlt-control INSTALL_PREFIX_PATH/bin/dlt-convert INSTALL_PREFIX_PATH/bin/dlt-dbus INSTALL_PREFIX_PATH/bin/dlt-logstorage-ctrl INSTALL_PREFIX_PATH/bin/dlt-passive-node-ctrl INSTALL_PREFIX_PATH/bin/dlt-receive INSTALL_PREFIX_PATH/bin/dlt-system INSTALL_PREFIX_PATH/share/man/man1/dlt-convert.1.gz INSTALL_PREFIX_PATH/share/man/man1/dlt-logstorage-ctrl.1.gz INSTALL_PREFIX_PATH/share/man/man1/dlt-passive-node-ctrl.1.gz INSTALL_PREFIX_PATH/share/man/man1/dlt-receive.1.gz INSTALL_PREFIX_PATH/share/man/man1/dlt-system.1.gz INSTALL_PREFIX_PATH/share/man/man5/dlt-system.conf.5.gz lib/systemd/system/dlt-adaptor-udp.service lib/systemd/system/dlt-receive.service dlt-daemon-2.18.10/debian/libdlt-dev.install000066400000000000000000000001741446635226000205610ustar00rootroot00000000000000INSTALL_PREFIX_PATH/include/dlt/* INSTALL_PREFIX_PATH/lib/*/libdlt.so INSTALL_PREFIX_PATH/lib/*/pkgconfig/automotive-dlt.pc dlt-daemon-2.18.10/debian/libdlt2.install000066400000000000000000000000461446635226000200650ustar00rootroot00000000000000INSTALL_PREFIX_PATH/lib/*/libdlt.so.* dlt-daemon-2.18.10/debian/rules000077500000000000000000000015451446635226000162260ustar00rootroot00000000000000#!/usr/bin/make -f #export DH_VERBOSE=1 # Debian host name can be different between each architectures # Preparing it's name for libdlt.so path DEB_HOST_MULTIARCH = $(shell dpkg-architecture -q DEB_HOST_MULTIARCH) %: dh $@ --buildsystem cmake --builddirectory=build override_dh_auto_configure: dh_auto_configure -- \ -DWITH_SYSTEMD=ON -DWITH_SYSTEMD_JOURNAL=ON \ -DWITH_MAN=ON -DWITH_DLT_DBUS=ON \ -DWITH_DLT_KPI=ON -DWITH_DLT_ADAPTOR=ON \ -DWITH_DLT_SYSTEM=ON -DCMAKE_INSTALL_PREFIX=/opt/tooling/dlt \ -DCMAKE_INSTALL_SYSCONFDIR=/opt/tooling/dlt/etc \ -DCMAKE_INSTALL_LIBDIR=lib/$(DEB_HOST_MULTIARCH) # Specific the path of libdlt.so for linking override_dh_shlibdeps: dh_shlibdeps -l$(CURDIR)/debian/tmp/opt/tooling/dlt/lib/$(DEB_HOST_MULTIARCH)/ override_dh_install: sed -i 's/INSTALL_PREFIX_PATH/opt\/tooling\/dlt/g' debian/*.install; \ dh_install dlt-daemon-2.18.10/distfiles000066400000000000000000000006521446635226000156330ustar00rootroot00000000000000CMakeLists.txt (src|include|wxctb|testscripts|doc).*CMakeLists.txt (src|include|wxctb|testscripts).*\.(cpp|h|c|cxx) include/dlt/.*(\.h|\.cpp|\.cmake) #testscripts/Ubuntu/.*(\.h|\.cpp|\.cmake) #testscripts/Meego/.*(\.h|\.cpp|\.cmake) #systemd/.*(\.h|\.cpp|\.cmake) automotive-dlt.spec.in [^/]*\.cmake src/daemon/dlt.conf src/system/dlt-system.conf src/tests/dlt-test-filetransfer-file src/tests/dlt-test-filetransfer-image.png dlt-daemon-2.18.10/doc/000077500000000000000000000000001446635226000144645ustar00rootroot00000000000000dlt-daemon-2.18.10/doc/CMakeLists.txt000066400000000000000000000121331446635226000172240ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if(WITH_DOC) # Markdown FIND_PROGRAM(PANDOC_TOOL NAMES pandoc PATHS /bin /usr/bin /usr/local/bin) if(NOT PANDOC_TOOL) MESSAGE(FATAL_ERROR "Could not find pandoc for man page generation.") endif(NOT PANDOC_TOOL) FIND_PROGRAM(SED_TOOL NAMES sed PATHS /bin /usr/bin /usr/local/bin) if(NOT SED_TOOL) MESSAGE(FATAL_ERROR "Could not find sed for html generation.") endif(NOT SED_TOOL) file(GLOB MD_FILES "${PROJECT_SOURCE_DIR}/doc/*.md") add_custom_target(generate_doc ALL) add_custom_command(TARGET generate_doc PRE_BUILD COMMAND ${PANDOC_TOOL} -s -f markdown -t html5 ${PROJECT_SOURCE_DIR}/README.md -o ${PROJECT_BINARY_DIR}/README.html COMMAND ${SED_TOOL} -i 's|\.md|\.html|g' ${PROJECT_BINARY_DIR}/README.html) foreach(FILE ${MD_FILES}) get_filename_component(FILENAME ${FILE} NAME) string(REPLACE ".md" ".html" HTML_FILE ${FILENAME}) add_custom_command(TARGET generate_doc PRE_BUILD COMMAND ${PANDOC_TOOL} -s -f markdown -t html5 ${FILE} -o ${PROJECT_BINARY_DIR}/doc/${HTML_FILE} COMMAND ${SED_TOOL} -i 's|\.md|\.html|g' ${PROJECT_BINARY_DIR}/doc/${HTML_FILE}) endforeach() # Doxygen find_package(Doxygen REQUIRED) configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen.cfg.cmake ${PROJECT_BINARY_DIR}/doc/doxygen.cfg @ONLY) add_custom_target (doc ALL COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/doc/doxygen.cfg WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc ) FIND_PROGRAM(ASCIIDOC_TOOL NAMES asciidoc PATHS /bin /usr/bin /usr/local/bin) if(NOT ASCIIDOC_TOOL) MESSAGE(FATAL_ERROR "Could not find asciidoc for doc-manuals generation.") endif(NOT ASCIIDOC_TOOL) add_custom_target (doc-manuals ALL COMMAND mkdir -p ${PROJECT_BINARY_DIR}/doc/manuals COMMAND mkdir -p ${PROJECT_BINARY_DIR}/doc/manuals/images COMMAND cp -r ${PROJECT_SOURCE_DIR}/doc/images/* ${PROJECT_BINARY_DIR}/doc/manuals/images COMMAND ${ASCIIDOC_TOOL} -a TOC1 -o ${PROJECT_BINARY_DIR}/doc/manuals/dlt_design_specification.html ${PROJECT_SOURCE_DIR}/doc/dlt_design_specification.md WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc ) endif(WITH_DOC) if(WITH_MAN) # Compress the man pages and install to proper place FIND_PROGRAM(GZIP_TOOL NAMES gzip PATHS /bin /usr/bin /usr/local/bin) if(NOT GZIP_TOOL) MESSAGE(FATAL_ERROR "Could not find gzip for man page compression.") endif(NOT GZIP_TOOL) FIND_PROGRAM(PANDOC_TOOL NAMES pandoc PATHS /bin /usr/bin /usr/local/bin) if(NOT PANDOC_TOOL) MESSAGE(FATAL_ERROR "Could not find pandoc for man page generation.") endif(NOT PANDOC_TOOL) set(MAN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(MAN_BUILD_DIR ${PROJECT_BINARY_DIR}/doc) file(GLOB MD_SRC "${MAN_SRC_DIR}/*.[1-8].md") set(MAN_BUILD_SRC "") foreach(FILE ${MD_SRC}) get_filename_component(FILENAME ${FILE} NAME) string(REPLACE ".md" "" MAN_FILENAME ${FILENAME}) list(APPEND MAN_BUILD_SRC ${MAN_BUILD_DIR}/${MAN_FILENAME}) endforeach() set(MAN_BUILD_GZ "") foreach(FILE ${MAN_BUILD_SRC}) list(APPEND MAN_BUILD_GZ "${FILE}.gz") endforeach() add_custom_target(generate_man ALL) set(CNT "0") list(LENGTH MD_SRC NUMBER_OF_MAN_PAGES) while(CNT LESS ${NUMBER_OF_MAN_PAGES}) list(GET MD_SRC ${CNT} SRC_MD_FILE) list(GET MAN_BUILD_SRC ${CNT} BUILD_MAN_FILE) list(GET MAN_BUILD_GZ ${CNT} BUILD_MAN_GZ_FILE) add_custom_command(TARGET generate_man PRE_BUILD COMMAND ${PANDOC_TOOL} -s -t man ${SRC_MD_FILE} -o ${BUILD_MAN_FILE} COMMAND ${GZIP_TOOL} -c ${BUILD_MAN_FILE} > ${BUILD_MAN_GZ_FILE}) MATH(EXPR CNT "${CNT}+1") endwhile() # If user has not set the base dir for man pages, use a default location set(MAN_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/man) set(MAN5_GZ_FILES "") set(MAN1_GZ_FILES "") foreach(FILE ${MAN_BUILD_GZ}) if(${FILE} MATCHES "(\.1\.gz)$") list(APPEND MAN1_GZ_FILES ${FILE}) elseif(${FILE} MATCHES "(\.5\.gz)$") list(APPEND MAN5_GZ_FILES ${FILE}) endif() endforeach() install(FILES ${MAN5_GZ_FILES} DESTINATION ${MAN_INSTALL_DIR}/man5 ) install(FILES ${MAN1_GZ_FILES} DESTINATION ${MAN_INSTALL_DIR}/man1 ) endif(WITH_MAN)dlt-daemon-2.18.10/doc/dlt-adaptor-stdin.1.md000066400000000000000000000022651446635226000205040ustar00rootroot00000000000000% DLT-ADAPTOR-STDIN(1) # NAME **dlt-adaptor-stdin** - Forward input from stdin to DLT Daemon # SYNOPSIS **dlt-adaptor-stdin** \[**-a** apid\] \[**-c** ctid\] \[**-b**\] \[**-s**\] \[**-t** timeout\] \[**-h**\] # DESCRIPTION This is a small external program for forwarding input from stdin to DLT Daemon. ## OPTIONS -a : Set application ID to apid (default: SINA) -c : Set context ID tp ctid (default: SINC) -b : To flush the buffered logs while unregistering app -t : Set timeout when sending messages at exit, in ms (default: 10000 = 10sec) -h : Show help # EXAMPLES Forward all dmesg to DLT Daemon without discarding any messages **dmesg | dlt-adaptor-stdin -b -s** Send DBUS messages to DLT Daemon using the program dbus-monitor **dbus-monitor | dlt-adaptor-stdin** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Saya Sugiura (ssugiura (at) jp.adit-jv (dot) com) # COPYRIGHT Copyright (C) 2019 Advanced Driver Information Technology, Bosch and DENSO. License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-adaptor-udp.1.md000066400000000000000000000023231446635226000201460ustar00rootroot00000000000000% DLT-ADAPTOR-UDP(1) # NAME **dlt-adaptor-udp** - Forward received UDP messages to DLT Daemon # SYNOPSIS **dlt-adaptor-udp** \[**-a** apid\] \[**-c** ctid\] \[**-p**\] \[**-h**\] # DESCRIPTION This is a small external program for forwarding received UDP messages to DLT Daemon. This also can be used for e.g. sending syslog messages to the DLT daemon. Therefore a syslog daemon called *syslog-ng* is necessary. This syslog daemon must be configured to send the syslog messages to a specific UDP port. For configuration of this syslog daemon, see the documentation for *syslog-ng*. This tools is already integrated into *dlt-system*. ## OPTIONS -a : Set application ID to apid (default: UDPA) -c : Set context ID tp ctid (default: UDPC) -p : Set receive port number for UDP messages (default: 47111) -h : Show help # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Saya Sugiura (ssugiura (at) jp.adit-jv (dot) com) # COPYRIGHT Copyright (C) 2019 Advanced Driver Information Technology, Bosch and DENSO. License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-control.1.md000066400000000000000000000070551446635226000174150ustar00rootroot00000000000000% DLT-CONTROL(1) # NAME **dlt-control** - Send control messages to DLT Daemon # SYNOPSIS **dlt-control** \[**-v**\] \[**-h**\] \[**-S**\] \[**-R**\] \[**-y**\] \[**-b** baudrate\] \[**-e** ecuid\] \[**-a** id\] \[**-c** id\] \[**-s** id\] \[**-m** message\] \[**-x** message\] \[**-t** milliseconds\] \[**-l** level\] \[**-r** tracestatus\] \[**-d** loglevel\] \[**-f** tracestatus\] \[**-i** enable\] \[**-o**\] \[**-g**\] \[**-j**\] \[**-u**\] \[**-p** port\] hostname/serial\_device\_name # DESCRIPTION Send control messages to DLT Daemon. This is useful when there is no client (e.g. DLT Viewer) available. It supports several control messages including: - Setting log level/trace level - Setting default log level/default trace level - Enable timing packets - Store configuration - Reset to factory default - Get logging information **Note** Use -u option instead of hostname/serial\_device\_name if Unix Socket is used. See example for detail. ## OPTIONS -v : Verbose mode -h : Usage -S : Send message with serial header (Default: Without serial header) -R : Enable resync serial header -y : Serial device mode -b : Serial device baudrate (Default: 115200) -e : Set ECU ID (Default: RECV) -a : Control message application id -c : Control message context id -s : Control message injection service id -m : Control message injection in ASCII -x : Control message injection in Hex e.g. 'ad 01 24 ef' -t : Timeout to terminate application (Default:1000) -l Set the log level (0=off - 6=verbose, default= -1) supported options: -l level -a apid -c ctid -l level -a abc* (set level for all ctxts of apps name starts with abc) -l level -a apid (set level for all ctxts of this app) -l level -c xyz* (set level for all ctxts whose name starts with xyz) -l level -c ctid (set level for the particular ctxt) -l level (set level for all the registered contexts) -r : Set the trace status (0=off - 1=on, default=255) supported options: -r tracestatus -a apid -c ctid -r tracestatus -a abc* (set status for all ctxts of apps name starts with abc) -r tracestatus -a apid (set status for all ctxts of this app) -r tracestatus -c xyz* (set status for all ctxts whose name starts with xyz) -r tracestatus -c ctid (set status for the particular ctxt) -r tracestatus (set status for all the registered contexts) -d : Set the default log level (0=off - 5=verbose) -f : Set the default trace status (0=off - 1=on) -i : Enable timing packets (0=off - 1=on) -o : Store configuration -g : Reset to factory default -j : Get log info -u : unix port -p : Port for TCP communication (Default: 3490). # EXAMPLES Change log level of application "APP1" to DEBUG with unix port **dlt-control -a APP1 -l 5 -u** Change log level of application "APP1" and context "CON1" to ERROR **dlt-control -a APP1 -c CON1 -l 2 localhost** Get logging information of current running applications with unix port (IPC: Unix Socket) **dlt-control -j -u** Get logging information of current running applications (IPC:FIFO) **dlt-control -j localhost** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Saya Sugiura (ssugiura (at) jp.adit-jv (dot) com) # COPYRIGHT Copyright (C) 2019 Advanced Driver Information Technology, Bosch and DENSO. License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-convert.1.md000066400000000000000000000036221446635226000174110ustar00rootroot00000000000000% DLT-CONVERT(1) # NAME **dlt-convert** - Convert DLT Logging files into ASCII # SYNOPSIS **dlt-convert** \[**-h**\] \[**-a**\] \[**-x**\] \[**-m**\] \[**-s**\] \[**-t**\] \[**-o** filename\] \[**-v**\] \[**-c**\] \[**-f** filterfile\] \[**-b** number\] \[**-e** number\] \[**-w**\] file1 \[file2\] \[file3\] # DESCRIPTION Read DLT files, print DLT messages as ASCII and store the messages again. Use Ranges and Output file to cut DLT files. Use two files and Output file to join DLT files. ## OPTIONS -h : Display a short help text. -a : Print DLT file; payload as ASCII. -x : Print DLT file; payload as hex. -m : Print DLT file; payload as hex and ASCII. -s Print DLT file; only headers. -o : Output messages in new DLT file. -v : Verbose mode. -c : Count number of messages. -f : Enable filtering of messages. -b : First messages to be handled. -e : Last message to be handled. -w : Follow dlt file while file is increasing. -t : Handling the compressed input files (tar.gz). # EXAMPLES Convert DLT file into ASCII: **dlt-convert -a mylog.dlt** Cut a specific range, e.g. from message 1 to message 3 from a file called log.dlt and store the result to a file called newlog.dlt: **dlt-convert -b 1 -e 3 -o newlog.dlt log.dlt** Paste two dlt files log1.dlt and log2.dlt to a new file called newlog.dlt: **dlt-convert -o newlog.dlt log1.dlt log2.dlt** Handle the compressed input files and join inputs into a new file called newlog.dlt: **dlt-convert -t -o newlog.dlt log1.dlt compressed_log2.tar.gz** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-daemon.1.md000066400000000000000000000036741446635226000172030ustar00rootroot00000000000000% DLT-DAEMON(1) # NAME **dlt-daemon** - Diagnostic Log and Trace daemon # SYNOPSIS **dlt-daemon** \[**-h**\] \[**-d**\] \[**-c** filename\] \[**-t** directory\] \[**-p** port\] \[**-a** filename\] # DESCRIPTION The DLT daemon is the central place where logs and traces are gathered from different applications, stored temporarily or permanently and transferred to a DLT client application, which can run directly on the COVESA system or more likely on a external tester device. ## OPTIONS -h : Display a short help text. -d : Daemonize, needed in System V init systems. -c : Load an alternative configuration file. By default the configuration file /etc/dlt.conf is loaded. -t : Directory for local fifo and user-pipes (Default: /tmp). Applications wanting to connect to a daemon using a custom directory need to be started with the environment variable DLT_PIPE_DIR set appropriately. -p : Port to monitor for incoming requests (Default: 3490) Applications wanting to connect to a daemon using a custom port need to be started with the environment variable DLT_DAEMON_TCP_PORT set appropriately. -a : Load an alternative configuration for app id log level defaults. By default, the configuration file /etc/dlt-log-levels.conf is loaded. # EXAMPLES Start DLT daemon in background mode: **dlt-daemon -d** Start DLT daemon with own configuration: **dlt-daemon -c ~/my-dlt-configuration.cfg** Start DLT daemon with custom pipes directory: **dlt-daemon -t ~/dlt_pipes** Start DLT daemon listening on custom port 3500: **dlt-daemon -p 3500** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2016 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt.conf(5)**, **dlt-system(1)** dlt-daemon-2.18.10/doc/dlt-logd-converter.md000066400000000000000000000057721446635226000205340ustar00rootroot00000000000000# dlt-logd-converter Android specific logging features of dlt are managed by the ```dlt-logd-converter``` process. It currently contains the message forwarder from logd buffer to DLT. The application listens to the system logs on Android (logd) and sends them to DLT. The prerequisite is that dlt-daemon is already started and running. dlt-logd-converter loads by default the configuration file ```/vendor/etc/dlt-logd-converter.conf```. To change the log level, use application ID and context ID set in configuration file. ```DLT_INITIAL_LOG_LEVEL``` can be set on startup phase, or control message can be sent from DLT client (e.g. dlt-control, DLT Viewer) at runtime. Refer to [dlt_for_developers.md](dlt_for_developers.md) for more detail. ## Usage ```bash dlt-logd-converter [-h] [-c FILENAME] ``` -h : Display a short help text. -c : Load an alternative configuration file. By default the configuration file */vendor/etc/dlt-logd-converter.conf* is loaded. Non zero is returned in case of failure. ## Configuration By default, the configuration is loaded from */vendor/etc/dlt-logd-converter.conf*. It contains a few basic options: - *ApplicationID*: this Android system log forwarder will have this applicationn ID and appear on DLT client. Default value is **LOGD**. - *ContextID*: the context ID of the above application to appear on DLT client. Default value is **LOGF**. - *AndroidLogdJSONpath*: the JSON file for MAIN buffer app logs should be looked up at a defined path to use the context ID extension feature. If not found, the primitive context ID **MAIN** is applied for all. Default path is */vendor/etc/dlt-logdctxt.json*. - *AndroidLogdContextID*: If the JSON path is found, but applications are not listed in JSON file, default context ID is **OTHE**. ### Log level mapping As the severity levels on Android logs are different from DLT Log Level, the below table shows how they're converted from the former to the latter. | Android System Log Level | DLT Log Level | |--------------------------|--------------------| | ANDROID\_LOG\_DEFAULT | DLT\_LOG\_DEFAULT | | ANDROID\_LOG\_UNKNOWN | DLT\_LOG\_DEFAULT | | ANDROID\_LOG\_SILENT | DLT\_LOG\_OFF | | ANDROID\_LOG\_FATAL | DLT\_LOG\_FATAL | | ANDROID\_LOG\_ERROR | DLT\_LOG\_ERROR | | ANDROID\_LOG\_WARN | DLT\_LOG\_WARN | | ANDROID\_LOG\_INFO | DLT\_LOG\_INFO | | ANDROID\_LOG\_DEBUG | DLT\_LOG\_DEBUG | | ANDROID\_LOG\_VERBOSE | DLT\_LOG\_VERBOSE | ### Context Mapping The json file dlt-logdctxt.json can be used to map android tags to dlt-contexts. #### Example Here is an example that sets a mapping from the tag "usbcore" to the DLT context "USBC", and the tag "dummy_hcd.0" to the DLT Context "DUMM". The description field is in the registration with libdlt. ```python { "USBC": { "tag": "usbcore", "description": "" }, "DUMM": { "tag": "dummy_hcd.0", "description": "" } } ``` For the tags that are not listed, the mapping context ID should all be "OTHE". dlt-daemon-2.18.10/doc/dlt-logstorage-ctrl.1.md000066400000000000000000000030321446635226000210340ustar00rootroot00000000000000% DLT-LOGSTORAGE-CTRL(1) # NAME **dlt-logstorage-ctrl** - Trigger DLT Daemon to start/stop using an offline logstorage device # SYNOPSIS **dlt-logstorage-ctrl** \[**-h**\] \[**-c** ctype\] \[**-p** path\] \[**-e** ecu\] \[**-p\**\] \[**-t** timeout\] \[**-v**\] # DESCRIPTION Send a trigger to DLT Daemon to connect/disconnect a certain offline logstorage device # OPTIONS -h : Display a short help text. -c : Specify connection type: connect = 1, disconnect = 0. -d : Run as daemon: prop = use proprietary handler -p : Mount point path. -e : Specify the ECU ID. Default is: ECU1. -t : Specify connection timeout. Default is: 10s. -S : Send message with serial header (Default: Without serial header) -R : Enable resync serial header # EXAMPLES Activate the offline logstorage device mounted on /mnt/dltlog **dlt-logstorage-ctrl -c 1 -p /mnt/dltlog** Deactivate the offline logstorage device mounted on /mnt/dltlog **dlt-logstorage-ctrl -c 0 -p /mnt/dltlog** Run logstorage control application as daemon listen to udev events **dlt-logstorage-ctrl -d** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Christoph Lipka (clipka (at) jp.adit-jv (dot) com), Syed Hameed (shameed (at) jp.adit-jv (dot) com) # COPYRIGHT Copyright (C) 2015 Advanced Driver Information Technology, Bosch and DENSO. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-passive-node-ctrl.1.md000066400000000000000000000026431446635226000212720ustar00rootroot00000000000000% DLT-PASSIVE-NODE-CTRL(1) # NAME **dlt-passive-node-ctrl** - Send a trigger to DLT daemon to (dis)connect a passive node or get current passive node status # SYNOPSIS **dlt-passive-node-ctrl** \[**-h**\] \[**-c**\] \[**-n** ecu\] \[**-s**\] \[**-t** timeout\] \[-v\] # DESCRIPTION Send a trigger to DLT daemon to (dis)connect a passive node or get current passive node status ## OPTIONS -h : Usage -c : Connection status (1 - connect, 0 - disconnect) -n : Passive Node identifier (e.g. ECU2) -s : Show passive node(s) connection status -t : Specify connection timeout (Default: 10s) -S : Send message with serial header (Default: Without serial header) -R : Enable resync serial header -v : Set verbose flag (Default:0) # EXAMPLES Get status about connected passives nodes **dlt-passive-node-ctrl -s** Connect to passive node ECU2 **dlt-passive-node-ctrl -c 1 -n ECU2** Disconnect to passive node ECU2 **dlt-passive-node-ctrl -c 0 -n ECU2** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Christoph Lipka (clipka (at) jp.adit-jv (dot) com), Syed Hameed (shameed (at) jp.adit-jv (dot) com) # COPYRIGHT Copyright (C) 2015 Advanced Driver Information Technology, Bosch and DENSO. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-qnx-system.md000066400000000000000000000074251446635226000177270ustar00rootroot00000000000000# dlt-qnx-system QNX specific logging features of dlt are managed by the ```dlt-qnx-system``` process. It currently contains the message forwarder from slogger2 to DLT. The application listens to the system logs on QNX (slogger2) and sends them to DLT. The prerequisite is that dlt-daemon is already started and running. dlt-qnx-system loads by default the configuration file ```/etc/dlt-qnx-system.conf```. > In order to catch all logs via slog2, the syslog needs to forward to slogger2 in [syslog.conf](http://www.qnx.com/developers/docs/7.0.0/index.html#com.qnx.doc.neutrino.utilities/topic/s/syslog.conf.html). To change the log level, use application ID and context ID set in configuration file. ```DLT_INITIAL_LOG_LEVEL``` can be set on startup phase, or control message can be sent from DLT client (e.g. dlt-control, DLT Viewer) at runtime. Refer to [dlt_for_developers.md](dlt_for_developers.md) for more detail. ## Usage ```bash dlt-qnx-system [-h] [-d] [-c FILENAME] ``` -h : Display a short help text. -d : Daemonize. Detach from Terminal and run in background. -c : Load an alternative configuration file. By default the configuration file */etc/dlt-qnx-system.conf* is loaded. Non zero is returned in case of failure. ## Configuration By default, the configuration is loaded from */etc/dlt-qnx-system.conf*. It contains a few basic options: - *ApplicationId*: this QNX system log forwarder will have this application ID and appear on DLT client. Default value is *QSYM*. - *ApplicationContextID*: the context ID of the above application to appear on DLT client. Default value is *QSYC*. - *QnxSlogger2Enable*: when the value is 1 (by default), the QNX slogger2 adapter which sends slogger2 to DLT will be started. Otherwise if the value if 0, it won't be started. - *QnxSlogger2ContextId*: this will set the context ID of the QNX slogger2 adapter. Default value is *QSLA*. - *QnxSlogger2UseOriginalTimestamp*: when the value is 1 (by default), slogger2 event timestamps will be used as DLT timestamps. ## Slogger2 adapter The slogger2 adapter that can be enabled in dlt-qnx-system attaches to slogger2 and converts the messages to dlt messages. ### Log level mapping As the severity levels on QNX system log are different from DLT Log Level, the below table shows how they're converted from the former to the latter. | QNX System Log Level | DLT Log Level | |----------------------|--------------------| | SLOG2\_SHUTDOWN | DLT\_LOG\_FATAL | | SLOG2\_CRITICAL | DLT\_LOG\_FATAL | | SLOG2\_ERROR | DLT\_LOG\_ERROR | | SLOG2\_WARNING | DLT\_LOG\_WARN | | SLOG2\_NOTICE | DLT\_LOG\_INFO | | SLOG2\_INFO | DLT\_LOG\_INFO | | SLOG2\_DEBUG1 | DLT\_LOG\_DEBUG | | SLOG2\_DEBUG2 | DLT\_LOG\_VERBOSE | ### Context Mapping The json file dlt-slog2ctxt.json can be used to map slogger names to dlt-contexts. #### Example Here is an example that sets a mapping from the "dumper" process to the DLT Context "DUMP", and the QNX Hypervisor to "QVM". The description field is in the registration with libdlt. ```python { "DUMP": { "name": "dumper", "description": "Writes core dump files to disk" }, "SYSL": { "name": "syslogd", "description": "" } } ``` ### Runtime enable/disable slog2 adapter The slog2 parser callback can be disabled and reenabled at runtime by using an injection. | App ID | Context ID | Service ID | Data | Description | |--------|------------|------------|------|------------------------| | QSYM | QSYC | 0x1000 | 00 | Disable slog2 adapter | | QSYM | QSYC | 0x1000 | 01 | Reenable slog2 adapter | ### Example: ```bash dlt-control -e QNX -a QSYM -c QSYC -s 4096 -m "00" -u dlt-control -e QNX -a QSYM -c QSYC -s 4096 -m "01" -u ``` dlt-daemon-2.18.10/doc/dlt-receive.1.md000066400000000000000000000073271446635226000173610ustar00rootroot00000000000000% DLT-RECEIVE(1) # NAME **dlt-receive** - Console based client for DLT Logging # SYNOPSIS **dlt-receive** \[**-h**\] \[**-a**\] \[**-x**\] \[**-m**\] \[**-s**\] \[**-o** filename\] \[**-c** limit\] \[**-v**\] \[**-y**\] \[**-b** baudrate\] \[**-e** ecuid\] \[**-f** filterfile\] \[**-j** filterfile\] \[**-p** port\] hostname/serial_device_name # DESCRIPTION Receive DLT messages from DLT daemon and print or store the messages. ## OPTIONS -h : Display a short help text. -a : Print DLT file; payload as ASCII. -x : Print DLT file; payload as hex. -m : Print DLT file; payload as hex and ASCII. -s : Print DLT file; only headers. -o : Output messages in new DLT file. -c : Set limit when storing messages in file. When limit is reached, a new file is opened. Use K,M,G as suffix to specify kilo-, mega-, giga-bytes respectively, e.g. 1M for one megabyte (Default: unlimited). -v : Verbose mode. -S : Send message with serial header (Default: Without serial header) -R : Enable resync serial header -y : Serial device mode. -b : Serial device baudrate (Default: 115200). -e : Set ECU ID (Default: RECV). -f : Enable filtering of messages. Takes a space separated filter file (see [Space separated filter file](#Space-separated-filter-file)). -j : Enable extended filtering of messages. Takes a json filter file ([Json filter file](#Json-filter-file)). -p : Port for UDP and TCP communication (Default: 3490). # EXAMPLES Print received message headers received from a dlt-daemon running on localhost:: **dlt-receive -s localhost** Print received message headers received from a serila interface:: **dlt-receive -s -y /dev/ttySO** Store received message headers from a dlt-daemon to a log file called log.dlt and filter them for e.g. Application ID ABCD and Context ID EFGH (Write:ABCD EFGH as single line to a file called filter.txt):: **dlt-receive -s -o log.dlt -f filter.txt localhost** Store incoming messages in file(s) and restrict file sizes to 1 megabyte. If limit is reached, log.dlt will be renamed into log.0.dlt, log.1.dlt, ... No files will be overwritten in this mode:: **dlt-receive -o log.dlt -c 1M localhost** ## Space separated filter file File that defines multiple filters. Can be used as argument for `-f` option. With this it's only possible to filter messages depending on their Application ID and/or Context ID. The syntax is: first AppID and optional a CtxID behind it, with a space in between. Each line defines a filter and the maximum number of filters is 30. Example: ``` DLTD INTM DLT INT TEST ``` ## Json filter file Only available, when builded with cmake option `WITH_EXTENDED_FILTERING`. File that defines multiple filters. Can be used as argument for `-j` option. With this it's also possible to filter messages depending on their Application ID, Context ID, log level and payload size. The following example shows the syntax. Names of the filters can be customized, but not more than 15 characters long. The maximum number of filters is also 30. Example: ``` { "filter1": { "AppId": "LOG", "ContextId": "TEST", "LogLevel": "3" }, "filter2": { "AppId": "app", "LogLevel": "4" }, "filter3": { "AppId": "app2", "ContextId": "con2", "PayloadMin": "20", "PayloadMax": "50" } } ``` # EXIT STATUS Non zero is returned in case of failure. # NOTES Be aware that dlt-receive will never delete any files. Instead, it creates a new file. # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-sortbytimestamp.1.md000066400000000000000000000042411446635226000211750ustar00rootroot00000000000000% DLT-SORTBYTIMESTAMP(1) # NAME **dlt-sortbytimestamp** - Re-order DLT Logging files according to message creation time and timestamp. # SYNOPSIS **dlt-sortbytimestamp** \[**-h**\] \[**-v**\] \[**-c**\] \[**-f** filterfile\] \[**-b** number\] \[**-e** number\] dltfile_in dltfile_out # DESCRIPTION By default messages in DLT files are ordered according to the time the logger received them. This can unhelpful when tracing a sequence of events on a busy multi-threaded/multi-core system, because thread pre-emption combined with multiple processes attempting to log messages simultaneously means that the order in which the messages are received may vary significantly from the order in which they were created. *dlt-sortbytimestamp* is able to re-order a DLT input file's messages according both their creation time and timestamp, and writes them to an output DLT file. # NOTE Use the \*-b\* and/or \*-e\* options to specify a range of messages within a single reboot cycle and all will be well. Hint: use *dlt-viewer* to ascertain the endpoints of the range in question. # OPTIONS -h : Display a short help text. -v : Verbose mode. Repeat to give more information. -c : Count number of messages. -f : Enable filtering of messages. Incompatible with range options. -b : First message to be handled. Zero based index. -e : Last message to be handled. Zero based index. # EXAMPLES Sort an entire file by message timestamp: **dlt-sortbytimestamp input.dlt output.dlt** Sort a specific range, e.g. from message 1,000,000 to message 1,500,000 from a file called input.dlt and store the result in a file called output.dlt: **dlt-sortbytimestamp -b 1000000 -e 1500000 input.dlt output.dlt** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Jonathan Sambrook (jonathan.sambrook (at) codethink (dot) co (dot) uk) Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2018 Codethink Ltd. Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)**, **dlt-convert(1)** dlt-daemon-2.18.10/doc/dlt-system.1.md000066400000000000000000000023001446635226000172450ustar00rootroot00000000000000% DLT-SYSTEM(1) # NAME **dlt-system** - DLT system logging process # SYNOPSIS **dlt-system** \[**-h**\] \[**-d**\] \[**-c** filename\] #DESCRIPTION The DLT system logging process is the central application, which logs system information from the platform. It provides the features filetransfer, syslog adapater, logging of any kind of files and procfilesystem logger. The individual features can be enabled and disabled in the configuration file. dlt-system loads by default the configuration file /etc/dlt-system.conf. ## OPTIONS -h : Display a short help text. -d : Daemonize, needed in System V init systems. -c : Load an alternative configuration file. By default the configuration file /etc/dlt.conf is loaded. # EXAMPLES Start DLT system with custom configuration: **dlt-system -c ~/my-configuration.cfg** # EXIT STATUS Non zero is returned in case of failure. # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-system.conf(5)**, **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt-system.conf.5.md000066400000000000000000000135001446635226000202010ustar00rootroot00000000000000% DLT-SYSTEM.CONF(5) # NAME **dlt-system.conf** - DLT system process configuration file # DESCRIPTION The DLT system logging process is the central application, which logs system information from the platform. It provides the features filetransfer, syslog adapater, logging of any kind of files and procfilesystem logger. The individual features can be enabled and disabled in the configuration file. The configuration file dlt-system.conf allows to configure the different runtime behaviour of dlt-system. The configuration file is loaded during startup of dlt-system. dlt-system loads by default the configuration file /etc/dlt-system.conf. An alternative configuration file can be loaded with the option -c. # GENERAL OPTIONS ## ApplicationId The application Id used for the dlt-system process. Default: SYS # SHELL OPTIONS ## ShellEnable Enable the Shell for command line injections. Be careful when you enable this feature. The user can send any kind of shell commands. The commands are executed with the rights of the dlt-system process. Dlt-system is started by default as user covesa. Default: 0 # SYSLOG ADAPTER OPTIONS ## SyslogEnable If this option is set to 1, the syslog adapter feature is enabled. SyslogPort needs to be configured too if Syslog is enabled. Default: 0 ## SyslogContextId This value defines context id of the syslog adapter. Default: SYSL ## SyslogPort This value defines the UDP port opened for receiving log messages from syslog. Configuration for syslog to forward log to this port is necessary. Adding this config `` *.* @localhost:47111 `` in config file of syslog (usually in /etc/rsyslog.d/50-default.conf) and restart the syslog service by command "sudo systemctl restart rsyslog.service". Default: 47111 # SYSTEMD JOURNAL ADAPTER OPTIONS ## JournalEnable Enable the Systemd Journal Adapter. This feature is only available, when dlt is compiled with the option "WITH_SYSTEMD_JOURNAL". Dlt-system is started by default as user covesa, see dlt-system.service file. The user covesa must be added to one of the groups 'adm', 'wheel' or 'systemd-journal' to have access to all journal entries. Default: 0 ## JournalContextId The Context Id of the journal adapter. Default: JOUR ## JournalCurrentBoot Show only log entries of current boot and follow. If JournalCurrentBoot and JournalFollow are not set all persistent journal entries will be logged. Default: 1 ## JournalFollow Show only the last 10 entries and follow. Default: 0 ## JournalMapLogLevels Map journal log levels to DLT log levels. - 0 Emergency DLT_LOG_FATAL - 1 Alert DLT_LOG_FATAL - 2 Critical DLT_LOG_FATAL - 3 Error DLT_LOG_ERROR - 4 Warning DLT_LOG_WARN - 5 Notice DLT_LOG_INFO - 6 Informational DLT_LOG_INFO - 7 Debug DLT_LOG_DEBUG Default: 1 # FILETRANSFER OPTIONS ## FiletransferEnable Enable the Filetransfer feature. 0 = disabled, 1 = enabled Default: 0 ## FiletransferContextId The Context Id of the filetransfer. Default: FILE ## FiletransferTimeStartup Time in seconds after startup of dlt-system when first file is transfered. Default: 0 ## FiletransferTimeoutBetweenLogs Time in seconds to wait between two file transfer logs of a single file to DLT. Default: 10 ## FiletransferDirectory You can define multiple file transfer directories. Define the directory to watch, whether to compress the file with zlib and the zlib compression level. For parsing purposes, FiletransferCompressionLevel must be the last one of three values. ## FiletransferCompression See FiletransferDirectory option for explanation. Default: 0 ## FiletransferCompressionLevel See FiletransferDirectory option for explanation. Default: 5 # LOG FILES OPTIONS ## LogFileEnable If this option is set to 1, the log files feature is enabled. Default: 0 ## LogFileFilename This value sets the full filename path to the file, which should be logged. ## LogFileMode This value defines in which operation mode the file is logged. In mode 1 the file is only logged once when dlt-system is started. In mode 2 the file is logged regularly every time LogFileTimeDelay timer elapses. 0 = off, 1 = startup only, 2 = regular ## LogFileTimeDelay This value is used in mode 3 and defines the number of seconds, after which the defined file is logged. ## LogFileContextId This value defines the context id, which is used for logging the file. # LOG PROCESSES OPTIONS ## LogProcessesEnable Enable the logging of processes. 0 = disabled, 1 = enabled Default: 0 ## LogProcessesContextId This value defines the context id, which is used for logging processes files. Default: PROC ## LogProcessName This value defines the name of the process to be logged, as used in the file stat of each process. If the value is defined as *, all processes are logged. ## LogProcessFilename This value sets the relative filename path to the file, which should be logged. The path is relative to the procfilesystem folder of the process. ## LogProcessMode This value the defines in which operation mode this process file is logged. In mode 1 the file is only logged once when dlt-system is started. In mode 2 the file is logged regularly every time LogFileTimeDelay timer elapses. 0 = off, 1 = startup only, 2 = regular. Default: 0 ## LogProcessTimeDelay This value is used in mode 3 and defines the number of seconds, after which the defined procfilesystem file is logged. Default: 0 # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-system(1)**, **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt.conf.5.md000066400000000000000000000255361446635226000166730ustar00rootroot00000000000000% DLT.CONF(5) # NAME **dlt.conf** - DLT daemon configuration file # DESCRIPTION The DLT daemon is the central application which gathers logs and traces from different applications, stores them temporarily or permanently and transfers them to a DLT client application, which could run directly on the COVESA system or more likely on some external tester device. The configuration file dlt.conf allows to configure the different runtime behaviour of the dlt-daemon. It is loaded during startup of dlt-daemon. # GENERAL OPTIONS ## Verbose Start daemon in debug mode, so that all internal debug information is printed out on the console. Default: Off ## Daemonize If set to 1 DLT daemon is started in background as daemon. This option is only needed in System V init systems. In systemd based startup systems the daemon is started by spawning own process. Default: 0 ## SendSerialHeader If set to 1 DLT daemon sends each DLT message to the client with prepanding the serial header "DLS0x01". Default: 0 ## SendContextRegistration If set to 1 each context which is registered from an application in the DLT daemon generates a message to inform the DLT client about the new context. Default: 1 ## SendMessageTime If set to 1 DLt daemon sends each second a DLT control message to the client with the current timestamp from the system. Default: 0 ## ECUId This value sets the ECU Id, which is sent with each DLT message. Default: ECU1 ## SharedMemorySize This value sets the size of the shared memory, which is used to exchange DLT messages between applications and daemon. This value is defined in bytes. If this value is changed the system must be rebooted to take effect. Default: 100000 ## PersistanceStoragePath This is the directory path, where the DLT daemon stores its runtime configuration. Runtime configuration includes stored log levels, trace status and changed logging mode. Default: /tmp ## LoggingMode The logging console for internal logging of dlt-daemon. 0 = log to stdout, 1 = log to syslog, 2 = log to file (see LoggingFilename), 3 = log to stderr Default: 0 ## LoggingLevel The internal log level, up to which logs are written. LOG_EMERG = 0, LOG_ALERT = 1, LOG_CRIT = 2, LOG_ERR = 3, LOG_WARNING = 4, LOG_NOTICE = 5, LOG_INFO = 6, LOG_DEBUG = 7 Default: 6 ## LoggingFilename If LoggingMode is set to 2 logs are written to the file path given here. Default: /tmp/dlt.log ## EnableLoggingFileLimit Only relevant for logging in file (LoggingMode = 2). If EnableLoggingFileLimit is set to 0, the daemon logs to one logging file without any size limit. If EnableLoggingFileLimit is set to 1, the daemon considers the size limits configured by LoggingFileSize and LoggingFileMaxSize. If the limits are configured accordingly, multiple log files are used. Default: 0 ## LoggingFileSize Only considered for logging in file (LoggingMode = 2) and EnableLoggingFileLimit = 1. Maximum size in bytes of one logging file. Default: 250000 ## LoggingFileMaxSize Only considered for logging in file (LoggingMode = 2) and EnableLoggingFileLimit = 1. Maximum size in bytes of all logging files. Default: 1000000 ## TimeOutOnSend Socket timeout in seconds for sending to clients. Default: 4 ## RingbufferMinSize The minimum size of the Ringbuffer, used for storing temporary DLT messages, until client is connected. Default: 500000 ## RingbufferMaxSize The max size of the Ringbuffer, used for storing temporary DLT messages, until client is connected. Default: 10000000 ## RingbufferStepSize The step size the Ringbuffer is increased, used for storing temporary DLT messages, until client is connected. Default: 500000 ## Daemon FIFOSize The size of Daemon FIFO (MinSize: depend on pagesize of system, MaxSize: please check `/proc/sys/fs/pipe-max-size`) This is only supported for Linux. Default: 65536 ## ContextLogLevel Initial log-level that is sent when an application registers. DLT_LOG_OFF = 0, DLT_LOG_FATAL = 1, DLT_LOG_ERROR = 2, DLT_LOG_WARN = 3, DLT_LOG_INFO = 4, DLT_LOG_DEBUG = 5, DLT_LOG_VERBOSE = 6 Default: 4 ## ContextTraceStatus Initial trace-status that is sent when an application registers. DLT_TRACE_STATUS_OFF = 0, DLT_TRACE_STATUS_ON = 1 Default: 0 ## ForceContextLogLevelAndTraceStatus Force log level and trace status of contexts to not exceed "ContextLogLevel" and "ContextTraceStatus". If set to 1 (ON) whenever a context registers or changes the log-level it has to be lower or equal to ContextLogLevel. Default: 0 ## InjectionMode If set to 0, the injection mode (see [here](./dlt_for_developers.md#DLT-Injection-Messages)) is disabled. Default: 1 # GATEWAY CONFIGURATION ## GatewayMode Enable Gateway mode Default: 0 ## GatewayConfigFile Read gateway configuration from another location Default: /etc/dlt_gateway.conf # Permission configuration DLT daemon runs with e.g. User: covesa_dlt Group: covesa_dlt DLT user applications run with different user and group than dlt-daemon but with supplimentory group: dlt_user_apps_group /dlt FIFO will be created by dlt-daemon with User: covesa_dlt Group: dlt_user_apps_group Permission: 620 so that only dlt-daemon can read and only processes in dlt_user_apps_group can write. /dltpipes will be created by dlt-daemon with User: covesa_dlt Group: covesa_dlt Permission: 3733 (i.e Sticky bit and SGID turned on) /dltpipes/dlt FIFO will be created by dlt application (user lib) with User: Group: covesa_dlt (inherited from dltpipes/ due to SGID) Permission: 620 Thus DLT user applications (and also or attackers) can create the dlt FIFO (for communication from dlt-daemon to DLT user application) under /dltpipes/. Since sticky bit is set the applications who creates the FIFO can only rename/delete it. Since SGID of /dltpipes is set the group of dlt FIFO will be covesa_dlt which enables dlt daemon to have write permission on all the dlt FIFO. One dlt user application cannot access dlt FIFO created by other dlt user application(if they run with different user). Owner group of daemon FIFO directory(Default: /tmp/dlt) (If not set, primary group of dlt-daemon process is used). Application should have write permission to this group for tracing into dlt. For this opton to work, dlt-daemon should have this group in it's supplementary group. ## DaemonFifoGroup Owner group of daemon FIFO directory (If not set, primary group of dlt-daemon process is used) Application should have write permission to this group for tracing into dlt For this opton to work, dlt-daemon should have this group in it's Supplementary group Default: group of dlt-daemon process (/tmp/dlt) # CONTROL APPLICATION OPTIONS ## ControlSocketPath Path to control socket. Default: /tmp/dlt-ctrl.sock # OFFLINE TRACE OPTIONS ## OfflineTraceDirectory Store DLT messages to local directory, if not set offline Trace is off. Default: /tmp ## OfflineTraceFileSize This value defines the max size of a offline trace file, if offline trace is enabled. This value is defined in bytes. If the files size of the current used log file is exceeded, a new log file is created. Default: 1000000 ## OfflineTraceMaxSize This value defines the max offline Trace memory size, if offline trace is enabled. This value is defined in bytes. If the overall offline trace size is excedded, the oldest log files are deleted, until a new trace file fits the overall offline trace max size. Default: 4000000 ## OfflineTraceFileNameTimestampBased Filename timestamp based or index based. 1 = timestamp based, 0 = index based Default: Function is disabled # LOCAL CONSOLE OUTPUT OPTIONS ## PrintASCII Prints each received DLT message from the application in ASCII to the local console. This option should only be anabled for debugging purpose. Default: Function is disabled ## PrintHex Prints each received DLT message from the application in ASCII to the local console. The payload is printed in Hex. This option should only be anabled for debugging purpose. Default: Function is disabled ## PrintHeadersOnly Prints each received DLT message from the application in ASCII to the local console. Only the header is printed. This option should only be anabled for debugging purpose. Default: Function is disabled # SERIAL CLIENT OPTIONS ## RS232DeviceName If this value is set to a serial device name, e.g. /dev/ttyS0, a serial port is used for logging to a client. Default: Serial port for logging is disabled ## RS232Baudrate The used serial baud rate, if serial loggin is enabled. The RS232DeviceName must be set to enable serial logging. Default: 115200 ## RS232SyncSerialHeader If serial logging is enabled, each received DLT message is checked to contain a serial header. If the DLT message contains no serial header, the message is ignored. Default: Function is disabled # TCP CLIENT OPTIONS ## TCPSyncSerialHeader Each received DLT message on a TCP connection is checked to contain a serial header. If the DLT message contains no serial header, the message is ignored. Default: Function is disabled # ECU SOFTWARE VERSION OPTIONS ## SendECUSoftwareVersion Periodically send ECU version info. 0 = disabled, 1 = enabled Default: Function is disabled # PathToECUSoftwareVersion Absolute path to file storing version information - if disabled the DLT version will be send. Default: Function is disabled. # TIMEZONE INFO OPTIONS # SendTimezone Periodically send timezone info. 0 = disabled, 1 = enabled Default: Function is disabled # OFFLINE LOGSTORAGE OPTIONS ## OfflineLogstorageMaxDevices Maximum devices to be used as offline logstorage devices. 0 = disabled, 1 .. DLT_OFFLINE_LOGSTORAGE_MAX_DEVICES Default: 0 (Function is disabled) ## OfflineLogstorageDirPath Path to store DLT offline log storage messages. Default: off ## OfflineLogstorageTimestamp Appends timestamp in log file name. 0 = disabled, 1 = enabled Default: 0 ## OfflineLogstorageDelimiter Appends delimiter in log file name, only punctuation characters allowed. Default: _ ## OfflineLogstorageMaxCounter Wrap around value for log file count in file name. Default: UINT_MAX ## OfflineLogstorageCacheSize Maximal used memory for log storage cache in KB. Default: 30000 KB ## UDPConnectionSetup Enable or disable UDP connection. 0 = disabled, 1 = enabled ## UDPMulticastIPAddress The address on which daemon multicasts the log messages ## UDPMulticastIPPort The Multicase IP port. Default: 3491 # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) # COPYRIGHT Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)**, **dlt-system(1)** dlt-daemon-2.18.10/doc/dlt_build_options.md000066400000000000000000000116271446635226000205320ustar00rootroot00000000000000# DLT Build Options DLT is highly configurable. It allows you to choose between certain technologies or implementations and to turn on or off certain features. This way, you can adjust it to your needs and keep the build process as simple as possible. In order to change these options, you can modify these values with cmake, do the appropriate changes in CmakeList.txt or via the commandline for cmake Change a value with: cmake -D\=\, E.g. ```bash cmake .. -DWITH_SYSTEMD=ON -DWITH_SYSTEMD_JOURNAL=ON -DCMAKE_INSTALL_PREFIX=/usr ``` ## General Options Option | Value | Comment :--- | :--- | :--- BUILD\_SHARED\_LIBS | ON | Set to OFF to build static libraries DLT\_IPC |"FIFO" | Set to either "UNIX\_SOCKET" or "FIFO" WITH\_DLT\_USE\_IPv6 | ON | Set to ON for IPv6 support WITH\_DLT\_EXAMPLES | ON | Set to ON to build src/examples binaries DLT\_USER | covesa | Set user for process not run as root WITH\_CHECK\_CONFIG\_FILE | OFF | Set to ON to create a configure file of CheckIncludeFiles and CheckFunctionExists CMAKE\_INSTALL\_PREFIX | /usr/local CMAKE\_BUILD\_TYPE | RelWithDebInfo WITH\_UDP\_CONNECTION | OFF | Set to ON to enable dlt UDP multicast SUPPORT WITH\_DLT\_DAEMON\_VSOCK\_IPC | OFF | Set to ON for VSOCK support in daemon. WITH\_DLT\_LIB\_VSOCK\_IPC | OFF | Set to ON for VSOCK support in libdlt (DLT\_IPC is overridden in libdlt). DLT\_VSOCK\_PORT | 13490 | Port to use for VSOCK communication. WITH\_LEGACY\_INCLUDE\_PATH | ON | Set to ON to add /dlt to include paths for the CMake config file, in addition to only WITH\_DLT\_LOG\_LEVEL\_APP\_CONFIG | OFF | Set to ON to enable default log levels based on application ids ## Command Line Tool Options Option | Value | Comment :--- | :--- | :--- WITH\_DLT\_ADAPTOR | OFF | Set to ON to build src/adaptor binaries WITH\_DLT\_CONSOLE | ON | Set to ON to build src/console binaries WITH\_DLT\_SYSTEM | OFF | Set to ON to build src/system binaries WITH\_DLT\_LOGSTORAGE\_CTRL\_UDEV | OFF | PROTOTYPE! Set to ON to build WITH\_DLT\_KPI | OFF | Set to ON to build src/kpi binaries WITH\_EXTENDED\_FILTERING | OFF | Set to OFF to build without extended filtering. Using json filter files is only supported for Linux based system with json-c and QNX. ## Linux OS Integration Options Option | Value | Comment :--- | :--- | :--- WITH\_SYSTEMD | OFF | Set to ON to run CMakeLists.txt in systemd WITH\_SYSTEMD\_WATCHDOG | OFF | Set to ON to use the systemd watchdog in dlt-daemon WITH\_SYSTEMD\_WATCHDOG\_ENFORCE\_MSG\_RX | OFF | Set to ON to notify the watchdog only if new messages where received in dlt-daemon since last notify WITH\_SYSTEMD\_WATCHDOG\_ENFORCE\_MSG\_RX\_DLT\_SYSTEM | OFF | Set to ON to notify the watchdog only if new messages where received in dlt-system since last notify WITH\_SYSTEMD\_JOURNAL | OFF | Set to ON to use the systemd journal in dlt-system WITH\_DLT\_DBUS | OFF | Set to ON to build src/dbus binaries ## QNX OS Integration Options Option | Value | Comment :--- | :--- | :--- WITH\_DLT\_QNX\_SYSTEM | OFF | Set to ON to build QNX system binary dlt-qnx-system DLT\_QNX\_SLOG\_ADAPTER\_WAIT\_BUFFER\_TIMEOUT\_MS | 100 | Maximum time in milliseconds to wait for buffer space in dlt before messages from the slog will be discarded. ## Documentation Options Option | Value | Comment :--- | :--- | :--- WITH\_DOC | OFF | Set to ON to build API documentation WITH\_MAN | OFF | Set to ON to build man pages ## Test Options Option | Value | Comment :--- | :--- | :--- WITH\_TESTSCRIPTS | OFF | Set to ON to run CMakeLists.txt in test scripts WITH\_DLT\_TESTS | ON | Set to ON to build src/test binaries WITH\_DLTTEST | OFF | Set to ON to build with modifications to test User-Daemon communication with corrupt messages WITH\_DLT\_UNIT\_TESTS | OFF | Set to ON to build unit test binaries WITH\_GPROF | OFF | Set \-pg to compile flag ## Experimental Features Options (Dragons ahead!) Option | Value | Comment :--- | :--- | :--- WITH\_DLT\_SHM\_ENABLE | OFF | Set to ON to enable shared memory as IPC WITH\_DLT\_CXX11\_EXT | OFF | Set to ON to build C++11 extensions WITH\_DLT\_COREDUMPHANDLER | OFF | Set to ON to build src/core\_dump\_handler binaries. dlt-daemon-2.18.10/doc/dlt_cdh.md000066400000000000000000000056711446635226000164200ustar00rootroot00000000000000# DLT Core Dump Handler Back to [README.md](../README.md) ## Overview When a program crash occurs on the system, the Core Dump Handler is triggered to extract relevant information from the core dump generated by the system. It stores this extracted information in the ECU's file system as Core Dump Handler Files. These files are transported via the [DLT Filetransfer](dlt_filetransfer.md) mechanism. The transferred information can be combined and integrated into the developer toolchain (gdb, Release SW, etc.). ![alt text](images/dlt_core_dump_handler.png "DLT CDH") ## Integration ### To build the core dump handler Add `-DWITH_DLT_COREDUMPHANDLER=ON -DTARGET_CPU_NAME={i686|x86_64}` options to cmake. The core dump handler code currently supports the i686 and x86\_64 architecture. ### Temporary activation as replacement for default crash handler until next reboot As *root* (not sudo) execute the following: `echo "|/usr/local/bin/dlt-cdh %t %p %s %e" > /proc/sys/kernel/core_pattern` NOTE: replace */usr/local/bin* with the path dlt-cdh has been installed to. This instructs the kernel to pipe a core dump as standard input to dlt-cdh together with the following parameters: - %t time of dump - %p PID of dumped process - %s number of signal causing dump - %e executable filename See `man core` for details. ### Persistent activation as replacement for default crash handler In */usr/lib/sysctl.d/* the file *50-coredump.conf* has to be created which is done automatically by `make install` Unfortunately - at least on Fedora systems - abrt has to be removed with `yum remove abrtd*` because it ruthlessly overwrites our change at every boot. The core dump handler can be activated then without reboot by running `sysctl -p /usr/lib/sysctl.d/50-coredump.conf` ### Configuration of [DLT Filetransfer](dlt_filetransfer.md) for usage with dlt-cdh Make sure the following is set in the "Filetransfer Manager" section of */etc/dlt-system.conf*: ``` ... FiletransferEnable = 1 ... FiletransferDirectory = /var/core ... ``` ### Generation of core dump When a crash happens the kernel invokes dlt-cdh and passes it the core dump as standard input. dlt-cdh does the following tasks: - check if enough disk space available - create target directories if not existing: - /var/core - /var/core\_tmp - /tmp/.core\_locks - clean /var/core\_tmp - retrieve context data mainly from /proc fs of the crashed process to a temporary context file in text format - initialise core dump - read ELF headers and notes to temporary core dump output file - move context file and core dump to /var/core - create id which identifies the crash After the files have been moved to /var/core the [DLT Filetransfer](dlt_filetransfer.md) mechanism ensures that they are sent to connected clients. ## AUTHOR Lutz Helwing ## COPYRIGHT Copyright (C) 2011 - 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . dlt-daemon-2.18.10/doc/dlt_demo_setup.md000066400000000000000000000137171446635226000200260ustar00rootroot00000000000000# DLT Demo Setup Back to [README.md](../README.md) In this document you will run an instance of dlt-daemon. It silently waits to collect and buffer log messages that are produced by one or multiple DLT users. You will run one of those DLT users and make it produce log messages that are sent to the daemon. Eventually, you launch a client that collects and displays these messages. *Note: We assume that you installed DLT (i.e. executed the [two optional steps after build](../README.md#build-and-install)). Otherwise you have to take care of the executable paths and explicitly state the library path.* ## Run the DLT Daemon The DLT daemon is highly configurable but for this case the default settings are okay. Don't be put off by warning messages: ```bash $ dlt-daemon [1886222.668006]~DLT~32290~NOTICE ~Starting DLT Daemon; DLT Package Version: 2.18.0 STABLE, Package Revision: v2.18.1, build on Dec 8 2020 11:11:51 -SYSTEMD -SYSTEMD_WATCHDOG -TEST -SHM [1886222.668651]~DLT~32290~INFO ~FIFO size: 65536 [1886222.668764]~DLT~32290~INFO ~Activate connection type: 5 [1886222.668897]~DLT~32290~INFO ~dlt_daemon_socket_open: Socket created [1886222.669047]~DLT~32290~INFO ~dlt_daemon_socket_open: Listening on ip 0.0.0.0 and port: 3490 [1886222.669159]~DLT~32290~INFO ~dlt_daemon_socket_open: Socket send queue size: 16384 [1886222.669355]~DLT~32290~INFO ~Activate connection type: 1 [1886222.669509]~DLT~32290~INFO ~Activate connection type: 9 [1886222.669644]~DLT~32290~INFO ~Ringbuffer configuration: 500000/10000000/500000 [1886222.669924]~DLT~32290~NOTICE ~Failed to open ECU Software version file. [1886222.670034]~DLT~32290~INFO ~Activate connection type: 6 [1886222.670188]~DLT~32290~INFO ~Switched to buffer state for socket connections. [1886222.670365]~DLT~32290~WARNING ~dlt_daemon_applications_load: cannot open file /tmp/dlt-runtime-application.cfg: No such file or directory ``` The daemon opened a named pipe from which it is ready to read and buffer log messages. It also accepts connections on TCP port 3490 by clients to collect the messages. ## Produce Log Messages A simulated ECU - a DLT user - will now use the DLT library to create log messages and send them through the named pipe for the daemon to collect. Open a second terminal and run ```bash $ dlt-example-user -n 5 -l 3 "This is my first log message" Send 0 This is my first log message Log level changed of context TEST, LogLevel=4, TraceState=0 Log level changed of context TS1, LogLevel=4, TraceState=0 Log level changed of context TS2, LogLevel=4, TraceState=0 Send 1 This is my first log message Client disconnected! Send 2 This is my first log message Send 3 This is my first log message Send 4 This is my first log message ``` This will send 5 (```-n 5```) identical log messages of Log-Level WARNING ```(-l 3)``` containing a string payload. ## Read logs The DLT daemon now has the messages in its buffer and will keep them there until they are fetched. A mighty tool for receiving and processing log messages is the [DLT-Viewer](https://github.com/COVESA/dlt-viewer), which also provides a graphical UI. For now, a simple command line client is absolutely sufficient: ```bash $ dlt-receive -a localhost 2020/04/30 12:27:14.976731 17134987 000 ECU1 DA1- DC1- control response N 1 [service(3842), ok, 02 00 00 00 00] 2020/04/30 12:27:14.976779 17067139 000 ECU1 DA1- DC1- control response N 1 [service(3842), ok, 01 00 00 00 00] 2020/04/30 12:27:14.976787 17067139 004 ECU1 DLTD INTM log info V 1 [Client connection #7 closed. Total Clients : 0] 2020/04/30 12:27:14.976794 17104625 005 ECU1 DLTD INTM log info V 1 [ApplicationID 'LOG' registered for PID 5241, Description=Test Application for Logging] 2020/04/30 12:27:14.976802 17104625 000 ECU1 DA1- DC1- control response N 1 [get_log_info, 07, 01 00 4c 4f 47 00 01 00 54 45 53 54 ff ff 18 00 54 65 73 74 20 43 6f 6e 74 65 78 74 20 66 6f 72 20 4c 6f 67 67 69 6e 67 1c 00 54 65 73 74 20 41 70 70 6c 69 63 61 74 69 6f 6e 20 66 6f 72 20 4c 6f 67 67 69 6e 67 72 65 6d 6f] 2020/04/30 12:27:14.976823 17104625 000 ECU1 DA1- DC1- control response N 1 [get_log_info, 07, 01 00 4c 4f 47 00 01 00 54 53 31 00 ff ff 1b 00 54 65 73 74 20 43 6f 6e 74 65 78 74 31 20 66 6f 72 20 69 6e 6a 65 63 74 69 6f 6e 1c 00 54 65 73 74 20 41 70 70 6c 69 63 61 74 69 6f 6e 20 66 6f 72 20 4c 6f 67 67 69 6e 67 72 65 6d 6f] 2020/04/30 12:27:14.976844 17104625 000 ECU1 DA1- DC1- control response N 1 [get_log_info, 07, 01 00 4c 4f 47 00 01 00 54 53 32 00 ff ff 1b 00 54 65 73 74 20 43 6f 6e 74 65 78 74 32 20 66 6f 72 20 69 6e 6a 65 63 74 69 6f 6e 1c 00 54 65 73 74 20 41 70 70 6c 69 63 61 74 69 6f 6e 20 66 6f 72 20 4c 6f 67 67 69 6e 67 72 65 6d 6f] 2020/04/30 12:27:14.976866 17104588 000 ECU1 LOG- TEST log warn V 2 [0 This is my first log message] 2020/04/30 12:27:14.976872 17109592 001 ECU1 LOG- TEST log warn V 2 [1 This is my first log message] 2020/04/30 12:27:14.976880 17114599 002 ECU1 LOG- TEST log warn V 2 [2 This is my first log message] 2020/04/30 12:27:14.976884 17119607 003 ECU1 LOG- TEST log warn V 2 [3 This is my first log message] 2020/04/30 12:27:14.976889 17124611 004 ECU1 LOG- TEST log warn V 2 [4 This is my first log message] 2020/04/30 12:27:14.976894 17134988 006 ECU1 DLTD INTM log info V 1 [New client connection #8 established, Total Clients : 1] 2020/04/30 12:27:15.442016 17139641 000 ECU1 DA1- DC1- control response N 1 [service(3841), ok, 4c 4f 47 00 54 45 53 54 72 65 6d 6f] 2020/04/30 12:27:15.442044 17139642 007 ECU1 DLTD INTM log info V 1 [Unregistered ApID 'LOG'] ``` The client connects to the default port 3490 of localhost to collect all messages and interprets the payload as ASCII text (```-a```). You can see lots of additional messages. These are control messages to control the flow between client and daemon. You will learn about them later. For now, you have set up a basic example have seen DLT in action. You can now experiment with this setup. What happens if you start the DLT user first and (while the DLT user is still running) the daemon?dlt-daemon-2.18.10/doc/dlt_design_specification.md000066400000000000000000001176201446635226000220310ustar00rootroot00000000000000*** SPDX license identifier: MPL-2.0 Copyright (C) 2011-2015, BMW AG This file is part of COVESA Project DLT - Diagnostic Log and Trace. This Source Code Form is subject to the terms of the Mozilla Public License (MPL), v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/ For further information see http://www.covesa.org/ *** # DLT Design Specification Alexander Wenzel 0.0.1, 2012/10/10: Initial version Luong Hong Duy Khanh 0.0.2, 2020/04/10: Update and convert to markdown format ![covesalogo](images/covesalogo.png "COVESA") ## Purpose This document specifies the usage of the DLT daemon v2 and also the internal functionality of the DLT daemon v2. The DLT daemon v2 is a complete rework of the DLT daemon v1, which is part of the COVESA 1.0 release. The DLT daemon component is based on the [AUTOSAR 4.0 standard DLT](https://www.autosar.org/fileadmin/user_upload/standards/classic/4-0/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf) (the current latest version is [R19-11](https://www.autosar.org/fileadmin/user_upload/standards/classic/19-11/AUTOSAR_SWS_DiagnosticLogAndTrace.pdf)). ## Overview ![dlt_overview](images/dlt_overview.png "DLT OVERVIEW") The DLT daemon is the central component in COVESA, where logs and traces are gathered from the DLT user and different applications, stored optionally temporarily or permanently in a file in the ECU. The DLT daemon forwards all logs and traces to a connected DLT client application, which can run directly on the COVESA system or more likely on an external tester device. The DLT client can send control messages to the daemon, e.g. to set individual log levels of applications and contexts or get the list of applications and contexts registered in the DLT daemon. In DLT, a log message contains debug information like state changes or value changes and a trace message contains information, which has passed via the Virtual Function Bus (VFB). ## Architecture ### DLT daemon The DLT daemon is the central component between the DLT clients and one or more applications using the DLT user library. #### Overview The DLT daemon is a standalone application which is running as the center of management and this is implemented as a single-thread process. The DLT daemon communicates with the DLT clients over TCP/IP connections or over a serial line with the applications using the DLT user library over named pipes (FIFOs), UNIX sockets or VSOCK sockets based on compile time configuration. The message format is specified in the DLT AUTOSAR Standard. More details concerning the exchanged user messages and their content can be found in [chapter 6](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/19-11/AUTOSAR_SWS_LogAndTrace.pdf#page=10). The main time, the DLT daemon executes the main loop, in which file and socket descriptors are watched (via poll()). If a message is received, the DLT daemon reacts. Here is a rough schematic, how the DLT daemon is structured: ![dlt_architecture](images/dlt_architecture.png "DLT ARCHITECTURE") #### Initialization During initialization of the DLT daemon, the following steps occur: - Option handling. - Option file parsed. The most important configuration files is dlt.conf - Initialization of logging facility for the DLT daemon application. The DLT daemon application by itself prints to screen, if not in daemon mode. In daemon mode, it uses the syslog daemon for log messages of the DLT daemon application. - Then the daemon enters initialization phase 1: - Enter daemon mode, if started as daemon - Initialize output of messages to the local file - Parse filter file, if specified; then set filters for file storage - Setup signal handler - Open DLT output file, if specified - After phase 1, the daemon initializes the connection handling: - Delete, create and open its own named FIFO /tmp/dlt or UNIX_SOCKET - If VSOCK support is enabled in the daemon, open, bind and listen to VSOCK socket for incoming application connections. - Open, bind and listen to TCP socket for incoming connections - Setup and open serial device, if specified - Then the daemon enters initialization phase 2: - Initialize daemon data structures - Initialize ring buffer for client connection - Check if a runtime configuration exists, if yes load all stored application and context ids, as well as all log levels and trace statuses. Store this information to a local array. - Prepare the main loop - Initialize receiver objects for socket and serial connection - Initialize binary semaphore - Create and start thread(s) for timing messages, sending of these messages is disabled at default. - After phase 2: - Initialize the offline logstorage, if the directory path is specified. - Prepare timer for system watchdog, if specified. - Prepare timer to check incoming events. - Prepare timer to send ECU version, if specified. - Initialize the gateway mode, if specified, then prepare the timer for gateway. - Now, the initialization is finished, and the DLT daemon enters the main loop. #### Main loop In the main loop, the following things occur: - Wait for event(s) on the incoming named pipe or socket, the TCP connections (the one connection for new connections, and all TCP connections from clients), and possibly on the serial device, via poll() call. - Distinguish from which socket/file descriptor the connection came, and handle them: - Event from TCP server socket (New DLT client to DLT daemon): - Create a new TCP connection - If the newly created connection is the first TCP connection, send all log messages already stored in ring buffer to DLT client. - Event from incoming named pipe (FIFO) or UNIX socket and, if enabled, VSOCK socket (from DLT user library to DLT daemon): - Use dlt receiver to read data - As long as there are DLT messages available in received data, the handle user messages type can be found at src/shared/dlt_user_shared_cfg.h - Move rest of data in front of buffer for next read attempt - Event from serial device (DLT client to DLT daemon via serial device) - Use other dlt receiver to read data - As long as there are DLT messages available in received data: - Check for DLT message type control request, and if yes process the request - Move rest of data in front of buffer for next read attempt - Event from TCP socket (DLT client to DLT daemon via TCP connection) - Use other dlt receiver to read data, and check for lost connection - As long as there are DLT messages available in received data: - Check for DLT message type control request, and if yes process the request - Move rest of data in front of buffer for next read attempt How the received user messages and control messages are handled, is described in the Appendix. #### Clean up Before exiting from DLT daemon, the following cleanup procedures occur: - Local cleanup - Destroy the connection list - Free the used memory by the organising structure of file - Uninitialise the offline trace - Free the used memory by the organising structure of file - Delete existing named pipes (FIFOs) or UNIX_SOCKET - Cleanup dlt logstorage - Close UDP connection, if specified - De-initialize the gateway, if specified. All internal data will be freed - De-Initialise the dlt daemon structure - Clear all contexts in internal context management of specific ecu - Clear all applications in internal application management of specific ecu - Release and free memory used by dynamic ringbuffer Now, the cleanup is finished, and the DLT daemon is terminated. ### DLT user library #### Overview The DLT user library is linked to each application that wants to use DLT. It encapsulates the communication with the DLT daemon and provides two interfaces: the DLT user macro interface and the DLT user functional interface. All macros from the DLT user macro interface are mapped to functions in the DLT user functional interface. The DLT user library has one additional thread, called housekeeper thread, responsible for receiving and sending messages from/to the DLT daemon. The DLT user library can be written/read from multiple threads (the threads of applications which are using DLT APIs, and DLT housekeeper thread which will send log messages to the daemon). To prevent the concurrent access to the DLT buffer, parts of functions accessible by the user interface are protected by a semaphore as well as parts of the function which is called within the thread. #### Initialization During initialization, the following things are done: - Setup internal structure including Application ID and Description (textual) of application - Get value from environment variable "DLT_LOCAL_PRINT_MODE". This variable can be used to control the local printing mode of the DLT user library. If enabled (either via "AUTOMATIC" or via "FORCE_ON"), all messages, which are prepared to be sent to the DLT daemon will also be print out locally (as ASCII string). If the environment variable is set, this value overrides the local print mode which can be set with the API function dlt_enable_local_print() or with dlt_disable_local_print() from within the application using the DLT user library. The following values are allowed: - "AUTOMATIC": Local printing is enabled, if NO DLT daemon is running. - "FORCE_ON": Local printing is always enabled. - "FORCE_OFF": Local printing is always disabled. - Clear internal context array (dynamically growing in step size DLT_USER_CONTEXT_ALLOC_SIZE, typically 500). The internal context array is NOT be kept sorted, as the DLT daemon stores for each registered context the offset position within this array, and sends this offset position for faster access of a context within this internal context array. The internal context array contains one entry for each context: - Context ID - Log level for this context - Trace status for this context - Initialize table (dynamically growing in step-size 1) with function pointers for callback functions used for injection messages - Description (textual) of context - Initialize ringbuffer for local storage of not sent messages - Setup signal handler and atexit handler - Ignore all pipe signals - Create and open own named pipe (with the name /tmp/dlt, where is the process id of the application using the DLT user library) or UNIX/VSOCK socket IPC to the DLT daemon - Open local file for storage, if specified - Initialize receiver object - Start housekeeper thread for receiving messages #### De-Initialization During de-initialization, the following things are done: - De-register application (and all contexts belonging to this application) from DLT daemon - Stop housekeeper thread - Close and remove own named pipe to the DLT daemon, if FIFO is used - Close and remove Unix socket if socket IPC is used - De-Initialize receiver object - De-Initialize ringbuffer #### Register application and context During register of the application, the following things occur: - Auto-initialize DLT user library, if necessary - Store application id to internal structure - Store application description to internal structure - Send message DLT_REGISTER_APPLICATION to DLT daemon During register of a context of the application, the following things occur: - Auto-initialize DLT user library, if necessary - Check, if context was already registered, if not, dynamically increment if required, the context array in step size DLT_USER_CONTEXT_ALLOC_SIZE, typically 500. Then store one entry for the new context to internal context array. - Send message DLT_REGISTER_CONTEXT to DLT daemon #### Unregister context and application During unregister of context, the following things occur: - Delete context from internal structures - Send message DLT_UNREGISTER_CONTEXT to DLT daemon During unregister of application, the following things occur: - Delete application from internal structures - Send message DLT_UNREGISTER_APPLICATION to DLT daemon #### Handling of messages received from DLT daemon During housekeeper thread within the DLT user library checks for newly received messages from the DLT daemon, and handles them in the following way: - **DLT_USER_MESSAGE_LOG_LEVEL** - Store received log level and trace status for the received context to the context array. - **DLT_USER_MESSAGE_INJECTION** - Check all registered callbacks for this context: - Compare service id of registered callback with received service id, if they matches: - Call registered callback function. #### Overflow handling If the named pipe/socket of the DLT daemon is full, an overflow flag is set and the message stored in a ring buffer. The next time, a message could be sent to the DLT daemon, an overflow message is sent first, then the contents of the ring buffer. If sending of this message was possible, the overflow flag is reset. #### Send log message During sending of a log message, the following things occur: - Auto-initialize DLT user library, if necessary - Initialize DLT log structure - Store log level of log message in DLT log structure - Check if log level is smaller than or equal than the stored log level of the context, under which the message should be sent. If yes continue, else don't send this log message. This is a kind of filtering on the DLT user library side. - In non-verbose mode, insert message id - Add values (int, string, raw, …) to DLT log structure: - Set argument type (only in verbose mode) - Copy content of argument to message - Set length information of argument - Set number of arguments and total length of message - Create new message with the help of the DLT log structure and handle this message: - Initialize new message - Add headers (standard header, extended header, storage header, ...) to this message - If logging to a file is enabled, write the log message to file - Print message locally, if requested by environment variable - Check if connection to DLT daemon was lost and try to reattach to daemon. - Check for overflow flag and try to send overflow message. - Try to send message to DLT daemon, and check for return values. This can be: - data could not be written - handle not open or pipe/socket error - other error condition - no error, all right - If sending failed, put this message in the ring buffer for later sending. - Handle these error conditions. #### Send network trace message During sending of a network trace message, the following things occur: - Auto-initialize DLT user library, if necessary - Check for trace status of network trace message to be sent. - If Trace status equals on: - Initialize DLT log structure - Set trace status in DLT log structure to network trace type of message - Copy length of network message header to DLT log structure - Copy data of network message header to DLT log structure - Copy length of network trace payload to DLT log structure - Copy data of network trace payload to DLT log structure - Create new message with the help of the DLT log structure and handle this message #### Register callback function for injection message During registration of a callback function for an injection message, then following steps are executed: - Check if the environment variable DLT\_DISABLE\_INJECTION\_MSG\_AT\_USER is set. - If yes: - libdlt will ignore all data/messages from dlt-daemon, including: loglevel change, custom injection messages ... - If no (default): - libdlt will handle all data/messages from dlt-daemon as normal. - For the specified context, check if service id is already in the table of the registered callbacks (this table is dynamically growing in steps of one entry). - If yes: - Stored service id is set to service id to be registered - Stored callback function pointer is set to callback function pointer to be registered - If no: - Increase the number of callbacks for this context - Store service id in callback table - Store function pointer in callback table #### Android: Thread termination On Android, `pthread_cancel` is not available in bionic. So current implementation uses *SIGUSR1* and `pthread_kill` to terminate housekeeper thread. Due to this, application which is linked to DLT library should not define *SIGUSR1*. ### Communication between DLT daemon and DLT user library The communication mechanism (IPC) used between DLT daemon and DLT user library are named pipes (FIFOs), UNIX sockets or VSOCK sockets, based on compile time configuration). During the startup of the DLT daemon, the DLT daemon creates and opens the IPC (FIFOs or UNIX_SOCKET) on the configured path called /tmp/dlt. If a DLT user application using the DLT user library wants to send log messages to the DLT daemon, this IPC is used. During the startup of the DLT user application using the DLT user library, it creates and opens the same IPC type of DLT daemon. If the DLT daemon wants to send the control messages to the DLT user application, this IPC is used. - When the FIFOs IPC is used, a named pipe called /tmp/dltpipes/dlt, where is the process id of the DLT user application. Each DLT user application creates its own named pipe to communicate with the DLT daemon. - When the UNIX_SOCKETS IPC is used, the DLT user application just needs to connect to the opened socket port of DLT daemon. All DLT user applications use the same UNIX_SOCKETS port to communicate with the DLT daemon. The exchanged messages are described in the [chapter 7.1](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/19-11/AUTOSAR_SWS_LogAndTrace.pdf#page=12). In a system with a single process tree where PIDs are unique, the FIFOs IPC shall work well. In a system with the multiple nested process trees, each process tree maintains an entirely isolated set of processes. Because of that, PIDs are not unique anymore and a DLT User application running in the parent PID namespace might have the same PID as another DLT User application running in the child PID namespace. Since a DLT User application creates its own FIFO based on its PID (getpid()), the DLT Daemon has to deal with multiple applications registering itself with the same PID, which is impossible. To solve this problem, the UNIX_SOCKETS based communication is used. The UNIX_SOCKETS IPC is also supported in the Non-linux platforms (eg: QNX). If the daemon is built with VSOCK socket support, it can also receive log messages from processes running in virtual machines. The communication mechanism between the daemon and the DLT user library on the host is still FIFOs or UNIX sockets. But the DLT user library for the system running in the virtual machine can be built to use VSOCK sockets for sending log messages to the daemon. See "man vsock" for more information about VSOCK sockets. This is an alternative to using a [multinode](dlt_multinode.md) setup for receiving DLT log messages from processes in a virtualized environment. No passive daemon(s) are required and it works without having a network configured between the guest and the host. ### Place of message creation The following table shows, where the certain types of DLT messages are created. The message types are described in more detail in the AUTOSAR Specification for Diagnostic Log and Trace. | Type of message | DLT client | DLT daemon | DLT library | | ---------------- | :--------: | :--------: | :---------: | | Control request | X | X | | | Control response | | X | | Log message | | | X | | Trace message | | | X | This table shows, that: - DLT messages of message type control request are created in the DLT client, and then sent to the DLT daemon. - DLT messages of message type control response (to a control request) are created in the DLT daemon, and then sent to the DLT client. - DLT messages of type log and of type trace are created in the DLT user library, then passed (via the named pipe of the DLT daemon) to the DLT daemon, which forwards them to the connected DLT clients. ### Message flow The following figure shows the overall flow of messages. ![dlt_message_flow](images/dlt_message_flow.png "DLT MESSAGE FLOW") ## Appendix ### Messages exchanged between DLT daemon and DLT user library There are several user messages (each has its own message identifier DLT_USER_MESSAGE_*) which will are exchanged between DLT daemon and DLT user library, and will be described in the following sub-chapters. From DLT user library to DLT daemon: - **DLT_USER_MESSAGE_REGISTER_APPLICATION** - **DLT_USER_MESSAGE_UNREGISTER_APPLICATION** - **DLT_USER_MESSAGE_REGISTER_CONTEXT** - **DLT_USER_MESSAGE_UNREGISTER_CONTEXT** - **DLT_USER_MESSAGE_LOG** - **DLT_USER_MESSAGE_OVERFLOW** - **DLT_USER_MESSAGE_APP_LL_TS** From DLT daemon to DLT user library: - **DLT_USER_MESSAGE_LOG_LEVEL** - **DLT_USER_MESSAGE_INJECTION** Each of the following messages has a message header with the following information: - Pattern: DUH0x01 - Message identifier #### User Message: Register Application This message is sent by the DLT user library once per application to register the application to the DLT daemon. It contains the following information: - The application id of the application to be registered - The process id of the process using the DLT user library. This information is required, if the DLT daemon wants to send something to the DLT user library. - The length of the following description. - The application description. #### User Message: Unregister Application This message is sent by the DLT user library once per application to unregister the application from the DLT daemon. It contains the following information: - The application id of the application to be unregistered - The process id of the process using the DLT user library. #### User Message: Register Context This message is sent by the DLT user library once for each context which should be registered to the DLT daemon. It contains the following information: - The application id of the application to be registered - The context id of the application to be registered - Each created context is stored with its associated information in a dynamically growing array in the DLT user library. The index in this array is sent. - The process id of the process using the DLT user library. This information is required, if the DLT daemon wants to send something to the DLT user library. - The initial log level of the context - The initial trace status of the context - The length of the following description. - The context description. #### User Message: Unregister Context This message is sent by the DLT user library once for each context which should be unregistered from the DLT daemon. It contains the following information: - The application id of the application to be unregistered - The context id of the application to be unregistered - The process id of the process using the DLT user library. #### User Message: Log This is the standard log/trace message send by the DLT user library to the DLT daemon. It contains the following information: - A standard DLT message header as specified in the AUTOSAR R4.0 DLT standard. - An extended DLT message header as specified in the AUTOSAR R4.0 DLT standard. - The payload of the DLT message #### User Message: Overflow This message is sent from the DLT user library to the DLT daemon, if there was an overflow during writing to the DLT daemon named pipe or socket IPC. It contains no further information. #### User Message: Application Log Level and Trace Status This message is sent from the DLT user library to the DLT daemon, when the overall Log Level and Trace Status for the whole DLT application should be set from within the DLT application. It contains the following information: - The application id - The Log Level to be set for the whole application - The Trace Status to be set for the whole application #### User Message: Log Level If the log level or trace status is changed, or initialized, this message is sent from the DLT daemon to the DLT user library to store the current log level and trace status for filtering in the DLT user library. It contains the following information: - The new set log level - New set trace status. - Each created context is stored with its associated information in a dynamically growing array in the DLT user library. The index in this array is sent. #### User Message: Injection This message is sent from the DLT daemon to the DLT user library, if an injection message was received by the DLT daemon from a DLT client. Via the context, the appropriate application and its named pipe can be identified. The injection message is then passed to this named pipe. It contains the following information: - Each created context is stored with its associated information in a dynamically growing array in the DLT user library. The index in this array is sent. - Service ID of the injection message - Length of the following injection message - The contents of the injection message ### DLT daemon: User message handling Following things occur for the received DLT user messages: - **DLT_USER_MESSAGE_REGISTER_APPLICATION** - Add all information about application to a local application array (dynamically growing in a predefined step size (DLT_DAEMON_APPL_ALLOC_SIZE, typically 500)). The array is always being kept sorted (via qsort()). Finding entries in this array is done by a binary search (via bsearch()). - Open named pipe (or Unix socket IPC if specified) to DLT application using the DLT user library with process id . The name of the pipe (or Unix socket IPC) is /tmp/dlt - **DLT_USER_MESSAGE_UNREGISTER_APPLICATION** - Remove all information about this application from local application array, and remove all information of all contexts belonging to this application from local context array. The arrays are always being kept sorted, without empty entries in between. Dynamically shrinking of this array is NOT implemented. - **DLT_USER_MESSAGE_REGISTER_CONTEXT** - Add all information about context to local context array (dynamically growing in a predefined step size (DLT_DAEMON_CONTEXT_ALLOC_SIZE, typically 1000)). The array is always being kept sorted (via qsort()). Finding entries in this array is done by a binary search (via bsearch()). - Send log level and trace status to DLT user library for this context. Therefore, the DLT_USER_MESSAGE_LOG_LEVEL is used. - **DLT_USER_MESSAGE_UNREGISTER_CONTEXT** - Remove all information about this context from local context array. The array is always being kept sorted, without empty entries in between. Dynamically shrinking of this array is NOT implemented. - **DLT_USER_MESSAGE_OVERFLOW** - Set internal flag for overflow. - Create and send DLT control message response overflow to all connected TCP connections, and optionally to serial device, if connected. If the message was sent, reset the internal flag for overflow. - **DLT_USER_MESSAGE_LOG** - Overwrite ECU id, if requested - Set storage header - Check for filters of message, if no filter is set, or filter is matching: - Possibly display message as specified in the options. - Whole message display in hex - Whole message display in ASCII - Show message headers only - Store message to output file - Set serial header in front of message, if specified. - Create and try to send DLT message to all DLT clients connected via TCP connection, and optionally via serial device. - If the message could not be sent, store the message to a local ring buffer. The ring buffer internally uses a variable length for the buffered elements, and therefore uses the memory available for the buffer the best way possible. If the buffer is full, the oldest messages are silently discarded, until there is enough space for the message to be stored in the ring buffer. - **DLT_USER_MESSAGE_APP_LL_TS** - For all contexts belonging to the specified application: - Set specified log level - Set specified trace status - Send specified log level and trace status to DLT client library ### DLT daemon: Control message handling If the DLT daemon receives a control message request from a DLT client, it handles it in the following way. First the service id of the message is detected, and if it is no injection message, the following things occur: - DLT_SERVICE_ID_SET_LOG_LEVEL - Check if received log level is other then already set log level. If yes: - Store new log level to local array. - Send new log level to DLT user library for this context. Therefore, the DLT_USER_MESSAGE_LOG_LEVEL is used. Note that the DLT would take the log level of Logstorage as the highest priority. So even if log level is changed from client, it will be overwritten by Logstorage definition. - Send DLT control response to DLT client, with status of operation. - DLT_SERVICE_ID_SET_TRACE_STATUS - Check if received trace status is other then already set trace status. If yes: - Store new trace status to local array. - Send new trace status to DLT user library for this context. Therefore, the DLT_USER_MESSAGE_LOG_LEVEL is used. - Send DLT control response to DLT client, with status of operation. - DLT_SERVICE_ID_GET_LOG_INFO - Create answer message for DLT control response. All kinds of requests are supported: - Application/Context: - All applications and all contexts - One application and all of its contexts - One application with one context. - Request type (as specified in the AUTOSAR DLT Standard, 1 and 2 are not specified): - 3: Application ID, Context ID - 4: Application ID, Context ID, Log Level - 5: Application ID, Context ID, Trace Status - 6: Application ID, Context ID, Log Level, Trace Status - 7: Application ID, Context ID, Log Level, Trace Status, Description - Answer is of the corresponding type 3-7, or of type 8 (no matching context ids found), or of type 2 (error). - Send DLT control response answer to DLT client. - DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL - Send DLT control response with default log level to DLT client. - DLT_SERVICE_ID_STORE_CONFIG - Store configuration files with currently registered application ids and context ids as well as currently set log levels and trace statuses to configuration files. If these files exists, they will be read in when the DLT daemon is started next time. - Send DLT control response to DLT client. - DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT - Delete the stored configuration files, if they exists. - Set default log level and trace status to initial values, and inform all applications using the default log level and trace status about the new defaults. - Send DLT control response to DLT client. - DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_SET_VERBOSE_MODE - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_SET_MESSAGE_FILTERING - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_SET_TIMING_PACKETS - Set flag to start/stop sending of timing messages in thread. - Send DLT control response to DLT client. - DLT_SERVICE_ID_GET_LOCAL_TIME - Send DLT control response with local time to DLT client. - DLT_SERVICE_ID_USE_ECU_ID - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_USE_SESSION_ID - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_USE_TIMESTAMP - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_USE_EXTENDED_HEADER - Send DLT control response "Not supported" to DLT client - DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL - Check if received default log level is other than already stored default log level. If yes: - Store new default log level to internal structure. - Send a DLT_USER_MESSAGE_LOG_LEVEL to all DLT clients containing the new default log level, which uses a context which is set to default log level. - Send DLT control response to DLT client, with status of operation. - DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS - Check if received default trace status is other than already stored default trace status. If yes: - Store new default trace status to internal structure. - Send a DLT_USER_MESSAGE_LOG_LEVEL to all DLT clients containing the new default trace status, which uses a context which is set to default trace status. - Send DLT control response to DLT client, with status of operation. - DLT_SERVICE_ID_GET_SOFTWARE_VERSION - Send DLT control response containing a software version string to DLT Client. - The software version string contains: - the package version of the package dltv2, e.g. "2.0.0" - the package status of the package dltv2, e.g. "alpha, beta, final" - the overall subversion revision number for the package dltv2, e.g. "2300" - DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW - Try to send DLT control response containing the status of the internal flag for overflow. If the message could be send, reset the internal flag for overflow. For handling of the injection message, the following steps occur: - Create new user message DLT_USER_MESSAGE_INJECTION from received DLT control request message, and send this user message to the DLT application using the DLT user library. ### Mapping to files Here is a description, how the whole project is structured and which files exists. The following table shows a top level view of the available Git repositories: | Directory | Description | | --------- | ----------- | | dlt | DLT Daemon and Library implementation; command line utilities, examples and test programs | | dlt_viewer | DLT Client GUI (DLT Viewer): QT based implementation | As this document has the focus on the DLT Daemon and the DLT user library, only the "dlt" directory is introduced in more detail: | Directory | Description | | --------- | ----------- | | doc | Documentation | | include | Include files, installed on target | | src | Source Code | | src/shared | Shared source code (between DLT daemon and DLT user library) | | src/adaptor | Adaptors to DLT daemon:dlt-adaptor-stdin (for connection over stdin) dlt-adaptor-udp (for connection over UDP) | | src/console | Console utilities: logstorage, dlt-control, dlt-convert, dlt-passive-node-ctrl, dlt-receive, and dlt-sortbytimestamp | | src/daemon | DLT Daemon | | src/examples | Examples for usage of the DLT user library:dlt-example-user (Macro IF) anddlt-example-user-func (Function IF) andwintestclient (MS Windows based test client) | | src/lib | DLT library functions | | src/tests | Test programs:dlt-test-client and dlt-test-user for automatic tests, dlt-test-stress for stress tests, dlt-test-internal for internal tests | | testscripts | Several supporting scripts | The DLT daemon implementation uses the following files, besides DLT functions from files from the shared directory: | File | Description | | --------- | ----------- | | dlt-daemon.c | DLT daemon implementation | | dlt-daemon.h | Header file for dlt-daemon.c | | dlt-daemon_cfg.h | Compile time configuration for DLT daemon, Part1 | | dlt_daemon_common.c | Supporting functions for a DLT daemon implementation | | dlt_daemon_common.h | Header file for dlt_daemon_common.c | | dlt_daemon_common_cfg.h | Compile time configuration for DLT daemon, Part2 | The DLT user library contains the following files: | File | Description | | --------- | ----------- | | dlt_user.c | Implementation of functions, available via the DLT user library interface. | | dlt_user_cfg.h | Compile time configuration for dlt_user.c | | dlt_client.c | Functions required for DLT Client implementations | | dlt_client_cfg.h | Compile time configuration for dlt_client.c | The shared directory contains the following files: | File | Description | | --------- | ----------- | | dlt_common.c | Common helper functions, such as: Print functions for DLT messages, Functions for handling DLT Ids, Filter functions, DLT message handling functions, Functions for handling DLT files, DLT receiver functions, Log handling, Ringbuffer functions, Setting and checking of storage header | | dlt_common_cfg.h | Compile time configuration for dlt_common.c | | dlt_user_shared.c | Shared functions, required by the DLT daemon and the DLT user library, such as: Setting and checking the user header, Sending DLT messages over named pipes (FIFOs) or UNIX/VSOCK sockets | | dlt_user_shared.h | Header file for dlt_user_shared.c | | dlt_user_shared_cfg.h | Compile time configuration for dlt_user_shared.c | The public available include directory contains the following header files: | File | Description | | --------- | ----------- | | dlt.h | Overall include file, includes dlt_common.h and dlt_user.h | | dlt_common.h | Include file for dlt_common.c | | dlt_user.h | Include file for dlt_user.c, contains the "User API" functions | | dlt_user_macros.h | Include file for dlt_user.c, contains the "User API" macros | | dlt_client.h | Include file for dlt_client.c | | dlt_protocol.h | DLT protocol specfic definitions and macros | | dlt_types.h | Definition of types, must be adapted to the target architecture and compiler toolchain. | ### Description of used structures in implementation The following important structures are used in the DLT Daemon and DLT User Library: | Structure | Description | | --------- | ----------- | | DltDaemonFlags | Flags and values, set over command line during start-up of DLT daemon | | DltDaemonLocal | Global variables of the DLT Daemon, grouped together in a struct | | DltDaemon | Parameters of the DLT daemon | | DltDaemonApplication | Parameters of an application, used within DLT daemon | | DltDaemonContext | Parameters of a context, used within DLT daemon | | DltUserControlMsg... | User control messages | | DltContext | Each context is represented with this structure | | DltContextData | Temorary used structure for constructing a log message | | DltUserInjectionCallback | One entry in dynamic callback table for callback function | | dlt_ll_ts_type | Table managing all contexts (and loglevels and trce statuses) within DLT user library, contains dynamicly growing array with "DltUserInjectionCallback" entries | | DltUser | Parameters for DLT user library application, contains dynamically growing array with "dlt_ll_ts_type" entries | | DltStorageHeader | Storage header | | DltStandardHeader | Structure for standard header of a DLT message | | DltStandardHeaderExtra | Structure for standard header extra fields of a DLT message | | DltExtendedHeader | Structure for extended header of a DLT message | | DltService... | Structures for control messages (requests and responses) | | DltFilter | Structure to store filter parameters | | DltMessage | Structure to organize a DLT message, includes pointers to DltStorageHeader, DltStandardHeader, DltStandardHeaderExtra, and DltExtendedHeader, data of message is stored within a private buffer within this structure | | DltFile | Structure to organize access to a DLT File | | DltReceiver | Structure to organize the receiving of data | | DltRingbuffer | Structure to organize a ring buffer | #### Implementation specifics - The following preconditions were given prior to implementation: - C-only implementation for the DLT daemon and the DLT user library - Implementation of common functions, which can be used in a command line utility as well as in a Graphical UI - Implementation of C+\+ like classes in C, see dlt_common.c and dlt_common.h - The current implementation of the DLT daemon and DLT user library is tested with gcc under Ubuntu 16.04 on Intel HW; Android and QNX on IMX, RCAR, Qualcomm ARM target boards. - It is assumed that packed structs are always stored in memory in the order specified within the packed struct. - The implementation is multithread safe. - Initialize DLT application and contexts, then forking and using the forked process, will lead to unclear behavior (or in the worst case to a crash), as the forked process uses another process id as the parent process. Instead, initialize the DLT application and contexts in the forked process. - Calling of DLT logging and tracing functions within a callback function for injections are not supported, and will lead to an unclear behavior.dlt-daemon-2.18.10/doc/dlt_example_user.md000066400000000000000000000045171446635226000203510ustar00rootroot00000000000000% DLT-EXAMPLE-USER(1) # NAME **dlt-example-user** - Console based application for sending a custom dlt message # SYNOPSIS **dlt-example-user** \[**-h**\] \[**-g**\] \[**-a**\] \[**-k**\] \[**-d** delay\] \[**-f** filename\] \[**-S** filesize\] \[**-n** count\] \[**-m** mode\] \[**-l** level\] \[**-A** appID\] \[**-C** contextID\] \[**-t** timeout\] \[**-s** size\] message # DESCRIPTION Sends the given message as DLT messages to DLT daemon or prints the raw DLT messages into a local file. ## OPTIONS -h : Display a short help text. -g : Switch to non-verbose mode (Default: verbose mode). -a : Enable local printing of DLT messages (Default: disabled). -k : Send marker message. -d : Milliseconds to wait between sending messages (Default: 500). -f : Use local log file instead of sending to daemon. -S : Set maximum size of local log file (Default: UINT\_MAX). -n : Number of messages to be generated (Default: 10). -m : Set log mode 0=off, 1=external, 2=internal, 3=both. -l : Set log level, level=-1..6 (Default: 3). -A : Set app ID for send message (Default: LOG). -C : Set context ID for send message (Default: TEST). -t : Set timeout when sending messages at exit, in ms (Default: 10000 = 10sec). -r : Send raw data with specified size instead of string. # EXAMPLES Send "HelloWorld" with default settings (10 times, every 0.5 seconds) as DLT message to dlt-daemon:: dlt-example-user HelloWorld Set app ID to `APP1`, context Id to `TEST` and log level to `error` for send message:: dlt-example-user -l 2 -A APP1 -C TEST HelloWorld Send 100 DLT messages every second:: dlt-example-user -n 100 -d 1000 HelloWorld Send "HelloWorld" can log to local file with maximum size 1000 bytes:: dlt-example-user -f helloworld.dlt -S 1000 HelloWorld # EXIT STATUS Non zero is returned in case of failure. # Notes The default descriptions for application and context registration are used irrespective of the IDs that could be set. App will always register with "Test Application for Logging" and context with "Test Context for Logging". # AUTHOR Darian Biastoch (dbiastoch@de.adit-jv.com) # COPYRIGHT Copyright (C) 2020 ADIT GmbH. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt_extended_network_trace.md000066400000000000000000000071421446635226000224040ustar00rootroot00000000000000# Extended Network Trace Back to [README.md](../README.md) ## Introduction The extended network trace allows the user to send or truncate network trace messages that are larger than the normal maximum size of a DLT message. This interface will be enabled if following calls are supported on the target: - mq\_open - mq\_close - mq\_unlink - mq\_send - mq\_receive ## Protocol When truncation of messages is allowed, the truncated messages will be wrapped into a special message which indicates that a network trace message was truncated and what was the original size of the message. Segmented messages are sent in multiple packages. The package stream is prepended with a start message indicating which contains a unique handle for this stream, size of data to follow, count of segments to follow and segment size. Each segment contains the stream handle, segment sequence number, the data and data length. Finally after sending all the data segments, one more packet is sent to indicate the end of the stream. ## Truncated package Truncated message can be sent using the following function: ` int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate) ` This will send a packet in the following format: Value | Description | Type :--- | :--- | :--- NWTR | Package identifier | STRING header | nw_trace header and it's length | RAW size | Original size of the message | UINT payload | The truncated nw_trace payload | RAW ## Segmented messages User can send a segmented network trace message asynchronously using: ` void dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload) ` This will start a background thread and return immediately. User can also send all the required packages one by one using: ` int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len) ` ` int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload) ` ` int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkTraceType nw_trace_type) ` *NOTE*: It is not recommended to use these functions unless you really have to. ## Segmented start packet The first packet in the stream is the header: Value | Description | Type :--- | :--- | :--- NWST | Package identifier | STRING streamhandle | Unique identifier for all packages in the stream | UINT header | nw_trace header and it's length | RAW payloadsize | Size of the complete payload in this stream | UINT segmentcount | Number of segments to follow | UINT segmentlen | Size of one segment | UINT ## Data segment After the header, follows a stream of data segments. Value | Description | Type :--- | :--- | :--- NWCH | Package identifier | STRING streamhandle | Unique identifier for all packages in the stream | UINT sequence | Sequence number of this segment | UINT data | One segment of the original nw_trace | RAW ## End packet After all the segments have been sent, an End identifier is sent. Value | Description | Type :--- | :--- | :--- NWEN | Package identifier | STRING streamhandle | Unique identifier for all packages in the stream | UINT ## Author Lassi Marttala ## COPYRIGHT Copyright (C) 2011 - 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . dlt-daemon-2.18.10/doc/dlt_filetransfer.md000066400000000000000000000214311446635226000203360ustar00rootroot00000000000000# DLT Filetransfer Back to [README.md](../README.md) ## Overview DLT is a reusable open source software component for standardized logging and tracing in infotainment ECUs based on the AUTOSAR 4.0 standard. The goal of DLT is the consolidation of the existing variety of logging and tracing protocols on one format. ## Introduction to DLT Filetransfer With DLT Filetransfer it is possible store the binary data of a file to the automotive dlt log. The file will be read in binary mode and put as several chunks to a DLT\_INFO log. With a special plugin of the dlt viewer, you can extract the embedded files from the trace and save them. It can be used for smaller files, e.g. HMI screenshots or little coredumps. ## Protocol The file transfer is at least one single transaction. This transaction consist of three main types of packages: - header package - one or more data packages - end package ## Header Package Every filetransfer must begin with the header package using: ` int dlt_user_log_file_header(DltContext *fileContext,const char *filename) ` Header Header Package Protocol: Value | Description :--- | :--- FLST | Package flag fileserialnumber | Inode of the file used as file serialnumber filename | Use the absolute filepath to the file filesize | Filesize of the file file creation date | Creation date of the file number of packages | Counted packages which will be transferred in the data packages BUFFER_SIZE | Defined buffer size to reconstruct the file FLST | Package flag ## Data Package After the header package was sent, at least one or more data packages can be sent using: ` int dlt_user_log_file_data(DltContext *fileContext,const char *filename,int packageToTransfer, int timeout) ` Data Data Package Protocol: Value | Description :--- | :--- FLDA | Package flag fileserialnumber | Inode of the file used as file serialnumber PackageNumber | Transferred package Data | Payload containing data FLDA | Package flag ## End Package After all data packages were sent, the end package must be sent to indicate that the filetransfer is over using: ` int dlt_user_log_file_end(DltContext *fileContext,const char *filename,int deleteFlag) ` End Package Protocol: Value | Description :--- | :--- FLFI | Package flag fileserialnumber | Inode of the file FLFI | Package flag ## File information The library offers the user the possibility to log informations about a file using the following method without transferring the file itself using: ` dlt_user_log_file_infoAbout(DltContext *fileContext, const char *filename) ` File Information Protocol: Value | Description :--- | :--- FLIF | Package flag fileserialnumber | Inode of the file used as file serialnumber filename | Use the absolute filepath to the file filesize | Filesize of the file file creation date | Creation date of the file number of packages | Counted packages which will be transferred in the data packages FLIF | Package flag ## File transfer error ```c //! Error code for dlt_user_log_file_complete #define ERROR_FILE_COMPLETE -300 //! Error code for dlt_user_log_file_complete #define ERROR_FILE_COMPLETE1 -301 //! Error code for dlt_user_log_file_complete #define ERROR_FILE_COMPLETE2 -302 //! Error code for dlt_user_log_file_complete #define ERROR_FILE_COMPLETE3 -303 //! Error code for dlt_user_log_file_head #define ERROR_FILE_HEAD -400 //! Error code for dlt_user_log_file_data #define ERROR_FILE_DATA -500 //! Error code for dlt_user_log_file_data #define DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED -501 //! Error code for dlt_user_log_file_end #define ERROR_FILE_END -600 //! Error code for dlt_user_log_file_infoAbout #define ERROR_INFO_ABOUT -700 //! Error code for dlt_user_log_file_packagesCount #define ERROR_PACKAGE_COUNT -800 ``` If an error happens during file transfer, the library will execute the method: ` void dlt_user_log_file_errorMessage(DltContext *fileContext, const char *filename, int errorCode) ` File transfer error Protocol: Value | Description :--- | :--- FLER | Package flag error code | see error codes above linux error code | standard linux error code fileserialnumber | Inode of the file used as file serialnumber filename | Use the absolute filepath to the file filesize | Filesize of the file file creation date | Creation date of the file number of packages | Counted packages which will be transferred in the data packages FLER | Package flag If the file doesn't exist, the content of the error package is a little bit different: Value | Description :--- | :--- FLER | Package flag error code | see error codes above linux error code | standard linux error code filename | Use the absolute filepath to the file FLER | Package flag ## Using Using DLT Filetransfer There are two ways to use the filetransfer - Automatic filetransfer in one step - Header, data and end package order handeld by the user ### Automatic Call - dlt\_user\_log\_file\_complete The method needs the following arguments: - fileContext -> Context for logging the file to dlt - filename -> Use the absolute file path to the file - deleteFlag -> Flag if the file will be deleted after transfer. 1->delete, 0->notDelete - timeout -> Deprecated. The order of the packages is to send at first the header, then one or more data packages (depends on the filesize) and in the end the end package. The advantage of this method is, that you must not handle the package ordering by your own. Within dlt\_user\_log\_file\_complete the free space of the user buffer will be checked. If the free space of the user buffer < 50% then the actual package won't be transferred and a timeout will be executed. If the daemon crashes and the user buffer is full, the automatic method is in an endless loop. ### Manual Manual starting filetransfer with the following commands: - dlt\_user\_log\_file\_head | Transfers only the header of the file - dlt\_user\_log\_file\_data | Transfers only one single package of a file - dlt\_user\_log\_file\_end | Tranfers only the end of the file This ordering is very important, so that you can save the transferred files to hard disk on client side with a dlt viewer plugin. The advantage of using several steps to transfer files by your own is, that you are very flexible to integrate the filetransfer in your code. An other difference to the automatic method is, that only a timeout will be done. There is no check of the user buffer. ## Important for integration You should care about blocking the main program when you intergrate filetransfer in your code. Maybe it's useful to extract the filetransfer in an extra thread. Another point is the filesize. The bigger the file is, the longer takes it to log the file to dlt. ## Example dlt filetransfer For an example file transfer you can use ```bash Usage: dlt-example-filetransfer \[options\] \ Filetransfer example with DLT Package Version: 2.2.0 , Package Revision: 1666, build on May 28 2011 02:18:19 Command: -f file - File to transfer (absolute path) Options: -a apid - Set application id to apid (default: FLTR) -c ctid - Set context id to ctid (default: FLTR) -t ms - Timeout between file packages in ms (minimum 20 ms) -d - Flag to delete the file after the transfer (default: false) -i - Flag to log file infos to DLT before transfer file (default: false) -h - This help ``` ## Testing dlt filetransfer When you call "sudo make install", some automatic tests will be installed. Start the test using the following command from bash: ` dlt-test-filetransfer ` It's important that the dlt-filetransfer example files are installed in /usr/share/dlt-filetransfer which will be done automatically by using "sudo make install". If not, use -t and -i options to specify the path to a text file and an image file. - testFile1Run1: Test the file transfer with the condition that the transferred file is smaller as the file transfer buffer using dlt\_user\_log\_file\_complete. - testFile1Run2: Test the file transfer with the condition that the transferred file is smaller as the file transfer buffer using single package transfer - testFile2Run1: Test the file transfer with the condition that the transferred file is bigger as the file transfer buffer using dlt\_user\_log\_file\_complete. - testFile2Run2: Test the file transfer with the condition that the transferred file is bigger as the file transfer buffer using single package transfer - testFile3Run1: Test the file transfer with the condition that the transferred file does not exist using dlt\_user\_log\_file\_complete. - testFile3Run2: Test the file transfer with the condition that the transferred file does not exist using single package transfer - testFile3Run3: Test which logs some information about the file. ## AUTHOR Christian Muck ## COPYRIGHT Copyright (C) 2012 - 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . dlt-daemon-2.18.10/doc/dlt_for_developers.md000066400000000000000000001123121446635226000206670ustar00rootroot00000000000000# How to DLT for developers Back to [README.md](../README.md) Table of Contents 1. [DLT Example Application](#DLT-Example-Application) 2. [General Rules for Logging](#General-Rules-for-Logging) 3. [The use of Log Levels](#The-use-of-Log-Levels) 4. [DLT Library Runtime Configuration](#DLT-Library-Runtime-Configuration) 5. [DLT API Usage](#DLT-API-Usage) 6. [DLT injection messages](#DLT-Injection-Messages) 7. [Log level changed callback](#Log-level-changed-callback) 8. [Disable injection messages](#Disable-injection-messages) 9. [Use DLT in library](#Use-DLT-in-library) ## DLT Example Application To use DLT from an application, it has to be linked against the DLT library. When the DLT daemon is installed on the system, there will be a shared library with the name libdlt.so which provides the interface for applications to get a connection to the DLT daemon. The library path and include path must be set in the build environment prior to building a program using the shared dlt library. By default, the header file "dlt.h" is located in a directory called "dlt/" within the standard include directory. This example gives an overview of DLT usage inside an application by using a minimal code example. Detailed information about the API can be found later in this document. ``` #include DLT_DECLARE_CONTEXT(ctx); /* declare context */ int main() { DLT_REGISTER_APP("TAPP", "Test Application for Logging"); DLT_REGISTER_CONTEXT(ctx, "TES1", "Test Context for Logging"); /* … */ DLT_LOG(ctx, DLT_LOG_ERROR, DLT_CSTRING("This is an error")); /* … */ DLT_UNREGISTER_CONTEXT(ctx); DLT_UNREGISTER_APP(); return 0; } ``` DLT is quite easy to use. The first thing a developer has to do is to include the dlt header file. DLT contexts can be statically declared using the macro shown in next line. Firstly, a DLT application has to be registered inside the main function. For this, an application identifier APID and application description has to be specified. Afterwards, one or more DLT contexts could be specified. To log messages in verbose mode, the DLT\_LOG macro can be used. As parameter, the logging context, the log level and a variable list of parameters have to be specified. DLT requires each parameter to be strongly typed using DLT type macros. In this example, DLT\_CSTRING is used to specify a constant string. On application cleanup, all DLT contexts, as well as the DLT application have to be unregistered. ### DLT with cmake To use DLT with CMake, the recommended way is to use the CMake Config file that is being generated as part of installation. You can thus: ``` find_package(automotive-dlt REQUIRED) ... target_link_libraries(myapp PRIVATE Genivi::dlt) ``` which lets your project automatically gain all necessary compile and link flags needed by libdlt, including the include directories. The generated CMake Config file follows "Modern CMake" convention and only exports an IMPORTED CMake target; it does not set any variables, except for the `automotive-dlt_FOUND` variable that can be used to treat DLT as an optional dependency. The generated CMake config file (which is implicitly being used when you call `find_package(automotive-dlt)`) by default only adds the top-level directory to the compiler's header search path; this requires that users' #include directives are written in the regular form e.g. ``. If you want to be able to use the legacy form `` as well (as is always allowed by the pkg-config module for backwards compatibility reasons), you can configure DLT with the CMake option `-DWITH_LEGACY_INCLUDE_PATH=On` in order to achieve that. ### DLT with pkg-config Alternatively to the CMake integration detailed above, it is also possible to use DLT via pkg-config. This can also be done with CMake's PkgConfig module as well. #### PkgConfig usage with "Modern CMake" Here, you let the PkgConfig module create targets as well; the target's name is however determined by the PkgConfig module: ``` find_package(PkgConfig) pkg_check_modules(DLT REQUIRED IMPORTED_TARGET automotive-dlt) ``` As per "Modern CMake", there are again no variables to be added, but only a CMake target to be added to the link libraries: ``` target_link_libraries(myapp PRIVATE PkgConfig::DLT) ``` #### PkgConfig usage with "Legacy CMake" (<3.0) Here, you let the PkgConfig module only create variables, but not targets: ``` find_package(PkgConfig) pkg_check_modules(DLT REQUIRED automotive-dlt) ``` to INCLUDE\_DIRECTORIES (or, since CMake 2.8.11, TARGET\_INCLUDE\_DIRECTORIES), add ``` ${DLT_INCLUDE_DIRS} ``` and to TARGET\_LINK\_LIBRARIES: ``` ${DLT_LINK_LIBRARIES} (preferred, for CMake >= 3.12) ${DLT_LIBRARIES} (otherwise) ``` The contents of `${DLT_LIBRARIES}` do not include the library's path (e.g. `-L/path/to/lib`), so if the library resides in a location that is not on the linker's default search path, you'll either have to add that path to LINK\_DIRECTORIES: ``` link_directories(${DLT_LIBRARY_DIRS}) ``` or, alternatively, not use `${DLT_LIBRARIES}`, but `${DLT_LDFLAGS}` instead, which combines `${DLT_LIBRARIES}` and `${DLT_LIBRARY_DIRS}`: ``` target_link_libraries(myapp ${DLT_LDFLAGS}) ``` ### Limitation On Android, definition of `SIGUSR1` in DLT application shall be avoided since DLT library blocks `SIGUSR1` to terminate housekeeper thread at exit. ## General Rules for Logging ### Be Smart Before implementing logging in code one should take a second to think about a concept first. Often strategic places in the software can be used as a central place for logging. Such places are often interfaces to other SW components. Use the solution with the smallest impact. Avoid logging the "good cases" but log e.g. in your error handling sections – you will need error handling anyway. In case an error occurred more logs don't matter as long as your regular code produces little logs. Keep in mind that tracing comes with a price tag – you are working in an embedded environment where CPU, memory and Bandwidth are sparse. ### Avoid high frequency outputs Certain events occur very often in a system – some of them dozens of times per second. In such a case do not implement logging for each occurrence. One example is the screen frame rate. Instead of printing a log for each frame rate aggregate the information and print an average once every five seconds or – even better – report once a second if the frame rate is below a critical value. ### Combine multiple messages Please always consider that each Log message creates a certain overhead. In case of DLT as the way of logging each has a header of 20 bytes. Therefore please aggregate information. In this way all necessary information is always combined. Please always use a human readable format; use identifiers for the different values, be consistent with separators. This helps to work with the data, especially when log messages are processed by scripts. Such scripts often use regular expressions – make the job easier! For example don't write log entries like this: > Total frames: 1000 > > Sync frames: 0 > > Reem frames: 0 > > Valid frames: 0 > > Urgent frames: 1 Better aggregate Information into a single message: > Frame info: total=1000, sync=0, reem=1000, valid=0, urgent=1 ### Do not use ASCII-art Information should be "on your fingertips". Logging is a tool to ease crushing bugs, not to win a computer art contest. → Don't use ASCII Art! ### Do not create charts using ASCII Charts can be a great help to visualize what is going on in the system. This type can be nicely done by a trace analysis or in case of usage of the DLT Viewer, in a Plugin. It certainly should always be done in a post processing step. Doing this on the target is a waste of resources. ### Avoid tracing in loops Bad example: ``` for(int index=0; index export DLT\_INITIAL\_LOG\_LEVEL="EXA1:CON1:5;EXA1:CON2:6" If the log level of all applications and contexts shall be initialized, then: > export DLT\_INITIAL\_LOG\_LEVEL="::2" If the log level for all contexts of application "EXA1" shall be initialized, then: > export DLT\_INITIAL\_LOG\_LEVEL="EXA1::2" If the log level of context "CON1" shall be initialized, then: > export DLT\_INITIAL\_LOG\_LEVEL=":CON1:2" In case only the log level of context "CON1" of application "EXA1" shall be initialized, and other contexts will be ignored, then: > export DLT\_INITIAL\_LOG\_LEVEL="::0;EXA1:CON1:2" 2. If DLT\_INITIAL\_LOG\_LEVEL variable is not exported in the environment, log level for it each context can be changed in the config file (/etc/dlt.conf). Default log level will be 4 (DLT\_LOG\_INFO) > ContextLogLevel = 4 3. DLT user can use dlt\_register\_context\_ll\_ts() api to initialize log level for each context. Example: > //Register new context to daemon, with initial log level is DLT\_LOG\_VERBOSE > > dlt\_register\_context\_ll\_ts(&con\_exa1, "CON", "First context", DLT\_LOG\_VERBOSE, DLT\_TRACE\_STATUS\_OFF); The priority of context log level would be as follows: - Priority 1: Using dlt\_register\_context\_ll\_ts() api - Priority 2: Using environment variable DLT\_INITIAL\_LOG\_LEVEL - Priority 3: Setting in config file dlt.conf ### Local print mode Sometimes it might be useful to print DLT messages for debugging directly to console. To force the library to do so, the following environment variable can be exported: > export DLT\_LOCAL\_PRINT\_MODE=FORCE\_ON ### Library buffer size The DLT library contains a message buffer in case the DLT Daemon is not started yet or the connection to DLT Daemon is temporarily lost. The buffer is allocated while library initialization with a minimum size. If more messages need to be stored, the buffer grows in defined steps up to a maximum size. In case messages are flushed to DLT Daemon, the buffer is reduced to its minimal size. The default values and the environment variable names to set these values are described below: | | Default value [in bytes] | Environment variable name --- | --- | --- Minimal size | 50000 | DLT\_USER\_BUFFER\_MIN Maximal size | 500000 | DLT\_USER\_BUFFER\_MAX Step size | 50000 | DLT\_USER\_BUFFER\_STEP For example, to limit the maximum buffer size to 250k bytes, the following can be exported: > export DLT\_USER\_BUFFER\_MAX=250000 ## DLT API Usage ### Register application **Important note** - DLT may not be used in a forked child until a variant of exec() is called, because DLT is using non async-signal-safe functions. - DLT\_REGISTER\_APP is asynchronous. It may take some milliseconds to establish the IPC channel. Because of this, you might lose messages if you log immediately after registration. Typically this is not a problem, but may arise especially with simple examples. The DLT application has to be registered as early as possible during the initialization of the application by calling DLT\_REGISTER\_APP(). It is only allowed to call DLT\_REGISTER\_APP() once per application. An application id (maximum four characters) has to be specified and must be unique within an ECU. In this example "MAPP" is used. And also a description for the application can be specified, here it is "Test Application for Logging". ``` int main(int argc, const char* argv[]) { DLT_REGISTER_APP("MAPP","Test Application for Logging"); } ``` DLT\_REGISTER\_APP is asynchronous. It may take some milliseconds to establish the IPC channel. Because of this, messages might be lost if logs are emitted immediately after registering. Typically this is not a problem, but may arise especially with simple examples. ### Get application ID To get the application ID value, requested to allocate a char array at least 4 byte length and input to the function call. The application ID will be stored in this input char array. #### MACRO ``` DLT_GET_APPID(appid); ``` #### Function ``` dlt_get_appid(appid); ``` ### Define and register all logging contexts As many contexts as needed can be defined. These contexts can be declared as contexts in different C or CPP files. But each context is only allowed to be declared once. Therefore a unique variable name for each context has to be used. ``` DLT_DECLARE_CONTEXT(myContext1); DLT_DECLARE_CONTEXT(myContext2); DLT_DECLARE_CONTEXT(myContext3); ``` If contexts from another C or CPP file shall be used, these contexts can be imported by calling: ``` DLT_IMPORT_CONTEXT(myContext1); DLT_IMPORT_CONTEXT(myContext2); DLT_IMPORT_CONTEXT(myContext3); ``` After the application is registered and contexts are declared, contexts need to be registered early during initialization of the application. DLT\_REGISTER\_CONTEXT() shall not be called before DLT\_REGISTER\_APP(). During registration of each context, a context id must be provided (maximum four characters long). In this example "TESX" is used. Also a description for the context can be provided; here it is "Test Context X for Logging". A context can also be registered with a predefined Log Level and Trace Status by using the Macro DLT\_REGISTER\_CONTEXT\_LL\_TS. The third context is registered using this method. ``` int main(int argc, const char* argv[]) { DLT_REGISTER_APP("MAPP","Test Application for Logging"); DLT_REGISTER_CONTEXT(myContext1,"TES1","Test Context 1 for Logging"); DLT_REGISTER_CONTEXT(myContext2,"TES2","Test Context 2 for Logging"); DLT_REGISTER_CONTEXT_LL_TS(myContext3, "TES3","Test Context 3 for Logging", DLT_LOG_DEBUG, DLT_TRACE_STATUS_OFF); } ``` Note: Please be aware that it might be taken up to a second until the synchronization of loglevel between DLT Daemon and application is done. ### Unregister contexts and application Before terminating the application registered contexts and at last the application need to be unregistered. ``` int main(int argc, const char* argv[]) { /* business logic */ DLT_UNREGISTER_CONTEXT(myContext1); DLT_UNREGISTER_CONTEXT(myContext2); DLT_UNREGISTER_CONTEXT(myContext3); DLT_UNREGISTER_APP(); return 0; } ``` ### Logging command DLT provides functions that allow for flexible construction of messages with an arbitrary number of arguments. Both Verbose and Non-Verbose messages are supported, with different APIs. Sending a message using these functions require multiple function calls, for starting message construction, adding the arguments, and sending off the message. The following table shows an example of all 4 types for logging using a constant string and an integer. #### Verbose vs. Non-Verbose API The following sections show examples of all 4 types for logging e.g. a string and an integer. ##### MACRO ###### Verbose ``` DLT_LOG(ctx, DLT_LOG_INFO, DLT_STRING("ID: "), DLT_UINT32(123)); ``` ###### Non-Verbose ``` DLT_LOG_ID(ctx, DLT_LOG_INFO, 42 /* unique message ID */, DLT_STRING("ID: "), DLT_UINT32(123)); ``` ##### Function ###### Verbose ``` if (dlt_user_log_write_start(&ctx, &ctxdata, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&myctxdata, "ID: "); dlt_user_log_write_uint32(&myctxdata, 123); dlt_user_log_write_finish(&myctxdata); } ``` ###### Non-Verbose ``` if (dlt_user_log_write_start_id(&ctx, &ctxdata, DLT_LOG_INFO, 42) > 0) { dlt_user_log_write_string(&myctxdata, "ID: "); dlt_user_log_write_uint32(&myctxdata, 123); dlt_user_log_write_finish(&myctxdata); } ``` #### Statefulness of Verbose/Non-Verbose The library uses a global state that applies to all logging commands being used. If the library is in global "Verbose" mode, both the "Verbose" and the "Non-Verbose" API calls shown above will always result in Verbose messages being sent. However, if the library is in global "Non-Verbose" mode, it is possible to send both Verbose and Non-Verbose messages in a single session; all "Verbose" APIs will send Verbose messages, and all "Non-Verbose" APIs will send Non-Verbose messages. It does not make sense to send a Non-Verbose message via a Verbose API, as there is then no sensible message ID, which is however mandatory when sending Non-Verbose messages. #### Switching Verbose and Non-Verbose To switch Verbose/Non-Verbose mode (Verbose mode is default), the following APIs are available: ##### MACRO ``` DLT_VERBOSE_MODE(); DLT_NONVERBOSE_MODE(); ``` ##### Function ``` dlt_verbose_mode(); dlt_nonverbose_mode(); ``` #### String arguments For string arguments, you can choose between ASCII and UTF-8 encoding. This encoding is written into the argument header, so that the receiver knows what to expect when parsing the message. In addition, you can also choose between null-terminated strings and (potentially) non-null-terminated ones. The latter often arise in C++ code when using classes such as std::string\_view, which does not provide an accessor method that returns a null-terminated C-string. Copying data out of a std::string\_view thus requires to copy only the desired number of characters. For instance, using Verbose mode: ``` std::string_view line = "Name: Ford Prefect"; std::string_view key = line.substr(0, 4); std::string_view value = line.substr(6); if (dlt_user_log_write_start_id(&ctx, &ctxdata, DLT_LOG_INFO, 42) > 0) { dlt_user_log_write_constant_utf8_string(&myctxdata, "key"); dlt_user_log_write_sized_utf8_string(&myctxdata, key.data(), key.size()); dlt_user_log_write_constant_utf8_string(&myctxdata, "value"); dlt_user_log_write_sized_utf8_string(&myctxdata, value.data(), value.size()); dlt_user_log_write_finish(&myctxdata); } ``` #### Using custom timestamps The timestamp that is transmitted in the header of a DLT message is usually generated automatically by the library itself right before the message is sent. If you wish to change this, e.g. because you want to indicate when an event occured, rather than when the according message was assembled, you can supply a custom timestamp. Compared to the example above, two macros are defined for convenience: ``` uint32_t timestamp = 1234567; /* uptime in 0.1 milliseconds */ if (gflag) { /* Non-verbose mode */ DLT_LOG_ID_TS(ctx, DLT_LOG_INFO, 42, timestamp, DLT_INT(num), DLT_STRING(text)); } else { /* Verbose mode */ DLT_LOG_TS(ctx, DLT_LOG_INFO, timestamp, DLT_INT(num), DLT_STRING(text)); } ``` If you wish to (or have to) use the function interface, you need to set the flag to make use of the user-supplied timestamp manually after calling dlt_user_log_write_start(): ``` if (dlt_user_log_write_start(&ctx, &ctxdata, DLT_LOG_INFO) > 0) { ctxdata.use_timestamp = DLT_USER_TIMESTAMP; ctxdata.user_timestamp = (uint32_t) 1234567; dlt_user_log_write_string(&myctxdata, "ID: "); dlt_user_log_write_uint32(&myctxdata, 123); dlt_user_log_write_finish(&myctxdata); } ``` #### Send log message with given buffer DLT applications can prepare a log message buffer by themselves instead of calling logging parameters. There are two benefits; the applications can reduce API calls to DLT library as much as possible so that the APIs won't block the application's sequence, and dynamic allocation can be avoided in DLT library during runtime. The applications should prepare following values in order to use this functionality: - *char buffer[DLT_USER_BUF_MAX_SIZE]*: Buffer which contains one log message payload - *size_t size*: Buffer size - *int32_t args_num*: Number of arguments One argument in the buffer consists of following: | Length(byte) | Description | |----------------|--------------| | 4 | Type Info | | x | Data Payload | DLT Applications need to simulate what are done in logging parameters to store data to the buffer (type info given to the buffer, etc.), otherwise the behavior is undefined. Also important note here is that the functionality works properly only with these function combination: - *Start logging*: dlt\_user\_log\_write\_start\_w\_given\_buffer - *Finish logging*: dlt\_user\_log\_write\_finish\_w\_given\_buffer Since the function does not allocate memory dynamically, it could lead to segmentation fault or memory leak with different APIs. It is mandatory to check if dlt_user_is_logLevel_enabled is returning DLT_RETURN_TRUE before calling dlt_user_log_write_start_w_given_buffer (see below code example). ##### Macro No macro interface is available as of now. ##### Function ``` /* Example: Prepare one log message with uint16 */ char buffer[DLT_USER_BUF_MAX_SIZE] = {0}; size_t size = 0; int32_t args_num = 0; uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT; memcpy(buffer + size, &(type_info), sizeof(uint32_t)); size += sizeof(uint32_t); uint16_t data = 1234; memcpy(buffer + size, &data, sizeof(uint16_t)); size += sizeof(uint16_t); args_num++; /* Give the buffer to DLT library */ if (dlt_user_is_logLevel_enabled(&ctx,DLT_LOG_INFO) == DLT_RETURN_TRUE) { if (dlt_user_log_write_start_w_given_buffer(&ctx, &ctxdata, DLT_LOG_INFO, buffersize, args_num) > 0) { dlt_user_log_write_finish_w_given_buffer(&ctxdata); } } ``` #### Attributes In verbose mode, log message arguments can contain attributes. A "name" attribute describes the purpose or semantics of an argument, and a "unit" attribute describes its unit (if applicable - not all argument data types support having a "unit" attribute). ``` dlt_user_log_write_float64_attr(&myctxdata, 4.2, "speed", "m/s"); ``` In non-verbose mode, these attributes are not added to the message. ### Logging parameters The following parameter types can be used. Multiple parameters can be added to a single log message. The size of all logging parameters together should not exceed 1390 bytes, including the DLT message header. Type | Description --- | --- DLT\_STRING(TEXT) | String DLT\_STRING\_ATTR(TEXT,NAME) | String (with attribute) DLT\_SIZED\_STRING(TEXT,LENGTH) | String with known length DLT\_SIZED\_STRING\_ATTR(TEXT,LENGTH,NAME) | String with known length (with attribute) DLT\_CSTRING(TEXT) | Constant string (not sent in non-verbose mode) DLT\_CSTRING\_ATTR(TEXT,NAME) | Constant string (with attribute; not sent in non-verbose mode) DLT\_SIZED\_CSTRING(TEXT,LENGTH) | Constant string with known length (not sent in non-verbose mode) DLT\_SIZED\_CSTRING\_ATTR(TEXT,LENGTH,NAME) | Constant string with known length (with attribute; not sent in non-verbose mode) DLT\_UTF8(TEXT) | Utf8-encoded string DLT\_UTF8\_ATTR(TEXT,NAME) | Utf8-encoded string (with attribute) DLT\_SIZED\_UTF8(TEXT,LENGTH) | Utf8-encoded string with known length DLT\_SIZED\_UTF8\_ATTR(TEXT,LENGTH,NAME) | Utf8-encoded string with known length (with attribute) DLT\_RAW(BUF,LENGTH) | Raw buffer DLT\_RAW\_ATTR(BUF,LENGTH,NAME) | Raw buffer (with attribute) DLT\_INT(VAR) | Integer variable, dependent on platform DLT\_INT\_ATTR(VAR,NAME,UNIT) | Integer variable, dependent on platform (with attributes) DLT\_INT8(VAR) |Integer 8 Bit variable DLT\_INT8\_ATTR(VAR,NAME,UNIT) |Integer 8 Bit variable (with attributes) DLT\_INT16(VAR) | Integer 16 Bit variable DLT\_INT16\_ATTR(VAR,NAME,UNIT) | Integer 16 Bit variable (with attributes) DLT\_INT32(VAR) | Integer 32 Bit variable DLT\_INT32\_ATTR(VAR,NAME,UNIT) | Integer 32 Bit variable (with attributes) DLT\_INT64(VAR) | Integer 64 bit variable DLT\_INT64\_ATTR(VAR,NAME,UNIT) | Integer 64 bit variable (with attributes) DLT\_UINT(VAR) | Unsigned integer variable DLT\_UINT\_ATTR(VAR,NAME,UNIT) | Unsigned integer variable (with attributes) DLT\_UINT8(VAR) | Unsigned 8 Bit integer variable DLT\_UINT8\_ATTR(VAR,NAME,UNIT) | Unsigned 8 Bit integer variable (with attributes) DLT\_UINT16(VAR) |Unsigned 16 Bit integer variable DLT\_UINT16\_ATTR(VAR,NAME,UNIT) |Unsigned 16 Bit integer variable (with attributes) DLT\_UINT32(VAR) | Unsigned 32 Bit integer variable DLT\_UINT32\_ATTR(VAR,NAME,UNIT) | Unsigned 32 Bit integer variable (with attributes) DLT\_UINT64(VAR) | Unsigned 64 bit integer variable DLT\_UINT64\_ATTR(VAR,NAME,UNIT) | Unsigned 64 bit integer variable (with attributes) DLT\_BOOL(VAR) | Boolean variable DLT\_BOOL\_ATTR(VAR,NAME) | Boolean variable (with attribute) DLT\_FLOAT32(VAR) | Float 32 Bit variable DLT\_FLOAT32\_ATTR(VAR,NAME,UNIT) | Float 32 Bit variable (with attributes) DLT\_FLOAT64(VAR) | Float 64 Bit variable DLT\_FLOAT64\_ATTR(VAR,NAME,UNIT) | Float 64 Bit variable (with attributes) DLT\_HEX8(UINT\_VAR) | 8 Bit hex value DLT\_HEX16(UINT\_VAR) | 16 Bit hex value DLT\_HEX32(UINT\_VAR) | 32 Bit hex value DLT\_HEX64(UINT\_VAR) | 64 Bit hex value DLT\_BIN8(UINT\_VAR) | 8 Bit binary value DLT\_BIN16(UINT\_VAR | 16 Bit binary value DLT\_PTR(PTR\_VAR) | Architecture independent macro to print pointers ### Network Trace It is also possible to trace network messages. The interface, here DLT\_NW\_TRACE\_CAN, the length of the header data and a pointer to the header data, the length of the payload data and a pointer to the payload data, must be specified. If no header or payload is available, the corresponding length must be set to 0, and the corresponding pointer must be set to NULL. ``` DLT_TRACE_NETWORK(mycontext, DLT_NW_TRACE_CAN, headerlen, header, payloadlen, payload); ``` Note that when DLT_NETWORK_TRACE_ENABLE is disabled, the mqueue.h will not be included. ### DLT C++ Extension The DLT C++ extension was added to DLT in version 2.13. This approach solves the need to specify the type of each argument for applications written in C++ by using C++ templates and function overloading. The following shows the usage of this API extension: ``` #define DLT_LOG_CXX(CONTEXT, LOGLEVEL, ...) #define DLT_LOG_FCN_CXX(CONTEXT, LOGLEVEL, ...) DLT_LOG_CXX(ctx, DLT_LOG_WARN, 1.0, 65); DLT_LOG_FCN_CXX(ctx, DLT_LOG_WARN, "Test String", 145, 3.141); ``` This works as well with C++ standard containers like std::vector, std::map, std::list. Of course, the logToDlt function can be overloaded to print user defined structures or classes. ``` struct MyStruct { int64_t uuid; int32_t interfaceId; int32_t registrationState; }; template<> inline int logToDlt(DltContextData & log, MyStruct const & value) { int result = 0; result += dlt_user_log_write_string(&log, "("); result += logToDlt(log, value.uuid); result += dlt_user_log_write_string(&log, ","); result += logToDlt(log, value.interfaceId); result += dlt_user_log_write_string(&log, ","); result += logToDlt(log, value.registrationState); result += dlt_user_log_write_string(&log, ")"); if (result != 0) { result = -1; } return result; } ``` ### Check if a specific Log Level is enabled In some scenarios it might be necessary to check if a specific Log Level is enabled or not, before log data is send to DLT Library. The macro is defined as follows: ``` DLT_IS_LOG_LEVEL_ENABLED(CONTEXT,LOGLEVEL) ``` In general, there is no need to check the active Log Level to decide if a log message can be send to not. This is handled inside the DLT\_LOG macro. ## DLT Injection Messages DLT provides an interface to register injection callbacks which can be sent by a DLT Client (e.g. DLT Viewer) to the application. An injection message callback is always registered for a specific context. The API to register a callback is defined as follows: ``` DLT_REGISTER_INJECTION_CALLBACK(CONTEXT, SERVICEID, CALLBACK); ``` Injection message Service IDs must be bigger than 0xFFF, because IDs up to 0xFFF are reserved for DLT Daemon control messages. The callback function needs to have the following definition: ``` int injection_callback(uint32_t service_id, void *data, uint32_t length); ``` For example, registering a callback function for a specific context with the service ID 0x1000 might look like: ``` DLT_REGISTER_INJECTION_CALLBACK(mycontext, 0x1000, injection_callback); ``` From DLT Viewer, an injection message can be sent by right-clicking the corresponding context in the project view ("Send injection"). A dialog will pop up to specify the injection data as shown below. ![alt text](images/dlt-viewer-send-injection-dialog.png "DLT Viewer Send Injection Callback") ## Log level changed callback A callback function can be registered to be called whenever the Log Level of a context changed. The usage is similar to DLT\_REGISTER\_INJECTION\_CALLBACK. ``` DLT_REGISTER_LOG_LEVEL_CHANGED_CALLBACK(CONTEXT, CALLBACK) ``` ## Disable injection messages An environment variable named `DLT_DISABLE_INJECTION_MSG_AT_USER` could be used in case dlt application wants to ignore all data/messages from dlt-daemon completely. To use: ``` export DLT_DISABLE_INJECTION_MSG_AT_USER=1 ``` To clear: ``` unset DLT_DISABLE_INJECTION_MSG_AT_USER ``` ## Use DLT in library There are cases where a library wants to use DLT interface to output its log message. In such case, applications and contexts can be registered using following way. ### Application registration The library can check if an application is already registered or not by `DLT_GET_APPID()` API. If returned application ID is not NULL, it can be considered that application was already registered previously. If it's NULL, then application can be registered. ```Example // Check if an application is already registered in this process char appid[DLT_ID_SIZE]; DLT_GET_APPID(&appid); if (appid[0] != '\0') { printf("Application is already registered with AppID=[%s]\n", appid); } else { DLT_REGISTER_APP("APP", "Application for library xxx"); } ``` ### Context registration The same context ID can be used among different applications, so context can be registered as usual. dlt-daemon-2.18.10/doc/dlt_gateway.conf.5.md000066400000000000000000000054711446635226000204100ustar00rootroot00000000000000% DLT_GATEWAY.CONF(5) # NAME **dlt_gateway.conf** - DLT configuration file for gateway # DESCRIPTION The configuration file dlt_gateway.conf allows to configure the different runtime behaviour of gateway in Multinode feature. The configuration file is written in an INI file format and contains information about different connected passive nodes. If Multinode feature is enabled, dlt-daemon loads by default the configuration file /etc/dlt_gateway.conf. An alternative configuration file can be loaded by changing `GatewayConfigFile` in dlt.conf(5). # GENERAL SECTION ### Interval Time interval for reconnection to passive Node in second. Default: 1 # PASSIVENODE SECTION Each passive node’s connection parameters are specified in a unique numbered separate section ([PassiveNode{1,2, …N}]). Example: [PassiveNode1] ### IPaddress Because TCP is the only supported communication channel, the IPaddress and Port of the Passive DLT Daemon has to be specified. IP Address of passive node. Mandatory ### Port TCP port. Default 3490 is used if no port is specified. Default: 3490 ### EcuID ECU identifier of passive node. Mandatory. ### Connect With the Connect property it is possible to specify when the Gateway DLT Daemon shall connect to the passive node. Default: OnStartUp The following values are allowed: OnStartup The Gateway DLT Daemon tries to connect to the Passive DLT Daemon immediately after the Gateway DLT Daemon is started. OnDemand The Gateway DLT Daemon tries to connect to the Passive DLT Daemon when it receives a connection request. ### Timeout Stop connecting to passive node, if not successful after 10 retries. After of retries, the connection to passive Node is marked as DISABLED. It means there is no any retry anymore. Set to 0 for endless retry. Default: 10 ### SendControl Send following control messages after connection is established. Optional. Default: disabled Supported Control messages: DLT_SERVICE_ID_GET_LOG_INFO 0x03 DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL 0x04 DLT_SERVICE_ID_GET_SOFTWARE_VERSION 0x13 ### SendSerialHeader Send Serial Header with control messages. Value in dlt.conf(5) is used as default if not specified. Default: disabled ### SendPeriodicControl Send following control messages periodically. Default: disabled Format: control:interval[in seconds] # AUTHOR Thanh Bui Nguyen Quoc (thanh.buinguyenquoc (at) vn (dot) bosch (dot) vn) # COPYRIGHT Copyright (C) 2020 Advanced Driver Information Technology, Bosch and DENSO. License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. # BUGS See Github issue: # SEE ALSO **dlt.conf(5)**, **dlt-daemon(1)** dlt-daemon-2.18.10/doc/dlt_glossary.md000066400000000000000000000077061446635226000175260ustar00rootroot00000000000000# Glossary Throughout the documentation specific terms are used. Those are defined below. Back to [README.md](../README.md) Term | Definition ----- | ---- Application ID | Application Identifier is a unique identifier for an application registered at the DLT Daemon. It is defined as 8bit ASCII character. e.g. "APP1". Each Application can have several sub-components each having a unique context ID Context ID | This is a user defined ID to group log and trace messages produced by an application. Each Application ID can own several Context IDs and the Context IDs shall be unique within an Application ID. The identification of the source of a log and trace message is done with a pair of Application ID and Context ID. It is composed by four 8 bit ASCII characters. Control Message | A control message is send by a connected client application (e.g. Log Viewer) to the DLT Daemon that includes an action request. E.g. change the Log level of a certain application). DLT Daemon | The DLT Daemon is the central component which receives all logs and traces from the DLT user applications. The DLT Daemon forwards all logs and traces to a connected DLT client (e.g. Log Viewer) or stores them optionally in a file on the target. DLT Library | Provides applications (esp. DLT users) with an API to produce DLT messages and to handle DLT Control Messages accordingly. DLT User | A DLT User is a type of application that produces log messages. It typically uses the DLT library to produce the messages and resembles an ECU. DLT Viewer | The DLT Viewer is the COVESA Log Viewer implementation. It is a Qt-based desktop application able to run on Windows and Linux operating systems. Further information and source code can be found here: https://github.com/COVESA/dlt-viewer Gateway DLT Daemon | In a Multi-Node system, the DLT Daemon running on the Node directly connected to a Log Viewer is called Gateway DLT Daemon (if configured as Gateway). It forwards log messages from Passive DLT Daemons to Log Viewers and command/control messages from Log Viewer(s) to Passive DLT Daemon(s). Injection Message | An injection message is a control message for a specific DLT application. Log Consumer | A log consumer is an application connected to the DLT Daemon (DLT Client) that receives log messages and stores (e.g. Logstorage) or displays them (e.g. Log Viewer). A log consumer can run on the same operating system or on a remote host pc. Log Level | A log level defines a classification for the severity grade of a log message. Log Viewer | A client application or tool used to view log information on a host pc. DLT-viewer is the supported Log Viewers. Multi-Node System | A system with more than one node. Node | A node represents an operating system, e.g. Linux, AUTOSAR or a container having its own DLT Daemon instance. Only one DLT Daemon should run on a node. In the context of DLT, Node and ECU describe the same thing. Node Identifier | Unique Identifier of a node (node ID). In DLT, the node ID is defined by __EcuID__ set in _dlt.conf_ configuration file. Passive DLT Daemon | A passive DLT Daemon runs on a node without direct connection to a Log Viewer. All communication between a passive DLT Daemon and a Log Viewer has to be send via the Gateway DLT Daemon. Trace Status | The trace status provides information if a trace message should be send. Supported States are ON or OFF Verbose / Non-Verbose Mode | The DLT supports Verbose and Non-Verbose Mode. In _Verbose_ mode, all logging data including a type description is provided within the payload. Furthermore, Application ID and Context ID are transferred as part of the message header. In _Non-Verbose_ mode, description about the sender (Application ID, Context ID) as well as static strings and data description is not part of the payload. Instead, this information is stored in a file that needs to be parsed by a Log Viewer. The log message contains a unique message ID instead which allows a mapping between received log message and information stored in the file.dlt-daemon-2.18.10/doc/dlt_kpi.md000066400000000000000000000115301446635226000164340ustar00rootroot00000000000000# DLT KPI Back to [README.md](../README.md) ## Overview *DLT KPI* is a tool to provide log messages about **K**ey **P**erformance **I**ndicators to the DLT Daemon. The log message format is designed to be both readable by humans and to be parsed by DLT Viewer plugins. The information source for the dlt-kpi tool is the /proc file system. ## Message format *DLT KPI* logs its messages as human readable ASCII messages, divided in multiple arguments. The tool will log messages in user defined intervals, which can be set in the configuration file dlt-kpi.conf. ## Identifiers and their datasets The logged messages always start with a three character long identifier as first argument. After this identifier, they can contain multiple datasets separated in the remaining arguments. The datasets contain information separated by semicolons. The order and meaning of those information chunks is defined below. The following will explain the meaning to each three-character-identifier and each information chunk of the datasets associated with this identifier. The example messages all contain only one dataset - in real use, many messages will contain multiple datasets (one per argument). *NOTE*: Arguments are delimited by spaces when shown in ASCII, but dlt-viewer plugins can easily access each argument separately by certain methods, which makes arguments useful for parsing. ### NEW This identifies a message that contains datasets describing newly created processes. The datasets in these messages have the following form: `[PID];[Parent PID];[Commandline]` Example message: `NEW 21226;1;/usr/libexec/nm-dispatcher` ### STP This identifies a message that contains datasets describing processes that have ended since the last interval. The datasets in these messages have the following form: `[PID]` Example message: `STP 20541` ### ACT This identifies a message that contains datasets describing active processes. These are processes that have consumed CPU time since the last interval. The datasets in these messages have the following form: `[PID];[CPU time in milliseconds per second];[RSS bytes];[CTX-switches since last interval];[I/O bytes];[I/O wait time in milliseconds per second]` Example message: `ACT 20503;10;389;3;1886649;0` *NOTE:* The *CPU time* value is the active time of a process in milliseconds, divided by the number of CPU cores. So this value should never get greater than 1000ms, which would mean 100% CPU usage. ### CHK This identifies a message that is logged for each process in a certain interval. These messages can be used to get a list of currently existing processes and to keep a plugin, that tracks running processes, up to date if messages were lost or if the commandlines have changed. The datasets in these messages have the following form: `[PID];[Commandline]` Example message: `CHK 660;/sbin/audispd` ### IRQ This identifies a message that contains datasets describing the numbers of interrupts that occurred on each CPU. The datasets in these messages have the following form: `[IRQ name];cpu[CPU number];[Number of total interrupts];` Example message: `IRQ 0;cpu0:133;cpu1:0; 1;cpu0:76827;cpu1:0;` ## Synchronization messages Because the messages can get too long for logging and segmented network messages don't allow for individually set arguments, the datasets can be splitted into multiple messages of the same type (i.e. they have the same identifier). This can make it difficult for an observer (human or machine) to keep track of currently valid information. For example, one can't be sure if a process is part of the list of currently active processes or not, or if this message was part of an older interval that simply arrived too late. So, to correctly associate these messages to each other, each group of potentially "segmented" messages is surrounded by two synchronization messages which start with the same identifier, followed by the codes _BEG_ (for the opening sync message) or _END_ (for the closing sync message). Synchronization messages do not contain datasets. Example (Messages have been shortened for simplicity): ```c ACT BEG ACT 21768;10;417;3;672075;0 19284;20;15857;303654;22932174;0 1826;20;39781;4404293;154392870;0 ACT 1635;10;10696;8412557;375710810;0 990;10;22027;1176631;0;0 ACT END ``` Only processes that are part of this group are active at this moment. *ACT* messages that came before this message-group are invalid now. It can also happen that, between a *BEG* and an *END* sync message, there are messages of other types. So, plugins should not expect these message groups to always be a "solid block", but react on each message individually and dynamically, and store the logged information until the closing *END* message arrives. ## AUTHOR Sven Hassler ## COPYRIGHT Copyright (C) 2015 BMW AG. License MPL-2.0: Mozilla Public License version 2.0 . dlt-daemon-2.18.10/doc/dlt_multinode.md000066400000000000000000000055601446635226000176570ustar00rootroot00000000000000# DLT MultiNode Back to [README.md](../README.md) ## Overview MultiNode allows to connect DLT Daemons running on different operating systems, e.g. in a virtualized environment. The central component is the Gateway DLT Daemon which connects external DLT Clients, like the DLT Viewer running on a host computer with Passive DLT Daemons running on nodes without a physical connection to external DLT clients. All communication between passive nodes and DLT Viewer has to be sent via the Gateway node. The Gateway node forwards log messages coming from passive nodes to all connected DLT clients. The Gateway DLT Daemon also forwards command and control requests coming from DLT clients to the corresponding passive node. ![alt text](images/dlt-multinode.png "DLT MultiNode") ## Precondition The dlt.conf configuration file which is read by each DLT Daemon on start-up contains an entry to specify the ECU identifier (node identifier). It has to be ensured, that **each DLT Daemon in the System has a unique ECU** identifier specified. The ECU identifier is included in every DLT Message and is used to distinguish if a DLT message has to be forwarded to a passive node or handled by the Gateway DLT Daemon itself. ## Configuration The dlt.conf configuration file provides an option to enable the Gateway functionality of a DLT Daemon. The default setting is 0 (Off), which means the Gateway functionality is not available. ``` # Enable Gateway mode (Default: 0) GatewayMode = 1 ``` ### Gateway Configuration File The MultiNode configuration file has to be loaded by the Gateway DLT Daemon during startup. Example: ``` [General] Interval=1 [PassiveNode1] ; IP Address. (Mandatory) IPaddress = 192.168.2.32 ; TCP port. Default 3490 is used if no port is specified Port = 3495 ; Passive node ECU identifier. (Mandatory) EcuID = ECU2 ; Connection to passive node only on demand. Default ‘OnStartup’ if not specified Connect = OnDemand ; Stop connecting to passive node, if not successful after 10 retries. ; Set to 0 for endless retry. Timeout = 10 ; Send following control messages after connection is established SendControl=0x03, 0x13 ; Send SerialHeader with control messages. Value in dlt.conf is used ; as default if not specified SendSerialHeader=1 ``` For more details, please refer to [dlt_gateway.conf.5.md](dlt_gateway.conf.5.md) ## Using DLT MultiNode ``` Usage: dlt-passive-node-ctrl [options] Send a trigger to DLT daemon to (dis)connect a passive node or get current passive node status. Options: -c Connection status (1 - connect, 0 - disconnect) -h Usage -n passive Node identifier (e.g. ECU2) -s Show passive node(s) connection status -t Specify connection timeout (Default: 10s) -S Send message with serial header (Default: Without serial header) -R Enable resync serial header -v Set verbose flag (Default:0) ``` dlt-daemon-2.18.10/doc/dlt_offline_logstorage.md000066400000000000000000000260441446635226000215270ustar00rootroot00000000000000# DLT Offline Logstorage Back to [README.md](../README.md) ## Introduction to DLT Offline Logstorage Logstorage is a mechanism to store DLT logs on the target system or an external device (e.g. USB stick) connected to the target. It can be seen as an improvement of the Offline Trace functionality which is already part of DLT. Logstorage provides the following features: - Store logs in sets of log files defined by configuration files - Log file content is configurable - Configurable options are: - Application identifier (single entry, list, wildcard) - Context identifier (single entry, list, wildcard) - Log level - ECU identifier - Log files are configurable in terms of: - File name and naming scheme - File size - Number of files - Log message synchronization strategy is configurable - Trigger start and stop logging using a control application - Integration into Udev device management ## Configuration ### General Configuration General configuration is done inside dlt.conf. The following configuration options exist: ``` ############################################################################## # Offline logstorage # ############################################################################## # Store DLT log messages, if not set offline logstorage is off (Default: off) # Maximum devices to be used as offline logstorage devices # OfflineLogstorageMaxDevices = 1 # Path to store DLT offline log storage messages (Default: off) # OfflineLogstorageDirPath = /opt # File options # Appends timestamp in log file name, Disable by setting to 0 (Default: 1) # OfflineLogstorageTimestamp = 0 # Appends delimiter in log file name, allowed punctutations only (Default: _) # OfflineLogstorageDelimiter = _ # Wrap around value for log file count in file name (Default: UINT_MAX) # OfflineLogstorageMaxCounter = 999 # Maximal used memory for Logstorage Cache in KB (Default: 30000 KB) # OfflineLogstorageCacheSize = 30000 ``` ### Configuration file format For DLT daemon to store logs the configuration file named “dlt\_logstorage.conf” should be present in external storage or internal storage device (= given path in the file system). ``` [Filter] # filter configration name LogAppName= # Name of application to store logs from. Multiple applications can be separated by "," and ".*" denotes all applications ContextName= # Name or names of contexts to store logs from. Multiple contexts can be separated by "," and ".*" denotes all contexts of the application LogLevel= # Define log level, e.g. DLT_LOG_INFO or DLT_LOG_FATAL File= # Base name of the created files that containing the logs, e.g. "example". For further file naming scheme configurations see man dlt.conf FileSize= # Maximum file size in bytes NOFiles= # Number of created files before oldest is deleted and a new one is created SyncBehavior= # Specify sync strategy. Default: Sync'ed after every message. See Logstorage Rinbuffer Implementation below. EcuID= # Specify ECU identifier SpecificSize= # Store logs in storage devices after specific size is reached. GzipCompression= # Write the logfiles with gzip compression. ``` The Parameter "SyncBehavior","EcuID" and "SpecificSize" are optional - all others are mandatory. If both of the parameter "LogAppName" and "ContextName" are set to wildcard or not present in the configuration file, "EcuID" must be specified. A typical configuration file may look like: ``` [FILTER1] LogAppName=APP1 ContextName=CON1,CON2 LogLevel=DLT_LOG_INFO File=App FileSize=10000 NOFiles=10 [FILTER2] LogAppName=TEST ContextName=.* LogLevel=DLT_LOG_ERROR File=Test FileSize=250000 NOFiles=5 EcuID=ECU1 SyncBehavior=ON_SPECIFIC_SIZE SpecificSize=5000 GzipCompression=on [FILTER3] LogAppName=TEST ContextName=.* LogLevel=DLT_LOG_ERROR File=Test FileSize=250000 NOFiles=5 SyncBehavior=ON_FILE_SIZE,ON_DEMAND EcuID=ECU1 ``` In case of Non-Verbose mode, following filters should be used. ``` [NON-VERBOSE-STORAGE-FILTER] # filter configuration name for a Non-Verbose passive node EcuID= # Specify ECU identifier File= # Base name of the created files that containing the logs, e.g. "example". For further file naming scheme configurations see man dlt.conf FileSize= # Maximum file size in bytes NOFiles= # Number of created files before oldest is deleted and a new one is created GzipCompression=on # Compress the log files [NON-VERBOSE-LOGLEVEL-CTRL] # filter configuration name to control log level of Non-Verbose applications LogAppName= # Name of application (wildcard allowed) ContextName= # Name of context (wildcard allowed) LogLevel= # Define log level, e.g. DLT_LOG_INFO or DLT_LOG_FATAL EcuID= # Specify ECU identifier ``` A typical configuration file may look like: ``` [NON-VERBOSE-STORAGE-FILTER1] EcuID=PASV File=scc FileSize=50000 NOFiles=5 [NON-VERBOSE-LOGLEVEL-CTRL1] LogAppName=LOG ContextName=TEST LogLevel=DLT_LOG_DEBUG EcuID=PASV [NON-VERBOSE-LOGLEVEL-CTRL2] LogAppName=.* ContextName=.* LogLevel=DLT_LOG_WARN EcuID=PASV ``` ## Usage DLT Offline Logstorage Enable OfflineLogstorage by setting ```OfflineLogstorageMaxDevices = 1``` in dlt.conf. Be aware that the performance of DLT may drop if multiple Logstorage devices are used; the performance depends on the write speed of the used device, too. Create the device folder: ```mkdir -p /var/dltlogs``` Create a configuration file and store it on into that folder or mount an external device containing a configuration file. Start the DLT Daemon. This is not necessary if the DLT Daemon was started already with Offline Logstorage enabled. Trigger DLT Daemon to use the new logstorage device: ```dlt-logstorage-ctrl -c 1 -p /var/dltlogs``` Afterwards, logs that match the filter configuration are stored onto the Logstorage device. ```dlt-logstorage-ctrl -c 0 -p /var/dltlogs``` The configured logstorage device is disconnected from the DLT Daemon. ### Using dlt-logstorage-ctrl application ``` Usage: dlt-logstorage-ctrl [options] Send a trigger to DLT daemon to connect/disconnect a certain logstorage device Options: -c Connection type: connect = 1, disconnect = 0 -d[prop] Run as daemon: prop = use proprietary handler 'prop' may be replaced by any meaningful word -e Set ECU ID (Default: ECU1) -h Usage -p Mount point path -s Sync Logstorage cache -t Specify connection timeout (Default: 10s) -S Send message with serial header (Default: Without serial header) -R Enable resync serial header -v Set verbose flag (Default:0) ``` ## Testing DLT Offline Logstorage The following procedure can be used to test Offline Logstorage: - Enable OfflineLogstorage by setting OfflineLogstorageMaxDevices = 1 in dlt.conf - Start dlt-daemon - The default search path of logstorage is: /tmp/dltlogs/dltlogsdevX where X is a number in the range [1..OfflineLogstorageMaxDevices] - Create the device folder ```$ mkdir -p /var/dltlog``` - Create the configuration file "dlt\_logstorage.conf" in this folder and define filter configuration(s): ``` [FILTER1] LogAppName=LOG ContextName=TEST LogLevel=DLT_LOG_WARN File=example FileSize=50000 NOFiles=5 ``` - Trigger dlt-daemon to use a new device ```$ dlt-logstorage-ctrl -c 1 -p /var/dltlog``` - Start dlt-example-user ```$ dlt-example-user Hello123``` - After execution, a log file is created in /var/dltlogs e.g. example\_001\_20150512\_133344.dlt - To check the content of the file open it with dlt-convert or DLT Viewer. ## Logstorage Ring Buffer Implementation The DLT Logstorage is mainly used to store a configurable set of logs on an external mass storage device attached to the target. In this scenario, writing each incoming log message directly onto the external storage device is appreciate, because the storage device might be un-mounted/suddenly removed at any time. Writing each log message immediately avoids the problem of losing too many messages because the file system sync could not be finished before the device has been removed physically from the target. On the other hand the DLT Logstorage feature might be used as well to store a configurable set of logs on any internal, nonvolatile memory (e.g. FLASH storage device). Due to the reason of limited write cycles of a FLASH device the number of write cycles has to be reduced as much as possible. But the drawback of losing log messages in case of an unexpected operating system crash has to be taking into account as well. The obvious idea is to cache incoming log messages in memory and write the log data to disk based on a certain strategy. Incoming log messages are stored in a data cache with a specific size. Depending on user defined strategy, the data cache is written onto the storage device、without relying on the sync mechanism of the file system. The following strategies are implemented: - ON\_MSG - sync every message(Default) - ON\_DAEMON\_EXIT - sync on daemon exit - ON\_DEMAND - sync on demand - ON\_FILE\_SIZE - sync on file size reached - ON\_SPECIFIC\_SIZE - sync after specific size is reached Note : 1. Combinations (not allowed: combinations with ON_MSG,combination of ON\_FILE\_SIZE with ON\_SPECIFIC\_SIZE) 2. If on\_demand sync strategy alone is specified, it is advised to concatenate the log files in sequential order before viewing it on viewer. 3. In case multiple FILTERs use the same `File` value, it is recommened that the following settings must also have same values: `NOFiles`, `FileSize` and `SpecificSize` ## Maintain Logstorage Log Level Implementation The log level setting of each user context in the logstorage FILTER will be treated as the highest priority. Other clients (e.g: dlt-control, dlt-viewer) can update the user context's log level to a lower level but can not update to a higher level. In case the clients need to update the user context's log level to a higher level, the new macro ```MaintainLogstorageLogLevel``` is implemented in the ```[General]``` session to allow changing user context's log level to any level or maintain the log level of logstorage configuration. A typical configuration file may look like: ``` [General] MaintainLogstorageLogLevel=OFF ``` By setting ```MaintainLogstorageLogLevel=OFF``` or ```MaintainLogstorageLogLevel=0```, the clients are able to update any log level to user contexts. By setting ```MaintainLogstorageLogLevel=ON``` or ```MaintainLogstorageLogLevel=1``` or not set, the logstorage will maintain its log level as the highest priority. dlt-daemon-2.18.10/doc/doxygen.cfg.cmake000066400000000000000000001753631446635226000177200ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a 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 (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config 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 # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = @PROJECT_NAME@ # 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 = @COVESA_PROJECT_VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # 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 = ./DOC_DLT # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 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 cause performance problems for the file system. CREATE_SUBDIRS = 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. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) 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. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) 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. REPEAT_BRIEF = YES # 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" "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. 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. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then 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. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then 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. 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 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. 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 # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = 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 comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) 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 behaviour. # 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 behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. 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. 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. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" 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:". # You can put \n's in the value part of an alias to insert newlines. 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. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. 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. OPTIMIZE_OUTPUT_VHDL = 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, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. 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 EXTENSION_MAPPING = # 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); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip 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. 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 (the default) # 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. IDL_PROPERTY_SUPPORT = NO # 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. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) 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. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT 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. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # 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 and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # 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. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When 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 (the default) only methods in the interface are included. 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. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) 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. HIDE_UNDOC_MEMBERS = NO # 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 (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. 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 (the default) these blocks will be appended to the # function's detailed documentation block. 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 (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) 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. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = 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 default) # the group names will appear in their defined order. 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 default), 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. SORT_BY_SCOPE_NAME = 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. GENERATE_TODOLIST = YES # 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. GENERATE_TESTLIST = YES # 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. GENERATE_BUGLIST = YES # 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. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of 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 initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. 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. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # 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 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 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 , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. 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. The 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. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED 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. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = 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) WARN_FORMAT = "$file:$line: $text" # 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 stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be 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. INPUT = @PROJECT_SOURCE_DIR@/doc/mainpage.h \ @PROJECT_SOURCE_DIR@/src/ \ @PROJECT_SOURCE_DIR@/include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_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 the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # 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. EXCLUDE = doc \ examples \ .git # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. 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, # AClass::ANamespace, ANamespace::*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. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = @PROJECT_SOURCE_DIR@/doc/images # 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. 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 # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # 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 also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # 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. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # 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. REFERENCES_LINK_SOURCE = 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 http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) 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. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # 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. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # 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 one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. 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. If left blank `html' will be used as the default path. 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). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # 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 the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = 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. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # 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, 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 http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # 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. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, 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. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, 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. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, 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. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, 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. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = YES # 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. 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. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. 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. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # 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 FRAME, 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 (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = ALL # 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. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # 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. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = YES # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = NO # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = @HAVE_DOT@ # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO dlt-daemon-2.18.10/doc/extended_network_trace_doxygen.cfg.cmake000066400000000000000000001754101446635226000245200ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a 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 (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config 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 # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = @PROJECT_NAME@ - ExtendedNetworkTrace # 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 = @COVESA_PROJECT_VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # 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 = ./DOC_DLT_ExtendedNetworkTrace # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 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 cause performance problems for the file system. CREATE_SUBDIRS = 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. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) 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. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) 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. REPEAT_BRIEF = YES # 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" "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. 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. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then 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. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then 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. 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 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. 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 # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = 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 comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) 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 behaviour. # 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 behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. 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. 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. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" 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:". # You can put \n's in the value part of an alias to insert newlines. 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. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. 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. OPTIMIZE_OUTPUT_VHDL = 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, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. 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 EXTENSION_MAPPING = # 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); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip 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. 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 (the default) # 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. IDL_PROPERTY_SUPPORT = NO # 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. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) 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. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT 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. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # 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 and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # 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. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When 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 (the default) only methods in the interface are included. 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. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) 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. HIDE_UNDOC_MEMBERS = NO # 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 (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. 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 (the default) these blocks will be appended to the # function's detailed documentation block. 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 (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) 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. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = 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 default) # the group names will appear in their defined order. 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 default), 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. SORT_BY_SCOPE_NAME = 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. GENERATE_TODOLIST = YES # 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. GENERATE_TESTLIST = YES # 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. GENERATE_BUGLIST = YES # 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. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of 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 initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. 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. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # 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 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 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 , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. 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. The 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. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED 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. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = 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) WARN_FORMAT = "$file:$line: $text" # 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 stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be 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. INPUT = ./../../doc/extended_network_trace_mainpage.h \ ./../src/lib/dlt_user.c \ ./../include/dlt_user.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_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 the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # 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. EXCLUDE = doc \ examples \ .git # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. 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, # AClass::ANamespace, ANamespace::*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. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = @PROJECT_SOURCE_DIR@/doc/images # 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. 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 # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # 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 also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # 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. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # 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. REFERENCES_LINK_SOURCE = 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 http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) 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. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # 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. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # 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 one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. 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. If left blank `html' will be used as the default path. 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). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # 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 the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = 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. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # 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, 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 http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # 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. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, 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. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, 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. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, 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. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, 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. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = YES # 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. 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. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. 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. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # 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 FRAME, 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 (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = ALL # 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. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # 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. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = YES # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = NO # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO dlt-daemon-2.18.10/doc/images/000077500000000000000000000000001446635226000157315ustar00rootroot00000000000000dlt-daemon-2.18.10/doc/images/covesa-logo.png000066400000000000000000000610531446635226000206620ustar00rootroot00000000000000PNG  IHDRcW pHYs.#.#x?vaIDATxy|T֭.ՙZ VDE @DTW@Ya'@QqA@uAi V;3~UY $z 9r<9#|ǘ޽\r7M8nkWl1UI4%ӻ={q&~>{ʦ3 `r G)YWpFF6S{q\݋S5MI^.|cXqeeR+WH2imq ):bŕ&aWKWIi++2GRӤaȈW&ʶ2>>u{ եm@@@@w.x W(wVٴ"M|swyew߶v˲Ag7tL&EvwyGmS)_)rD""?ill& lrv~]+Žb]2p UdSR;$,LI/%Y>]y]|gi hq(X<_,(v{ƱN^,׮ٶ?VQìȤKfi)W `ZO-\G,<" RWҝ})z;KƲ}ԏ=<{ӻ? $^\6i4fNi[)M"o'~M)t]Ww@.j$ ׻QHٌXsw/w/~0ԓ=X ,H'I8"LD$)w[ᓤ0rHa~lG|EyIʤ'YUP" Gw/! ~4Ǻ+`I/I*I~oܘD++až+’_lGީDzT„ K|&.|kc?+B}: Zԍ=XF^"'8,?E&EZlJI?_i0.7KRpWw!2~=ߒ"H$r%9$*Vg> ~q:bŕ_%!EZ%rY6IKRDJ $vO;[ცSpQ)%=ߟ| ^sI\""-F f|ӊ+@P1>*2M~=pJ@q&JA*r=y8~]q X"0O$2LDgܘb`ژeުKW㊌J\sGYET"*k.]҅}WW%JK $֤= ^Lm.>O"+3waR'.)4 α]:I}sYo΢]oM%i;dT`ZTzv"?ZTkQiƠ$.MYZ ޙ[,8,LqAw ~ αܷhmRx? ómfV0/ioh.&\DZo=: O")Ls).-8۶ Kt.2fx]9W/9܏vou~Nj^ळTTzD%|z~o_Eͯ迤CR䓒} XQ29*h4[~pW}Mᢣ.,9O $2ȏ.|yր#%aI>M!Iz~T»~/C]ė#5~4.+2-f@uMII|@aP?jpGעߞWTÇ&Wӟ>?1IHv.d<_ZT:kQ$\P y.Q|]W[̈́fX.,9>q\]#Ioo`Ei% ]{s^oTy2P$%sRҮpJȁI-04RE%\~M":J:qe`]NėQ%, 9.Dٻ»*OSXḝ$p|~+aHW{ϟ8 F&&EYp6s$hRI?\(+D~ȸqL:ҡ^q@:[^qT+&Al+g7OV*av΁҅}ȦJȿ]Lm\/]@@@@ı=I[?" ],K[djѮy.2š7u{U+VK9\ ΰE-R ,v[R49~1.*\XyPaIE(*ϋ5+7Tt6y#7w3K\9#94w3Ӡ6׬|8ˢmg (ߙ%.*V(T@@@@@PWӻ݋u/a}d[sW\Wm t6eS/F;wCk.W5ymg (=+ *ᗮH$rAz9seBk-,Q~@m'+ß<رyo'Td]}L¨qTiಟ+r,ǭ"j"y" _w2oX߼;VRvo/wlB[woMcvVƘ6UUPw]U(([\l\ɪb鸳c]9EDNi/[g@@@wQ:{hV͛.kW)qapJd޵Hgy寓*R;"rpMbd OLmFNm{v5;V19-˻}u^saaP#5|465i[Ó8xߦo0*Ÿ5"=H)3)F/|ѼTk5RjE.uEJߊ`\/`?PFs.eGE{ҴſkYK8.w3ik %^;_18U#wm߯YFmKmC5|c[o;o9"adkmm@5w_-E G>\Zu!ǻgT/4jgޱEY ?Ͷ4c``!"G+qa oWTu{/+d˻qU7Sk-m#F^P5Zݳza5TzmLHԷRTa1]*jk5Լ/DdL(Э-༛(UrG)U3.ʩv)Z*݊^KQI8Ɗ?gQAF&tݵE%M{I7MWM0D"mta5/^aEV( V[sZ<@`6p 0v6ݥIֵe1]v)jܚJ(ZN-W*j[$tJg9ß_; h%x)/ߚ3[?/Z)rAkMfV=pΟo# 5{1 8P$BOFva}hֈS#CjUX`⚮CE.SuRs`T-6`>`U.b и[ .l^YW{﨑-٪F1S.?SDE \7Ɗ'i'F>A'_/uWad¡)F8js"!bk#\>\#^@x}iaG`k=U{d}KWy:*bbU>@YS/խJ &_\_"+tp z CޘZߎu|\㊬*#.#[s{تԟk/$[w׋Wa]{t)ε^pRם0(}1!)`D8@M%XGFG_98lvvk$WP4 !m={jXbk-/$!`ǻWF6g)nS7nP/BXA:{-׵DLVXrSqoyʮbdk+ KgMְKm֊;N񊝜jʶ"V= İ~7Yb]jt-ƭimEJŐe|7_Ng"[ @@@@@@UT}濚DLI_R$LDYTfe9:-e^1r5BW,DG]g[8 '?P |W|"wo4}% 9n}D mfOcH40FU]gUsVG1QZHV~mn<|Kk$wmg5ƞpe٬M!F;s--fm <`T\cBTȿ+tA"wֆﵜah n1rΟȍbGp+T1"<$1l+ j4So17h( G4SG<$?w~kR{N fosFRgӼ`;Uh!Ѩ0VX@=*`_ 7.-D8Nw#W{I8y&;Ҋ*__  {z.;q0ө1 D+3!5q1?Z&&Ӎs2b}ۘ]|%"> 5*\CVP\i1oFG&Zȴ-_Z[cȯqZ>~nSDؤ\I6k?iw`i嚎Θsx@UﶖI6X]T~%[7='9x2ٰ' 1)^ॣ2p8o% X"cty&"p`qmI:.!_璽~%VDm+oN 4K|ƦQDçi-l%;'}, l,'c&yDeԆΖKӻ\#Gу=vg?m bd?k.nD>ZM~)ϊu1V>s\7C{>aY_NAFԦTe`Uz::|<,Yhd*J~h_ gck_b_d0ߙE/y54hx.GDZۻ5?Nyil",ma}Ѹjz"O#" 7c 5/UEw/~4$\xӊ+_kA!wԳդ*Y6 _mZ-H89rbnS1s\D$s/HX"?ƓI##av<!njix+Z?%29˪'QG7PE:"x7 XQN-e/w#uX"mL$~Z4wx vgcAkʱHe<>g[#üh'qS8L"ϔ}~q/kxM !7u!wֆQ k9LYbU᜽b X~7ʁaxxCcu 0K?':X—^t$.[(K,_Co&g0(K<ﳿ=QB:6"lOЕx,qz*+vE<[m,HA͟&{~[,8ᦾ vYn.,)X~7\ N/7)rBEkn1am!|aM"Z&7֚gڔ(x+pE~" GsTSŸS}81*@<( T- <h,9տکc/Rl0߇U`& bJ `1 Ӝt٩GXkWl/O52{V&\‡Io^>||"\]R]p|RcٔrȈf0лtaFk5n02r#2C D1#FpΒܰ5RZu :iPN,޸̱D,8Me:>-hp< t|<K_i0ۇix,No[)ou! ;3P=|oqƬx,iEscWLg݇ u%pWJc@$KlO ݇|M7w~Jڕ-psn\q;KO}hUwZȨ+/ U"*m zʐ'+./GNn ȹ* Ws PV^ms>jRѿ|X{. &SuMTĜH4ܝN "dv8۩c 7 f- =;A\iD2V-N59wW9Ur#J<ڸ* 7>;dFTkcjI?RX(,Qv*B?ENTTp$lrM8I"ᓇ>oeM?bu:`]׿k6"R{*G 'ZKX Z*EBԪ)7XH4|5ED% wc0Ȥo$ݘQhmtc3|CРq)44l~ui,^SJ>+ 杻vlnDKm"{ks[}Wᩈȏjd2YKZSx >wЬk q˙fʯTg[ ?7"܃S1;V?;Ee@aI,6ęY:b: ƨO|@<" _ԫe;D1H4p]kuwwXHKW$lyhqE~?s$sG=iFbds 2 Uxp",Gibha-8 :)j~ɤMK#pK{]!'x(76 8אH&mR6kZJQ/u_.t"2\e·^Tѕk7ߥ^Pquo!pǁ>ZQrs?%~K-"plލsاhcTDi8t+H4|}JAIxjֆ:twFԡZW?dWM# vM*߷yڪb:T ovކwjq'CDĸ/Z>Sq}oSXys'/PC gOU|홎aLAKٳ9͖x,1= o:io+  Y7KnhR29H4lmu dD 7?c{zN6"d۷!0$1f0%xդH4&pjX"Sgm}*2c,駓c%foƒY b4^ISfxD;9/H<{n"IGxaL /^̙x~}T: *Oeb}*@<_"U$D Pi֎=kB_c0k(zy=HH[Nq~f d F5æ&AtL'c/iC}f xjԁT$1?Τ ^~xguaWuIIW:z?5k*<>s׷ni#F[C+( l2ʽV=eDI65<iNX{)~ Np ?sc=X+{T#D[ fs~аJ@Dˁ@sǮg`!*XTǧXX}$Fځ^** BkQ)/ٹ&Eq-gn*mp ~*lȶHҧ .z!K,x,U$LZm< T$J JMxUABxQO@%*"p? qw`kȲxXFǀ)i~;cṉ852iF!޴lUGci/C%l g nKηx,I$?|83 kr"QdygCJXCx5[K}N1ȇL<AթZe"dN_x)Klx,> EzH4$`&]$nRCF-("ߔ+ g1}g+Ҽ۪,akٽݒwx2mۘN5F~ B|9HDӱsTY#1u :2_rK6N<hi2M!n;T/v`§r#pI$>.K=ZcTXrRRۥ V{<4Iv*V'p# Ϥɡm>P(k+V\"y<{dB7}<ˮb)5qn$Y<nnaӐا5R@xoOAdXɼZG3cpQNTs^L Ni]]%X El('\ ^V(HJ[Up5ڪa>a38a3T3q[v"W (8o5x(E$mϦck*#-XH4+`Kƿ,O$>"P4liM) [w  dw}P;{H4|asH4|WPcA(UnOK).wͻ1"׀ .lK~{BQmǬg}2TXGڪl+/T\i[6c"R2oߜ,DӹM< @Ok^<\g|jm4lHRɼc2)KF4&Ix?~9KTপŇT+Bo+5Lӑ{㪄8h+F0܎Pٽ|}-^tDV {޴稞A[Fu$ lD_^x,l P/cLMs^>̿6*=%'fcFZDïǦx,H4|9#0NXOAzj꧎χx,ѤMhN2,K좿R޽x?ȤF[&`ı"# j 2U vLuaP[oX~>[q]bp~T>:c3EC~҉%2J5 hx.0 h<&qJO~ p?P#028iBE[#ޛ~mܱk.u O#M"y.R[=~tB_q}rgn(rE(PW]iQQRb lЎ; ZM{HUnpZ\qc]ZL\wK(OUjޖ{WPQH塽Df%t(WkPRɜZkDӦVgxE ٟĪ+eCgwDݩӱI2#!M23#Kd  ܟl@<_ieO$nw;Ą:ӵ[Eyҧ^lZ}(jͳ_T=ϨݝjwQ\Qb]PX0VY39:wt_lupEu3 xѿ_ݵ*zQשFyŃw:˫|(T;,o.Ɠ+0p,p2^0ҏSl0x,Xz_xOƻ8m/ҩxB+TF$6d.7w*{̆vovШ).]図{}W=mgw>H-NjjVwFiZ)b-_収z}(8A,Xk\XWƪ+|bc5=YcQ}BTXSWu(yjWױڢ V FI]4?˻cuJpp^=}> pNc=cIxY,70 T<=\_ѕͷbx,7btoqF$S`Q&(Kɂ15oUmmMը^gXnPmEcS~ȂCwմE9ꈲa{m񖊡w9h#p q,9er'v]|b`P}`ylO[vR6S_Zb,Z}6TqbzLUFeKE%.yc^ȫ$cd<=0J/xo{/qѐc/Xm!}0F}نPjV>XWO<ﵼ ۟H4ܒy+Sh/)@NϨ\:xiLyIr\[IdP% tEJ}?޸<12͊#ӶaڳֶvEJuLjgM-^/+n8t}p/p I`ĖK(W_(ixb"UP|drQ]ZNչZDҥ>i(vW9bMo{`u*]*>?;rU'Uf:VC zcMO\lWhx<RWm%xѥng0ozwYXuN]}TD2x,11Sh# Sė "[4ۆ/xG骹dKA4&VMN$KA/X^Rk!)BR )"+?R#oF"*I,SjZE[[R+o"sxi-yvdEnQa#b-r2;e=h+ީ2(WyOcҭ7u !UFmsZ޳(e˸kވg0V7vNJ*WrΛ{4[Zh <=٪B7hC.>oE5فGUoQ $ lWa (,S0U#.󵭔{j)5FZS=iҺT:[{ TǀUr院PqS>w~=֤򝒖5(U0֛:'[ U]bӶRmKKrzuywRvoεlm3OIErS}ڽp>ߣid7x=<Ʒct`r|ܫ-L5*#^үA'T9*'xM-?n9ᜯ vQZM~(]2t[-;q%儵wzg-㺖ݱsc^[UORkv%ύꏰXE{ hx t|rO [<\% vnzJkX 0} T-"("8Fr*HkPy oyNZځ8~ɮr2&А-}nPqҤuTXjQ.H? muϚ3>7;۔ۭ$o 'jcQbCUwcT4D0UxZ;f~~-DŽ.*@d09=]w@0s0(gza /ʊZ0ro5y}*o;U4s;}م{jX!cX|:ٽ$TQ%xyx+~ϋmZҁZSѭhNw>#\y&9Ք*{jEZET7hh*C,`u⾵AVTbU[9Vw)k.2V?2iܭ7uj*[o;Xո5w~_n:;}NʩUDo_k <յtEGo7 MX/￴eg:/TϴF9eZ}Ѩ^ heX}(u.vrcc|Zv&rZ+}n~[rڪ(45X 5 7VQe&#[:.lJkW_R]:1 Ah6 KEU.yNL"Y;-6Þjm)U]Vh<NgN+[Ro-ƭyF+<.߷pJ֥Zm:K?uc (~.c#hZn׵|X&^lTO3/:o{%9c1.uTq`E0Qۄ_: sYv(NZf9ܱk~bc9kO!=i-'=ZꆴQ2ˇ-ǯ٥N薱oWi>ev+BUT>]V".Eu]j rAE4G8؁G-Fs~/a:2jX<%pekkW'jxcq5puX=zi.?ҿbkβޯϻNi.ϼı:٨;Y;ǀk c耀h:`YFu0k`R:pykS}jN0Qݱz?3ʗb6bkhUB^0ZM˳n1խ/{Z.AD\4EjuFU餾%bu*Xs-YkGyP {#.Z^󍷥6e^5w9\ߜݳe8ʺ3J9Fds}Haɯ  ggo`L P,x>J"3]a ?JoH#VUv1WF z37X!wKV7?wLF@Wpn 9;VOS-㻭^\6k>˽s]$VMXk۫h-__8FyMToã՘;gv:._;?h4<䨞W޳t@#+ڸ]ᾤrR" Ij ڙ6׬<u]=8R:TفN* QPigմB,Tc5V_Pe &%-6[^궾F6Cچz;_QMS GL9Ur`?00yIWgyg'ϝeic V>ڱ>ֽ+2pEO8gS:^T/9v8״'EV舀*U8qSFTH[wGOϵiuupgM=xF:(Y(%c#?AQbTV{$φaܒf rT6ʸkWVc޽x?yA7p,T"/mQ"?Y?/tmjKxJ9ʉxcU?DjLʽ#Xm{mta6.jsU{(ׁ['z1Tץ';TQY!8Pr8G%GXЧq,{n'˧u7 N+; *`3jEj~ŭ]̂>T򬠃*Zg-P&MVc%T.68 w3e"8V Fu*'gϷU=/)0 -Ro+Qxszrdn'h  -nRG5eN6O%ab;_Qֱ$uQ}]kY)|X6 ~!VfS}NT2oZ\}Zt 5*XTPNvu#.׶p@@@@@fm}h1I WI"hI*@nxg|_ bj)~k5 {j'@֟xЧ5#)jL,3]GQ`Z;?E^f _09^[%F|Mg| -T8P;tTgirs;Kܾ:5V˩Epw~a9軎6s z?jA+s e Q%O)4ڱ:h !\]=$Gh7JRU5g (]5tYJkw0;!8jWbb6='9  hl+8[F]\D=*ezjA]Jtv!87; oK}’c/*$Erdw}@@@@ٮXC-Ԓj~OA?[Op5'nd?HEVKgv~~Q _Qf9p_{Ic,8/vCtwB/!qT|UnQk&-Qbg.,9<;mRm\z~A}'@(M_BngXTvT{m0qItVڇi4;jGqK6d6Wйsl -[>R:y}+~ڍԐrjrSHuߙ1~+?MbW^Q U4]8Ɓ#*߶-GG=˾o9߹#=fQZ~{̇zn)&nXq/V݋rT;pjHiR6Ÿ!i ^訮~{w{. ^2p r2Z5u/;m 4Mwm7<^rp;X@@@@@wʱ@SU N d<^{zIENDB`dlt-daemon-2.18.10/doc/images/dlt-multinode.png000066400000000000000000000523521446635226000212270ustar00rootroot00000000000000PNG  IHDR*cJsRGBgAMA a pHYsodTIDATx^ mWyۈ;rAH؈H4qd\%`({uq%U!eb$aҕH,# XX2'88&=]{{{u:u|龧!B!B!B!B!r'< W/º` ֭^>B!jmZ_IZzB!r+6*IV/B!BnF4iC!Bȭبo~ƷC!BȫfQyDu~P=l:yhuFǥx:q4<'ݝ<[ Pڤ|uY/ 3B!k{~Mo!B"I5w{MyjiХn҆`f:M-1-16՛ú^vwK>+:7ܖxg7_Ǟs#B!T?'մcLjwQi7u;lTMoӹFoT|tWs~ҽy9= .=iO^*B!I5-q_$^hXM|sbm漸Y\J]nTG{gҪ>Ejss9׀ʿ~Szg!B8-'6Tug<`L!B'6*tWg}aB!J 7*h|OCa]Ψ!BbFŃ}xš]/ B!BEܥM3GzS/ B!BŋʜcU~zIB!Z 7* y6)!Bhݤ~8AB!$6*!Bى B!BhvbB!ب B!f'6*!Bى B!BhvbB!ب B!f'6*!Bى B!BhvbB!VQ9rz8OsLiى?Z!'.KR#TUwgC>SOwTW}.dx  +? h5_i/{ U՟|CU[>?xKgfyVS!' [ϓ\O@W: hk WCX| phC /_ U? U_-$4Eh(GﭪG=Uwx_U}^UU7pg۫s>{KC>sc>uk5}Zzj69F99fI'b#khqc!4 m9B~hJm92hBN]hʢ8Wr@5j4 mh Otbn5Rw04CjCׁڍʶм{A*>G6%KcΐnNtsΞ6Cb7uD+=\ͳmȑЀlˑЀ$s$4 r@Ekmsz9Q[ Db7*ڛ\Ijpp(hlA!ȡC!b7&FuKcrHz_w՛͛)6* +} 4S-%PˍEι |n=cUcۜL|,F%kh=իzK,棓 &Q!'ޤJR#U8 0Xw::!:޻ Dt ѿ&5zG{{iRBc=m$7Fsac @Lȅn=.up_gMi6Ru5rB۪'}nˍfxm`\sS|s@E,D:z[|nvo 9Cz$588B@T([6Kc1$n8t5%itX\{돩a}׏wSa} hZrƢ9V[72u;s ]`c: F8_2#Q!?xR-Gz5,5|;Uo㱟7u9g6fduܨhos%j c&by,B|,x3>;6 KpN XFER$oF#\SA3"l#X*CFn8RuS8&(fFb~5 X=QQˑЀlˑЀ9GZdCKތM$ꪟ=BN= kQ!'ОJR#T8w7 l4 ׄFy՜B~!UinW>crM{j+C}=s U6 FjzB~?y?%?Zjwx3VQ!'4IJ Qt8'\5"@LU?W A~ o˫sNrBNiJ|R XFSx8_kDyN^ȝ (!'VQ!'4F%>W 0穠nEx xۦ%EcІ@@Wm '>`h!_D((gDa~Qp4w1EDAҠ` cZ#TqNyUr@95F%ah4SYZ#M, AkDN]hm$yq%`(#O8p"?Q󃜘?DYd ٟ͟,+BGȃj.=W2@TsuvIȃj."dzXhoaz<2NjppL%po={{O>QG8Op<89_󄆣l,N ^̨9#<&cJGDOFm rܘyuȃj.SNhG4Yћ>mk8t}q/cXiٚO/mcfx^xΏh'O<c_(2=z&zZnba~^ L9!d Do/.}{B|nauмw/w%ܤw[&>{X0uw}ة}vq^ñ&5GFJGDOKBnS#yPe ͝&K zg z/}6u[?Zљ3G=Ofw"㉆>}[MRlwNmdzc?huW2=z&zZn}ba~^ L9!d DoER5~OCc mwL/qpt~dcq3ܽ8h8}ּ7O{@8ib:gpǟ՟B16*dzLԩ.150?L/\I i7_鼐w_tK@%[}}U#{V!tz_߼NgFevDO5<697Za~^ L9!d DoaWUzy=\W=y#<6W2=z&zTXhWaz<2NjppL%EyjE7cj6K Gx\cJGDO5<697Za~^ L9!d DozA5 Vcc͋6/-WWoڼMWV'71iب3S~ 7 a~^ L9!d Doz5Vcb]G==-䆁: A5)'4wR#d,M/Ss24Vcbm~ޡLkx r@^˔;2M@ߩ-4Vcb]ez2=z&zZ) 7 yuȃj.SNhG4Y[;5Vcb]ez2=z&zX`2_^ L9!d Dozj"b]ez2=z&zZߩ 7ȍ%a~^ L9!d Dozpp\g\36*dzL\SAnKȫ0@TsrBs'588BB;h8v(r(ӣg rXB^˔;2M@־NX׆#<6W2=z&zjkej rc yuȃj.SNhG4Yћ^\ 6ȣF#%ӣgnN An,!yPe ͝&K z cdž#<&W2=z&z0?L/\I i7xflT\[SBnKȫ0@TsrBs'588Bԩcdž#<W2=z&zjbj rc yuȃj.SNhG4Yћ^HXX׆#<W2=z&zX`2_^ L9!d DoEtr /Vcbp[5cJGDO r0Waz<2NjppL% otjn5)ִ}kب3ԫߩ 7 yuȃj.SNhG4Y_4n5)ֲ_ӚQq%ӣgWSAn0?L/\I i-`NEj,Rcá}iب3ԫߩ 7 yuȃj.SNhG4YxXEum8}hب3xOAnXȫ0@TsrBs'588B"919pflT\yT䆅: A5)'4wR#d,y/H nflT\yT䆅: A5)'4wR#d,y/Sr-vS16¼Z36*dzA[[BqqË́5MEKh"j2"m~zB6*dz An՜0@Tsr~st\0?j6n#lT|r-0?L/\I i4/dzy|xOk՜F#%c)x͍'Fja~^ L9F%g>O/lsFc/_|!s-5uhdz,Be/sEk0?L/\I iDtcXKfCkHXs#:^ oRa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M<`}CkHa~^ L9!$֧<L0OX/h ˔;2M4|˟y~TǞM񏼠ͯ㏚ׁL0ȓ: A5)'4wR#dsuT%6j.oJPz$6)azȓ2Q9 A5)'ب#zWSMg3i˹0OTsL0I٨˔lT 5 >zjW-uz?wja<)՜0@Tsrʺw3ۦ}w?Xֿ{uu\V?HtG8y6@5H@ja~^ L9FxWakl_x{uU'ͱSGb#:zEo_|侻owNw,8W_Z܆shdzC9az<2S"Fe_/hZ]ufCEͅ Σzt 79FJGX-sȃj.SNQ9%6*'2~j~m:Sx`x'*񾾧:ιԵ6x>y^/_Vo_]̥w@Nh{捞#LnqYd}P9 A5)'4wR#dtEeIi9~窇=l4~zS:}ݜtVX~b?.h{ja-7*y O՜0@Tsr)h.ydq,l\h7,O?RǷmTzy+YN/~:IO\̥k|aި6)2QOgy>y0?L/\I i"OT^w, l",kH0_TsLnYu6'%5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I iSZSFJG'yPe ͝&a>5uhdzyzGk0?L/\I is 7\Ґ_FJG>Xhoazŭ.d ͝&KR{VxkU}࣎x9iUuGj߿~o}U^;Ň'nq"*6oi|wﯹIڼ w\-ugu-wT=5:?X%shdzL Ȍ܈yBnF50?L/(9)B5)'ب'~/(ڙ@iCd#E E0B(T! U(J > ^"BqG=YUל6ڼ궚+Sm^qk[j.w;n6/|GͷPmjj͋6/-WWoڼMWV'6x\'1ײ$TsL!7ȍ9so dTsr~YE;w-TpyUyصfg% L;|s]qb FћUsg C%rq'<շYs]#lTKd!7hﲾC6 ^o6*ެnjc{P9~:g5X{vu?P_Ϙyd2_'.CnhﲾY{!)|Qq@fq*7쿩Ia%c/ G?is]#lTKdwQ}ܝ78z~QYVF>V]vRVlèu{ڨ414#XjFe;NUKuVlHѫ=Nu[ޜݝGhg?Q|Qq@% N~9#ͻ8\kԽG7\X9xlJsǻ^9P Acńm?s،7*M&DoSb۹͆nۜFcn13B3zׅ`t~ ٰ5s*5/ar䛍7Kڍ[hXuwCȡCա& 㡐ƺMO^b]ʾ)7*oyn3_lTvO57 s9ح!b6p9Sޭo5vh6gg#.6*۲#Femr]qb )z۩[[{F],ސhn{ݘyzq7Do9wA/ mCx@aY~c3rhq^ǦcńJZE;~ϥKq1v~^ Ǻn[Q_WyT:7VVm3ԑ96|}s.6*۲#FEy9DXѹ)Ӌ7OHuK2[6ߜ׽nL$d~nT4G:.4E٨8 z0wI/bv sN/d;&[ǗfqNxJTkƿJxP9U-mJq%7:d6wKF^sPՁ8^7;f.̈׆KCe6*ȼQ!7Q裭SW{뺵gZ4\-k:=`zoNO˝}ܨ o6*Tcb=ΫdcX4apޝsoT:buWw,ΟiJPcńʩʤ9\ClUwr#֠hñfcvjl3o溆x^~ubvdب{G^٨LCT{%Y{K՞zB,^+Ot=E~ǵaFћ^Fq($Be7ﺯ:٨)%7yVE lT!X)G٨8 zk pJFa%q*~?^lo y}^?TcӚ*Ѹ,pogr[S1"7wCwcɍr}ʏUfGFbdCghG4Yћ ojϛ硲wU 7^i?TX"D:'p,GjBri:FS~2+L/ވ>t Ȇm };S!d Do*QXᑢPټjk y曯6/hxӕ+֬PLbI #pL;a #gV^}tkt*a;SNhG4Yћ mjVxXPY! />|EgœñWC PEO==-䆁ȏcNl v@h!d Do*9 k*oOrƷ=嬛^pw] e'P8Ψ>ϤLkx r@^O!? Ӌ7:lާ>cY;2M@HO vϻ-)5Tn3r֙_x_/XYw-UhN}V}I_Lr8Uu10x#T d>4wR#d,-Lnwy\+vmqql,ƶP_ߥ?lX/'6*dCg Hs'588BTL5ygT{b6 AX5""ӾKB%qpǥE"cg<NѰ/~zOFst|rLAn*QV^}45<9lTȆ{L1 ͝&K zk )Ccsi,@NwF7i`'>ןfa_|q[ڮ̹fQ+ 7ȍU@V?zm<:90 LFeDo*/ /cl5 <cu󱛆cϚn8㒧CES|=7^}hXU\Jc?dzLw. rTnj裩aB6 c ~%d Do*9p7cǤ5+=TqdgF7֙g#%͝&K zSBeP GkVz9Sl6|?=+?eezLԭ)!7ȍ%u10x#甐 d=HIs'588Bڢ{ C%<Y" 4wR#d,M2H֬P} cO9̯]G^uշSȑ#?ќ5"ӣgnN)ȍhFc0x#XlXl"g,Ks'588BBLuxHnfz5:dٰI imQ *>fDj*aNY"L^ OAn$Waz|t awI i->'$Cc\nf<:l4R2=zF5<B^ѭ) Ȇ ߙrBs'588BVp њ*HyF yuoGNl v|g ͝&K@}*B*aY"L^r@^ѫUC6 D3NjppL% o'\ XPp֬PGFJG<1:Ӌ7c|l%)'4wR#d,yOn nNXNkVzȣF#%ӣg[ǫ 7Waz|tkuՐ dnL9!d [|rOA(VhĺJFkVzȣF#%ӣgW˫ 7v@^ѫUB6 {@3NjppL% o=8 *ך*Hy*!7D^ѫUB6aWwI im^1 *C6 {A3NjppL% oj.+0v:ZCE6)=#Oz^ a~^!]dٰG;SNhG4YxXVXu p\kVzȣF#%ӣgi<]!a~^! !Ȇ"ߙrBs'588B]% 1|u pLkVzȣF#%ӣgWӫ 7v:Ӌ7Wl NΔ;2M'* h^XP<nkJythdzĴB!2F!B!4;QA!BNlTB!BB!F!B!4;QA!BNlTB!BB!F!B!4;QA!BNlTB!BB!F!B!4;QA!BNlTB!BB!F!B!4; E UB!B!B!B!B!:tK>IENDB`dlt-daemon-2.18.10/doc/images/dlt-viewer-send-injection-dialog.png000066400000000000000000000301521446635226000246660ustar00rootroot00000000000000PNG  IHDRsRGBgAMA a pHYsod/IDATx^ypםfmyccWywklvWbVeک֎]IeWh[6eَMId[(RQIKZ"CV-RI.^ 9 E|~} j_=z;iϿ kmmȠ*nݢ+6.6@-3>+Aм=!K@8JaKۿ?ϸ77&MV[lA5w#D[$z8cި嘱eYzF>ID|tUa{)~B3*xMGWKQQ)yaʴ* >W Q 5XY1Pӯ[S8Z`hn%*-axx`` fgg% 1[[!ez8 >FyἅϸR*3i[+^л8ׯ^ {+{O%̌g|^:wddq1x8Ƥ $ճP]8?xS'O<{Ǐ(oH$pƈ$ss'fk;"*R~nʥl&z5;Ecrn|&=4ۏJ |ȈЌocUa΅I#WkNS)+ԢۍK顥[1i"[)gLΘ5r|@4lq thy #MxC2>z ӣ= 3v" gg r|@4,WsxMgػw ',4[vR9`t+$5OqU`.P\2G^;^;22=q<44ok*~={ol/^OMMٟwwm``*m ~3… ": "Ӡnt(9iUw)T6? ߱~PP>19~Y?~dov}I^͛#Muop,6tnYŷU'Z؍Bc-4xzxcJa~5YK zV|Z\b,}o$@%K\B8.?89I.NjBκubLEpAb Y⒳XD䐂XX{/O:u6(NGGX}ٷɹq_sv*ϼW_}u|| !l2^77r Vt>jOUȬ2VٳX.JTT\Οm޹fUԺfVuR/u i`<$KJJfiKfOz|G;n޼}{ ?eu%Xeٟ߶:qj:x]zK%+4O* r XbuϻxgÝ%؅32K%/</x o˖-^nKQ vY{C-1-FnuAAv%FAD,K\Z%W%>d';Mp<w\c0B-1T%UfA,%%qV&$B8K"6uO91?-ϻ8e]bIKL hۜh1X]B?Z6*0K f9>hVrGQrrG%W%DyBspXb.S!>J(Q+Uў%ɔoSAEX%.&YXƿ~Æ<~޽\sT905{lnK!OOO=O<++A#ẗ5kM/Jz}1HzoXcl"[K" suJR˱Ģx%W%N}q=x._0{/ޚ% }]|98ZŲđKT˷ĵIjb-O˹ECM,17"y=ѾX,+Vcwp-9W5fggkAb[իW󿡘wʕ\ݡ&dKN䲖7tn Fn8ny2xN.K~<K_qڵiP%ZRz߿u<Σ}}}OՊ.~BcJD!KT%$K,/+:H Z bq[Wu p pLlZqm6&Q/^FyI$ڲe r\.cEE s.\@+ A6;;J(|7%籠񢦚~M8ۺu+2{z#H[[7AZ((N(`]]] mOzLMM9xo?|ua#?|_gnnNh64elhD1A BŢĀ|hr8ACCC e1J :q`/t|w駹FMmVuܼaowwZmUMl`ա޷idZXjƞXM\ZXhz֭4e;x/=V[u튂rN`-A˴du7(g# A|ZAZ0Q [ _{|ӻ??gV?} u:bno;=;x7a Vb{1AL]^]Z؍ V- ,uZ)Q.3k?J FO<~o~ͯ|zG'~{ )g `0n~xaD ~D! C.e;. ?!-Bč ,A,8Y_<&;5w,D4Ale][*-qA .l;ó1$wSakU8vt$H<vu 7xf,\.=1(T̪_xB 2ۉґ . ґ "JQn'J'vb%E7(U25.;PeAF*Qw "@u b 7);G:6mܫ`Ve- ?pp׉TC1Kg]u4dۃ\2܃ul׍4P.\AܲkS>?O.nkkz]qZLf||sccc*w( P]21,`psJtկ<ˎnbX WA,]ɏ!T::xKbvT%~t y1Z.Y/T;|[$ ?hZ) $GPlǙNT%~t ĢFHē k֬/ Oʕ/^RYp.>Azrh\*=sIW11144sСv!yQDKp)-9<00lٲVd~_BXYXزe !h-qXΈnt#P@>= @MhN&-e (*E sdddzz 9A={P14?yܧYsx2Tx9)-WK-iR6^')aGr {)- ⦦cǎ]p!+Ǒ5?/}z׺e>#G;~/m.{~ުCYUKmǪ%Z:hK: :n~~BjRBZdjos/]v n"<bKA`#PcY(v7G Qϕpӧyc b*_ޱ_~hw?=`w VUvxx#eU3N5d18Uߤ6+7!lVcWVfb! b5B9\bRKsn % W\@Fr%:m۶ */dg~Ͽ}OqΆLg2R&NL&Fy#۳bTя4<#KGKeQ#AK=yuEGm^xg/v4~ggˆ" l-1E`ۋ/dc~t߲/~O| zlZ>/ K,n;f.x .uwA$PA\ |Ѿ*<Ոa>(:Ph;(v$jh21Ϧ;gi`PѻI ~K/߸"Dl:s1v?">"$EIē WA7aD%*b6Q 1 A, KeY\TkK5c D7:fY8f5$6 G]%hXU*~g9{q)tm f "hK1+tTOPW0ǰ{ڂ\%Ȃtm%B&J8 kKUģ%*bQ $EIī G>T>tmxc@X8#) ]I.GUK#쨊5G5*tm&Kڅ^,QYP=f_{L8 Kd/q &\!muA5/SS1k3qTEN1e](^ %*bPH< bxUʇM/q H@AɟA[GW@Ak#bVu]~xc LbF-f @FhE-Ka墼XWuAQ%1b[魃nt518B1r_㪸.QP=l@]K.]~xc 96Q 1 A, KUIĢHē 'A,/ xn5k׶sS`VfyrSY W*'sp 7w#2۲gO[?19~Ȩec>-{<=8x^Y$#-^]lw4E?M^۽o+myZ:00⩠D,5|v=yw`p-w3fT0-ev1ѫ! bGWn{綏}ܑ׈Oz9Qt3( }1j78%Ko`2[<,;~c>/>^ܹe.Ƞk6# Bajj R)߃{N # =I@/ې`^~C1ླvvN50 s}~=?8c~t35ĢHē 'A,Ozʕx`΂sY5kp_D|JqX|t\|V%) X%8͛7Tb' ,rl7npGD|Jq@`ḀA.S[.(<ï_.As#*ᢏLu*.ά8 A\=XBC8yqիW#>]@8ҐGq!#gggp">Az z333Qb8 A\=V\922pϪ^J 'S$EIē 'A,OX$^ noo q#GGG ~/ ޱcǑ|9]666oP>)T Veƻ)| <& dA^t ыphZl4ZъǏI9@gAk e}^u 38qݭt!CVM={ DF*剉N ڹsgss3n $nw}SNi$_bg##HԸ3^ 'OEƽV A>Fn5pˌ BƮO6㦟"_IqVd8YAp+1Xެ!CV b!HX!*LBT$b!0g"e~~>%KE 71wf/v<;;;333===Bᇲ%&'R())}`r,'\cT7/vƱ/\J[7BB:wGGG'&&TZ͌LNTBn1)|ll {BGGǫ, XGQ<̑#G>|Ѿt:t\d[v"FݶmҥK[[[HyQoD~%VA[r):mmm\?սgÖ-[[dQ׷={wȴȷȺN,F"C,|ԩW^y;qQqSSざ ~pE =;TGaO2gNe?'o8#""};Sq<>>>44с}Ё\LQD/\r0~Ləydl Na);Z#ȫ---KRcccȺf1zD<55$=00p=)tq.Wy훿;>Ã\Hs*{"B9%̏n;/s%gH5D ȫ;vhoo?y$n/^o1غq/Dߏqf"vņ_wflC_}=~⁽ݽg;>wYٰ%IZS۷HS}D`5p%'Z#FRߜVk^j2H7-iʭ\8BGT;GIoMP.:߳P"& jss3yرA;[Sem{Owx=¶^Պ/`/3AkU۱!l7.반FkUG*͎UV Uc &^t^## HhV=;Gg,2n36DB-ΐ ^FVf ל@}D mtḍܱGe2Sr̙I΂He:5=v1qG6DԴ~J.\(0}y?=?p~/o㷾V~'_Ǐn&޵n;ݮ)y!L)mف3ߤyoF70`~ؑJ\}[ߚn3oM3>G"VlNv.{k"\"bF}>klLĨ 76iFF֥v[E U=䦢3ԓˆ2.W."Q&⹹'V?=w޵ܷ_Μ9_wC!Tv GP;h a^*r᧖BFwdDa8#9rَ=zih8 BGZ nuY?yFQh8ő C e| ?&B*LGc%1PspxHBXSG~|UɎm4KpU/E=BSD?1B!![R$ !DYI"B D,&X!*LBT$:4:~4!?IID̏!S\1}WBӻ/)lG{Y-w"d3k!JGX$bG!|Ǔrs$#g"vTZڅ(IĞbunq5!HX$b(\//>wEvF'nѨKI"TDg;2- ~uc@/';b̙K SpED)vTV7EM 7噦FA}$bO1#6Z< Bs"_"u$bONĄ4W$J,C]bzc;bp7Rn"B="%b!L'II%X$$bOJG~#_IBT$b!0IBQa|H?J>5!H'bkWؾtR0@DWɷ晈 \+LD‰m.Uc&TuO/̄1a &F͝1Qcp Da${>c&Jw`ntw7{G]Ϋf-L"jf^!H-^epW h=U>x&b!bN'II%X$$bOJG~#_IBT$b!(1) $b!IBTXĉX _jZAU4ZP|⭰ n Y7<%/t^d4nR)[]]9;z-&^4pSQ~*ۑ8F/g;emGP<~8^;_Gv9.F" >`ȃBN7Y5F:V*׬]4ȸI XDHL"%S܉åp/(@$bZun1 By}J٨2nv B䋞\uC#&sF-=b.׳QBD.XFNDD\$ djȏOU~D,&X!*LBT$b!G}衇W \ G ^&XYbťKD\Х/$XASW+tK6I""v(+]. uŬ:duA6G_Ig/eQCBRn{@pEK|K6I""vSLԐP[PpF W 0Ӧ1Wo_YW%"K軞!XbPV:5$.e*D(8+|~ei!l #M<{^z4V (8sl\WI*.NU^|ɦ$bD,D읝=Z]pE.$XYbŹsǻW9Zd$b!?)ø\_dMBT$b!0IBQa$ !DGGG% !Dqss3t)#1C:8+HV(PLrYg_Ww؁;ݓ'O{$⹹ѣGn݊}|9 Gz6ᇧhFCkpĬpvQ) QJȨO<ݻ;::R.t<|x,tJ2--m JN{h5wq*t DERD&5(@:yE1ktV0\n@DDI4n-Ls:o7ek---K, ݼy=EY eŒȢ T"TYai,5+IB%VƔ3ZiLeN=$1(+kA{yfʔRE$5(Yȷuߤ$ۦ~z\\ozz:0= ò,(,._/.a)C,f͚ӧO9r PvM6:tյ`Pv;w~~~~1|ǯѣGǏZ`pÉu0W[lj>\oGA"CuP)pBCP2 8 !eA(pBCPAH3T]U17bo\A(sՐ+yoG7-pv}PN&zxwfsWۘ:\.3R@B(à' 9jSe,˲k:ҪdgQ1d)pÀB(à;W& f"'II&&O0 pt(Ci)KL  $2 vڭɲ%Je"3d"IR!˲wen3˲,[t;2 N}XQ}<(YjJ RvވiY,KI(S=GSa8d pekkk+*****($$$$$rNA(g0rss׮][__BDw˖-<eaLغF x{{FDD86.c#a*,,\`իW{]СCr U؂Px޼y$W~~>Be CPPPuuux"ƗUpI Yuuu}].33s z0,ҥ~{뭷?^(:*^ CSmmm}}}mhh8S~Ʊ CPEE{g*4559$;!a0!zZ5ǖ`'2m.)2 A!!!|XؒP!($$ߩ*[0o]H4v~'Ieٲew_W ׯgzG`hm&L(((xcƌ#|y,e*Bp<O U0dEDD:t\ YYYӧO'"hK C\.+ ǏGkc0 ̔>JD/D"룢qu0|y0455)?ݿ[bźud2X,;vũ@+B\a8 PxgyF={l"rww=82 /s-((;w_Z%q0TWW:uJJJjjj\]eFrrr(:::''XPa$;;;>>㳳]]e.JKKf͚EDgϮ3ep B츸8777"rssCg8W_pƍ@FjFEE]x\/`8z_hhyJXXH$:v  Â% }Ǐ/))  "fԩ.]  0,h4)SR@@@hhFqIUV!a۽{w ݻw; a諮^tYK.rr==2 ;gaL[P2 8 !eA(pBCP2 8 !eA(pB< !eA(Kr\#Ҫ.SUZ :Zn1}Cٞӯ#y[Zt{ 5l$I*FZ>ICJsOZ(ul¡avCBʎ4UWmPL֩rSS֪Lm;RYvձLGw]4O1obWZ2(Y~9 }ep +tdW,#";1Y,˲wb(AjHR:kV,ˮHR5WitꄼJeY2&O\D )lr,JPiIIM 2ZE_?KǺ;:!/F\$cM4mQ:íUI56u$ EVPADVN>at'+5N-d%)b\6 #b-JL=iQRjj$; j"=\ꐢdˍaYar à !eA(ð0K !eA(pBCP2 8 !eA(pBCP/<&<<zlA(ð0{캺SN644̚5˅UtPa-..βᢴ4**ŋ<`0j4PW'` Dǎ#G!0Op/`:uj]]e`fkpЂ)S -,[__ʕ݋H$] hnn駟nܸB;vĈv{ ު*Gms0- :+*#|Fo_Ͻ.ӱ˲uW|Nj?T*y<^?*0|a9/OzWa穯mZLj&DΔ=zѣ#gW;nܸQOcp7`i[捯[n==­#GzQ1IJ_KDl)tLdY2X˹O?Y__YdŪFrڱsccr.\Mf!&Jyˏ4_&Wa>1}/V[b%hG,'Ok ^fnI-fټo[KO~(6:8?*,480weڍߕ>L&#;ekkk+*****($$$$$ߟa#'Bݧ߹e+㼽zXn Nʖ~__H/)LzVxv3Cj.K/o{cGs~(||xv+x}d0rss׿kWi_cccbšl+s[쎞tl\RW4ީ~;ݽc ` e\h.r^_#8,2{sO=mϊY:Gzn) n}ﯚr>]2ccc.痛öӪU{.ٵmk/ڶ5j"s_x0ڵk.,ŊԪ=efνa/PԢŎ=y]z彼_>}?r۹)>uZ\wCy}mASvavmˋ»wv~t'|Xj2k|(LPͭZuuu7yc~}=C7+sg̟MhgҶ]3:j'L&y7Xe?܊7]mKK9oo?5˕aǒyMMM*ة̲ڵk{G)%%fo % F#͑/_FV9msw>胎@hށ3x'˿뒒Tn:7Qmm_[N|]ZkՖ֖֖'{Yr6Sxڙ3ʵäfo ;jѠO}Pֿ-mWrMw|aʿU?wH}sÿYQ@@ڵkKJJ4 0J2,,l555DTQQqde7Y₲֖NN-m V:60[:t+;0Y؇3O}iӦ4N7eʔsڵkN7ǟ Ô(59g~hmmuaoLzzŪo燉)hY-&:]DD fVP|Ac[sxL\x-~4^kiizF?OVNZ$񲂫՞N1mۅզ޾}{ssKD:x$"'4Uo9e|Pëޮ&": yz"C0U<.9㞍fQ'ܤ<|f{CGb(#x;n,3x<ܹs{?>v3z3 رW5ߘ+V];ʧA26|.,>p{OYl2W(+t3;}4=ï FNS0N3tpݿ`䌹IzۖON=?ɿ)JRy=|~77鸞zl]S4s;777Q^J2 ͍[l2-b&FGU}'#fN3M[yddltdS>U<"*kA=h̔QTlJJ1*4%ϊI+<|fy \IIIMMW*NPvI?z4E:L}Kɖ}3kLgBw<;ħhOzOH[aY`o߾ .466'xwܹ>H;U;5 +>Y2SWZX,vSC9$$D !߶m[UUՀ~cywl;2gǏ[OqcO/MVjGUYS>x|[Lj(d9_-WղZk' }Ύ>-?da7'; Nq?g|ڵ+Mp/½v&"ZV:s|ijv|uO,uH52u!ybV##Lg%'ONL~bG-޼8S&g>ĎZんme'7m{n;wzx\9f" fk*'dW(?l{DeDް{-7# " ֔E=JZǟ<|s"u&%%|ɵL1Gtz"}_1`|Mm%Q(#a91eIT祧Zji,-X53-K|_t*DS><4[]p)qƯ P5557o bFє]/o:]M[߽0Ó/<iׇ-8y\=sرz‰SC׷D"v"¢^l9Zh-xSۗ(c Vg_jm!Hy?f1qKƯo򂤁lً'im;w>ZM,҉şg; ӛC+F+V9m赩gfʑ#\_Ѳi<0嘲dm*u v==%ͤ 8g9"nb|g3V[>sA>ܹsܹSLiii/^ܴiS2 kݶϲ,x5Z’ںk;̲lI) +a-[X'Boٓ]ZZtҴYfY}ỹ ?ryQ'{Ssa{[kO"p&}_#v^{8e>#$\ ܶxʾ?N?I~I=xf>+'}]|)cݿF.xDGLS[ka#3z>Y5og=x "X+}ؓEǶҟHF_XZF39fXumۅMO?gV?js[Gw#aQǭG >LM\{um L_$brŸnۗOx[Ke(hzja+e3?>jy˼y=(ʞOccc_ze?[n9'wfm+QQQD)jϾ0 AAA}Zk„ <o̘1B  춍IDAT\lYߘ9(*=<=;dz/Ǐ|-BDGC  h;l1<"R엵 Gm77n ߿/HXϣpܳ/Lfg_WMGz뭞I:;/okjogM'}w~8}t_0n/qSy<^nnnH$ o|A;;[Ιnߟkz/eL o'lCڶ G|}rz c`[K=wxrPGDD|ѝֱ,[pL`D$9vpȑD!;n~'>`/<^򵷶cLd___Ga\:[7 BHö;7gPnqμO/U,zƸH$}j.l.GrB2P>YR(ztGCy`0dff1n[Eyx.Ũ(F+C;%%緶 H~:l{,tƫ*-xeIЄ5j\!?9/S;Pvmv7}]gV-ZTsL1[555)?s^'"X,ǎk,L|EšlöS[[9=AʧN<;qNݨQ6yp2ڶ/[NwU(,G{ybz}J 455]kjݝzDe#gv?UO=cbkAW4eY6.ǭ=W?_cRt,/^n0&ΐ%̜9."ȇÉli@bl@Sϣ5Iyx&M7Ňk0~Gg6x<=2;7ƍ77b@Qݹ2`2LLՑBXAZn9t U,Ip2lrR%IY $"T-"%J\ "NL y#),XBD$ za@gCDT^^~5q0bĈ#FS"S:S'hb r"^2;se֗Q,˲ bYe+S#MLd$ SؖMD999.GR.5EթҼ$ERVLTY.\u# "]CJa&!.w[X0ǟP.-b%i`lx"vu9E~d{g2;lJn:QH/NҨ/x<h<NΎ3wssCg8=enܸa?3' "a8z`EXXH$:v  Â% }Ǐ/))1^lL:ҥK80,h4)StU$ 44TѸ*0޽؅Q||ݻ\@0UWW/]ꬥKVUU9`L|0 -eA(pBCP2 8 !eA(pBCP2 8 p\P2 aЪTZ""ҩSj])SHVu6ˎm-,~B( HgYe5aYeDUIb*YeY2&OjT4K0I %:uy r̶҆t@@;2 b:Ԭ$_žӘDDEytU ;Ɛ֩raTZpGgc0ed+S)͋Jtd$M)vWJI7E iE2u e*S6ֿ'2 b`Y9tiY _ƮpG?C!,jH)Wt(Ci "6#'I;,)k҆Erx0,!a0S,%'wZu{U1eI{w݂Z@YrB5EzeL>%؂PaauuuN2O)--mhh5k  Â[\\eg9;;;.. ?-8EiiiTTŋy<` h4 N0&;FDGC"!a1)>, _0RSS3uԺ:___e܁ ^CSLA"7pulmmmEEŸqhڴi555 ø4N0|C`]vm}}{ssskkȑ#_e˖X2c#a*..kll_nnnDDk CYaa ^^^^N e͛gO"yyy磿 P`0UWWi-~T@pI Muuu}].33s z0԰,ҥ~{뭷?^(:*{ CPmmפL'ej***.?Sqɱ% CMEEEKKKmmmך9$!jmkuu 0|!a P|X,nkkslIC(PTmmmŎO0o]H4v~'yejٲew_W ׯg쁛G`m&L(((xcƌ#y&e*Bp<O 04EDD:t\ YYYӧO'"hK B,\CW(?> '"___OOO'Ɣa3 ))) |>_DGEEzaXahjj:S~L^ODbX,;T_  .PᥩZӵֶV%|wg#K N-g:jbZәiIki_U2-e.Zu]8BD k!z"*ҍ $/UIb*ɓv`Ez{ݟ׿ B#ŚT;~N,5+Ib$[dnSr\n1IRf%Kб B%I+ʂ%/U)+ϢbY4:Pk#S+X \]ڙ$XVv΢ju(CiKL_vA(`ݚ,[ҏNb,9}0ZNPn6" EV_I}N~C({e%i6N^gZASi=p)vl(Yjt#@#܂P2 8 !eA(pBCP2 8 !eA(pBCP2 8 !eA(pBCP2 8 !eA(pBCP2 8 !eA(pBCP2 8 !e.aY%դΟIENDB`dlt-daemon-2.18.10/doc/images/dlt_core_dump_handler.png000066400000000000000000005112741446635226000227660ustar00rootroot00000000000000PNG  IHDRD pHYs   IDATxKlU;Ɯk|3Qt:N߿Oկ~9"/}n7c/wފ W @Ru۵^}t:N~~~~pppZ8<_8/ [ENyq,J-L59jiJNt1\(wowpp@2s/wޢ >")l;t:N\I-G[0<:::;;t:N4Mqxxg}嗛au zZ,3iGt:;[nH|?2>lhNt:w;w46.[}k_[<xgw:N8>>n-Iv MmQ 1W_}=vt:;&߿rrrA|Wnbi&t:NNfsݎ]4okgqf ^y̭3zä>ޣ'`X)\7^y|kl;Ny %$/h $/F!3|uvE߾9O7 zL-G?JH֭=ڗk^k>z)qg7|?o|:NtxSN <|B.B8t1BO}C{5~ϛt:N DxS:h`7>UCݨˆoH?i4GS{[v:N鼽lѕ A$@B!T/!5t!K(CYȪ>rۼ<Gc~vyjwj?.=Wuv;N穳n|l/Qk(vW?mzj1kוy)]gܯFGuK R7n7ء$ /Ÿ$ )y2`+ɼ6o75u_bzq]n̴G,Jay6l٬Viq?:N)2 C)MRLzqyn뵻꫷o&F޿sDy3sZG4NWOn,Q)eq6+/KKO{y4ԊԕłXa;ɇJK Hqq : 8&~]w=mkzk=Pl|P_wH^s͹$8#t. %V1nGvanܸѮ}Wv}nv'''=gggGGGw}g|]ڊ[zpp}ۢP: dE-5[*L\LaT0rib]@TDEKk.5Q+j,F%B@|EM^H8E @D~"/k.ךz(($xiА\=˓zRG_+9^Ããã;wԘG@<]^yGGGGGGf;;>ɉ$ /| '''/w}__|tt$- d~|w|w{[7)&_\XgKq}?BQ}}]UȀWksjTq%5;:Cև+NWY0I"R HhtPmOqu#BFrҀ-Euukt!u%VČ]4n'  ~fX+J{{mFdVfsqejuppj4}_#t.>,n7MӍ7{9IG;h{5 '''_>O>O|"3/__W~}ð^2s_|~w?vfa}׻u*lE(Ҽe N0$I 0RMEi~r CCfFBRCR5 ^Sʭ!IDBH2zP['E"H 0A W2^!xo -2wr2m}=f*F:~GI o<끒Nԑ3fC>R$(/~~#ȅk_//ݾ}ޚo-|tM5~|`uxӄ?y}m6+ #ITRiZ >4mSxć 4Vi23WL8ض2 c"^tCv.XRLJV$Md{H Rl `LG̫[*Ra2 )hnn BkGh%xH&6^׿yRW\\ ŵ4E|`~嗎{ #t~.sZ֊-n[׭޽{8~ _8==g>?#bw]ꫯfiij<NWO&ar p]0ьt@u}U ڊ'_+a͙\VZUk _5|'"W230 ʸJYfK`4+  Ue,K*!1,n NIv\>W>ve Wr(fS9 ۷Ǩ_ NށKOl˶22;7={;޹{rv^t:E4M$a888~_G^x_2%/EğOfy?{EL޺ukN,4ժ=J釽4MfVJi'5jg/+qPtI!(s-Asha眓urL>Ј476?@3Δ S$jsLRd=ySY{yif)TD#feCevKp9wH#y' ȄP3ì`B&QIDh 4X:QBB fMEI `6&)5 hgC![dBɠ$!"oEpN" K-k.@HD(&GWG "-&, NgX" H 5V5t:oԧ><nkzJ4R. meZܽ}|+n7ol0-At [Be\>Dy6L Vn?:38WsdJZA$ 0h(II^cRXlnYIr֜Kt%ա)%i0,aIʐ@\EDдdp2i&S@ ,Y!ThMdMہMb@њo 6b+Ѫ~)vu. ]9qBR̬40)i&'gj rmlv̼Gx Y۟4nD2Rdbb oS ޖ;h`FFJ߅||-̦iZVwyWy.{A-~Iw6Mvd/bAt~EAaq[F@fiGE4Nyn:]9;;kg>'' ڼ[ny{ /о۾2ۿ}Dēy:w7Z?/3SC>y=^#aټ֧"b4nb4yZWb LY}]N7KHnZ'efVZ)!u3hU)qRiL!$a_qo fcly,@ `JBIѬ".hɴq0b)$]BQ"iemd*PVeDJL䜑ВSZVf_Γ(a 1Zn<%@3ȔB\oѨ}eX;ae:{KgRI+PTJFB("##SsM[vMU-ZeAM̖DJm]&ꄡgt:ΛASW `f8~S?O~{>򑏬6K_o}ݼys܏R+ %86g7=0|#""!h "Y4<86ӘX V!ǚ0FjIT,IBxi5B I\Zf43@ʄM`3/WYa#I ZCZ6:7 3D)a4N*B-ݐHL$OIXjB"1 U|\lkD"sd].Y.IڀP@y($9nYUcr[l_\~}sP@:p 0h`찫[cp\52 >0ԑs @4^ҬN :!UhǫNsD,etpy^ly̖{VJ)w/Z[g3^g&sɨi^%ĔQʼnn&eVFwYA 9Ss, 1`f2SH1EifN{т\Ӵ :M[e˾&O>dR}"$7cjHkB]2SfAL"́M/a82^4 ^L2Qcf֌l]a2%pX eώmQZ ײެ2m?p ^t:F;9j~aw͛74?c?O~}oˀ?}sW'"~g~7~776im?RR_tf } PL5~ ;"Hn?]OR1da4V^F:F(HWhJ7E>yPڧ|K?,17-ЙYXq2 5!#rD4:IX[U=KzoއHYldr`2e̗m?P)NID&kE~+mTH7Ęm!a M RdB I J =eB3r# 9a0T{P2v4E%؇b .CunKFQD5jև~0/q Vk||m͛$ȯ\u?~Qb@`PTaќ{ˤ@K +# 'ڷ~U6_Vd{V϶z$@Tlyz.iD&3/`4@$$Ku}Y4%߲z)ѴJdesɜ˩ZkbzR$Aff%YVW@4 h 0,fAwt:N Q ]{KԵhr8=b4ȐR . D% 532m "ԢFM٫w4RY-`q錤I8WR-amNK\ͺDZ %%J>0j^n*(dJʴ7>I&[>3s5M1ƃ%msL&K貶?RM'Kř IDAT-fТeAqvAnKY4hϤ9o(kQ[k4O lmÑBeH1%dDYd99#gM ̈INtcte}Y#GNhf.Xxo숌@fP@E6UJ8ޕE#7apRnKiif2]5ޔӑpaD`~\N7[FX-rcL(6LBEŒdbWl.4$ (Pc@lt "CRlPs$r*0y5'=fϝT$7B A[&^aǕ*UTf l԰!ksP1dwt:N :> RtzGC ,Fr!W9h`Fbf.ݖyъN 0Ml#"ߍ[:#Is & h.@ޢERdIM ,0#`aޖͪN2*P۷ e Fэh,YK >W|fFo! iF >%3IٴQ,$՚08連}bER!i;ڈ\3';CBpL܈(&o " EIQA *US&b3@sI󌨘*ª,)Km[t:NWwAK0\xQ ,gn,4S99FbJ•+@R@aenXb@g\tCF>RVܬif S$y]ZZJde,h9097Q~SZ]Iv_<46M# aLʠyaQ$B̓qHE̶vTgOy^mZ"o;#h?ت-.P(dvf¾s@bUĄ+33SVP e\DP"BDWѤsp+M=t:NWo K],@MջfAH& b^l 4:q ‡$HPSD&wOf}4+(i[?t;Z: 餣 TBs `%}<FsRo(LYfTHhL@3 >ËNv `Bt0'Z̎0N7Zj![i^D͐ͮlڏe El]ĩd55LT$SN͠0b'bjřC9#BQ[,N{Č*"J8Q^a;ivBft[^h3"a!-:NtZ)VQ W5MZ#(3Vā㤠F75Z@ p:,d1:T,L4y@2`J#V\$a^Ҧ2AB@E"CfJIeͨ-V"W.T2Lc,[ )䫐UY)Jbi6L ݸ"2jvxtbu21SCfaY--91"6Ӓ+@jIf6x1fa.w(H8Lmdt֌ٚM dJdTz *bgjբ&BJ1 eS,ߠ9sf4H<4Sai@Jt:NWףbh.N@k}4hf@OV5q5+[+p&Z`&He6 Мn(ƒȉڌ5)BZ{K$2D.:\+ 0\0;؀q@y aEĦhVJR1cdkY[6sdbhHPeL2.b'3ryq0(؆-2"'9۰EUj%ږZ^fvxp@x43h6;d"cW D.i 3qw1CR-O)ʜ\ 6h@,xJC6 98L*5(+p(3}_2$ &ҍ5l8%YqyNƅ[ϝLI$ͬfگvUK[)[9篜 L_QkڐB")Z j(b@"r2sԪVVL󄩢V@VԊtDr}dv2)$V̶q-qkU[Y8Q433NL&D8!t:N+-NTd Øy}O@{M.UeQr>&P9IQ/j& kVbUaapb5,ޒ C&J8atC.h܆bw7je9\ X$]! bfa\Tfaۤya5i`UV\ *LS瑃7N?>=ߎnmܭK'ÃʹeqݼRJƲ(QZ$`b&MݼMDU5̚ 9ҧD%m&"j0Dbm]>+"U͠ql_N`'cf;t`A@()$|nwPl;NtT_ϚkM%!\HPT$LSm'´ĮM41uop.b TK81 '7((|fU<, w%ƍo3ry5Yl+kdn7'8\G8;/L$P lP^="z'8>䝗x`Gہx6Li8;}vTH?,t5ޚ{\A9L[jS5Yvg'y7S) BzjBfb"D!o*A"sK`-RTrmm4WtZAZ|4P׾ۤ{휯^7t0r1m^ hR7\'m9Iݘߙ;LrxϮt) = H@H--YLdt"!IEwP5B+B]4=======q] ^\y߯tۊ0 d tJ<@tf S{D35V#FeoQA&cH t1S3^|ijY?{'׋x+M(m'^ t/YI+$ dΦw*ryW[{D'Fw%$㝻SP"r";NIH&mV Ζ;$o z+կ *)J#`` -kx h`lHF#AxVrW֙4PttU/E]QPHT ݚ- 'XWؤaqs0?6˯}-NO~\WM(/eA28IŶ*9J&7[h:^_-_~8|tҖo½N[8nkȊYz%-|#49Dh~wZ&'R.&(9$G |\cy;@d=۶t r",%(f W?+b-Љi y둄L",4ՍaB`zR isřSqZsF򖭛 H;s-$tզ<}fwזҿ_4hlrhJy*XŴ[Φ!G24T"VH@[v9s($%Aeu<{wE@Na̗be/{zzzd{7Oj],W^Y5'E躩NT+HN$ARyN0"\ɲ%@#xMв4nsBν$BH ='A F(f|~_߼_OZDU+5m&CӢ(V//giaêmroض٦6!m/]nV?vxy^V V`4rx"l>oyM}nNW %X;Mmս^9 RRn@K4&VmwJ &6BrT>%t1`wD> .[chTgϐ========N_ZkIyc[ԃ#* G?]"u?̫Ji*;[7d[@F&,/uDYU{Of`Yʥw(pd1hWO_TiQ!Fv~hݬ6b16a>[Q N2ڸj`YEs8ŷV矜`<8T9.CdSrpIL,p(d4d!Gq t"@H \?u;=e^"p}]~|z>W🱂.d9S>@W G2.?o2o*/çR H֥@ 2&<7 95R]D:|خ@a IDATcZb^P'۞F(uݶmKͧ&5ު6.q$t4 o~{6m[ P41ͧںQ,_j'!N_٧/[[(j;\V\FG壳:nb( CDiR%QwMd631' d|/7ˇˣ_z!9qvWQUO ?sܟ՛eiu&o^~0ᆭxBG{] 7virhBH)ӀP뽢9.KmͦVjmNް0&/^,ruiOΕ0 ,!6* m{z'^. Ej[MEgok$Rںew1f26 \ruKנ.H~52Ohs覮"E9[ݛ_+ :gn"!CCumOOOOOOOO9~e 뿂~8ήsB t9aUڡY磖ȫ 4ȏ2yʃ^)3SJ`pÊCUC%oTFNi]mۈ^yk1)6ӏn-.&3pZ6ɽiǘb"Nrz|Ǿޗ'?(`~8;Mbs'cy{=}`7O^ܼqyt|`\7#PDUԤ(I1ɪU^7RkN ÁUMٮC9ߟۺج-jy5C. sc ham&W޶;vP@ .+E EY4 ꗜ.nSJ1ƜKW43d# k7&7"HQ׎( Ev.OE BA0D)B00U tn%k0PN7juP=;w/j]]VG`w|xswoԷ|~qqq/X.ܛgpoHg &XNN^ oW9P0f yy5(( R):P"O(D]yNl~0 kAc, l(ణf0ۻqo݂ 8;__ m@ڶ>r>>Y==SQ-.ӓ}ptxvzMVpjAYza!Vmڴ^%8c rbƆs}lbeiip7Y5'?#Wx2y~B1eYzDp>6L6uy*P0YàPԪnEF ]7+8JHd\ݲn*VRΓZȍ붕%$ɂ 1QTt"-dC@Iy%D04NʫK`aMOOOOOOOOc >;gv%R hFiNG1c1wJ= q;c7‡1{&(W># @!Q2R(aP&y~эxoor4z.>}8ǃaTk7g\6 :1+55ۺG `>ĈY7pnM[yˆ XQr}i%!BÑ A\;l%)ٿDQ&nh2v" F;ۋZ8'#tPf@fY9svomaO{zzzzzzz7U Y3)9A %<#=XV ]F ?U0o-&k JbJ"B n1)p )facKjCۼM{]֢dhd<ojw V`|[ǯnN?{u1l{ýEHMKq:d |^_\N,TcZXz[mT(bq`[oC0Ӏ:$ΟbD$u`9vS%-` 1PvnyZ8`B63[-ʻ-!߫3 gՃ.mW y2J+u|8c.>"D<,7Z4.=Ǻ+PYǃi %<"{ .UZ] N@N 91o+vzȡ4e҃X0,Ęw[#of4* F(BAE@rk QmJML~^g;bc=gҠ a'g7 7p"a;mx>;σC̦?B# K%`hڢu0BA"/#R9*o;_o+C b8D9Ru" "cgCqB).J=AwyI]?%@Z1DIPVxf `tP#N 4]'kΟ6צW0_f;󚅆9:P dP"hRj` ]ռʞϾy(RvfAn 0Z!H -napz];<nhW\ IeYjyZ߻?XmZf~हXm_põmfYomMQ(QokmQNe|00Q4 yϰ/bUjjÙ|r}aXn (3@\JT-HZ9}rQA ;-]ݕ^%#*4B$kb~cK4W 3ш 3HrL#hL`P%dye!.OQ,PRrGYYp8bBlĐ$ݺ,a,ǏOONO'lg'ťfo|ݡ[Ӌ;o=|뇟ظ?'Na.4kl"i8(m`VjAy(Z|46TUYJ)`T,l8B(Z-bm !@!e$ $a@ %w` %@E% d;vOf9WH >W 8ASD ========Eǝy2t= 5.E  (9Vn cî s;)#i g  ;~E1+eUw_X_>䃓O>}b|p;{MT[lry<>>x6Ov8c>|WEXU(m0.Y=ܸ8rmjvXzP=3RHq<ͧ:۞_<~y{_lOi: o KL#, r1!Atxzu =ߐltAhQޒR0%)9Bވ]dZ] \nО"d o`BgH:d.(\,A (@ٹ\`I&%,̓xD!\Ŋ|@ e/ (BQ,Q!BXN7Z#s0w !X,XhT\j(G|=َ;|B{uooޟܻsߚ'(g{}6?8qwh_ͯjX>Y_Lp?D%(T# ,zdd"V1 X>n?I|^N5;;ytj`~Νލ[->GO("X k.&OsRɉHB r;Sr@ ^ &9'&})dޔؕ*s`|ogHȕ?p0hUMsӪ"WPRnV*B($eMd{JҲ Ü<e1kw3s\!56pܶ]#dC 8MjGMֻxe,?xѭ8[~޳ýںMp|x:+?~Xmy`V Y/L<b7hn a9m!EҜ 㨁&30&ȥV˙LB~CC;B@OOOOOOO1Evyu()w(կVZa YQ @7p˱*Tn  G )3Fnܺ{o}xxk_z[_~M|etVUϷvwtX3,?oVO~f|'ɽ ~iנlws34 #E15Aq@ǧ'pqKm7fC./Λo|ý|ɓN7>lc"o a:)`p$26)7J` s!m.iFSl+N $rDAe67B sbOOOOOOOOQxC iX@fS0@@[lW$#Xw2T>N)y*i" #dfGY!$`Jq6Ynaxm|Gѭ>x8?kPfmSx>?;}/)0߲7g b09oˈuX}yXJ7o(a?4ɏ~ n~Y6 mxMEWrzy曈l?|O.Ƣ[E6$Ly`f*[Y\s:g^E#@0shN1Pr:$`̾v8d "8w:۬=======;G2t,`iF0d+<Ȃ@""nnP GD  Z,.d @"kyoQ$#;A2BYLIpgO7.f'w~a,Zo`DU d03?|c熳|h> IDATz3 _} Wm)N/ibzݠcYIu|ŢYrq^SU+m jjYHz2(ɣũo.w7~ aa`{p?ڑ+%6C> o-ðy.t] !kMLߢ@JWm^ⵉ{i?{9Mt2 ne #ab` $Q#AofYs`]f~ʦk-ɁxsNmDZOge{я?ܳ/9&(j_>{}7ˢG`2ZV3 0og7tP_Vv87Q00퍧mQm؛ ½]6O"?x'x㗿%S~4X.Y#Wb|1LAU|wWQmȝV#).~FNus8!k@% RWU0عs\dA|${ha)؞e9Af]d:h%Ad 3 ǐHB4RH5ow~<%+Hs/ESNxAS "0;> pPO)ǜ)r!W|8}㹵.ßhoޮסz(omfyvΝIVGɠᶙ-byޝ%a8YfRGqv{tڈgf7/NOϞ|0o|O~'?^q[-LM@khC]A&G_ij ޑ:ULO@]96usteM+)N,6˒&.\8\*.3$ Jsznq,AN Aɳp$rߓp%DVmZmV/I8lu[Np(\?VqN > bjoɋG7n(}Sg%u_'+9ojߜLfOLJl:Zu{M/=G=o0(f/N.zy?]!kڶjBme̩0IHIJBvdy |׵H:'_#yc uuA.$ݑ!2K=======yJQ/씀I $C.0A^Tit%"  H: AˊpA:QNX@Lr@.xrXG`/\\T%nUUi^o'A[f??>ؿS*uCON^ ޽VN:L1PRURZ1aHݸVftۮʻz:ȫĠa'<"M>Blڇ_ڃ?ߟmXT&ZޛXmyk}vEF6*DD$$ hi X$@TY23oKs=^kJ& ޛuY{o2=tqH̄^L.%@&/ty!\lk:^bk .PtizE(5O퐶i+ z,$.cїċ%W"A;gkqſ2534@Eٺ5u{̈{*8 -Z'S[h@]k(mR2# 9&伊̐٦L |8+_>n4mnva^uM5-᪡u||vl݁7(}1d7̰®٬&OO2Wemγy?:[^OSofao>So_}qv_?2dJz x7C`J0ĕRWZEF*hJR(2 )$c k|jMTB"v!(e*SLh&'S҂HƬu 2˝f o(x>.1hIvDRD .I T$ ׂfjvKPBel fR]-opZmIRB Uc&u1~fSu^ܹ,|ڟwws^8~BD|5`5Q90 WD 犒|Oomݡ/\? ð:_|O_=mYfb! uyh¥;7"/4 L1/F)ez4Ka*_lfW轢 c\ОwKqƖ0;|sZXXXXXXXǤ/0& P d2RY@P J3H(/F%z>(E# k˫l~vd;1Tx[S5Ým72C`xmYX>Χ0wWOw?k7}gLqZz粮[[pG<=`ūۛ~*/:t0H+>k޿W_û7ws|CL~瓟:,W|Ͽ7_v'M|^mY)`H)2 +"% b[r&!223.^&``K!D}8N1|7T A'HI0)j@_6ZiOE:eV_nGH8BtXE &adf 2\:3qF%/]1$lޡ2ˤE7a^*F t%I#a0GgOzu[׫jXHi<|YlD9G7ۿӟhWۇo⫿;s]N_}/q}_~|~z>}{%џa2De3-A%jNvrR[`&3SD fa˴i//Ql-\ /yyړQEY)@faaaaaaaQ𿁖~|4͇ԗDkYf$$Z.F9i8BiO[k 57 7,ů_kXz.Q-̀W)42C )I# p*qaX:ᘪmʋ] `ha՗ae?0N{{9}Uvu4oaZn{z3q+4wu?~m1 z(@R#DRh2bODG#ږ^9(0.a?a?D #&c+$׊(9.' /`> a2ϗ?^!7d4BLjMV<̰Ah=)0Bi%t8p"~5`t2Gkb% Ha$ ՛9·d`Hw7538^?' f[r q&~1:~^ zӆخl>LW1q~^aZt~~Sn= ]тA_Œ.q0'/-BdL p)Q_ p _nlnT2l$4CVʥ[;?$s7eﭱ{^y EtXi)#\r r?L.Z`-̼tҐ&"zhxɂRA߻!*6>%-fDqxi2"㛇nxz՚S}f~qNӏ;)Yȡ2IX1w Y ETB26?K2SSTFok dUmgXD’H*= ֧vb^@`$mɢYXXXXXXXoȦ{/ yA $I#YW(шYH\k7DIyHjŒQZ E.}y9He+ʡˤ5ʈНr6Nc``":s jXdz rȐ4ԡ<ݟ>|~>{uu]o?_~O:pV˶R*âΝL8Zu3Qa\?8Սf *\4 qvq#u&Tн iBZ p(DvPP(b͓8NSqhdis:vz=ξ^\)msZXXXXXXXoA[T 嚀 Jʜ@ dD9s3W4&Q.SXEWȕؑ =ىy1W:SFN9 ӹ͍w!)"["Ġ*IYV}mP*tXW@lL)MY,a=b\yx]v{Eg?ɗ?seSZB9G.06^\OE^J4+@VD4]o.k'(fFdUdHf8QA͵‰ zؾkSm] Qr<#HìD(e!(@̈xd]qF?,2~aaaaaaaQ"sBw "Q"벉.s+`Gh&obZo ޠ/w/x[Z|d0tf9X336zSeAQjHd)uگlD Lvq:ܤ\8 3Z"[e4#t]w4Env7kF)e"#PιTsTk[8UkJ(Jf0H L~x/G-nLD-.t  DJ+wWLyZzZ+^r-@;y?ܬN￾E)t|?gƿrz]T2y kc"S Tqj2-!HZ&/eYypq.G\Ľ}(~9WBPl5beBĘ \@ T#S`aaaaaaaQ_^/,DK"<;wOlo) )ifNrtZVh ˗y*fVMٗ2*/ >?\)Xs8MjJhR  :X<#gZFo(I;SMh,$A^IE8Y|{^c톧| ͦ~tm뫬qU0q:2 C y)8#j.UYvI% E)[&L2u?45OjRI=.i&d[P 8k*3_}N1ju1k{٢^XXXXXXXX_ ݷQjVx}9ͽ4 h+ itD_<^h~7!ݭb"%[租rl/Ex1|x,pu d1i|ߛ0L7T:z Q^ulK-\`!]qsfuz:m7~8Tá6*eU"uwKF9K0Y׺>@$:cNsDNcR)E tNtǩ֚YH>(x<LRgZ.'Izdi3 AC(iujUCT#caaaaaaaaQ.rS`0?l^IRdR$Tf}]da 6MD=H)%5yh%P0fv:.ڑI6?N/4"jBR2vt03 b =lH ̹ZґŲ,@J 3+*jJ Vz/áz]3u?է۟{GltU00MM42mj9TLQ.PȒYͰa,JobM#2)EJ*;@hΌZ%MIʹƨd:aJS4دrXƚ#`aaaaaaaQJ:@E&̚"àtj鈄쳂dfB\L5UE"H$MG_ݗ.?gr:GvZ 1Էi}g~\gczIh:GIEhg,"ղfZ~s["㌈6p`Pmy>yzؘ`Rwb0#ɸ,7;ݎ,B.XAd;5!_л̌_0!CtQ@5bpdyc{ lɒ\XXXXXXX  M̤Vzm x[d"bVtYf晦"&%GeBJ]d$,-CJBv-B'f g Db3F˱``&x~)~>]A9sCV}2xv콰VGn.be¤tp^65pRE zeP&tp_iK$G{\-vD0NveL)YdY*#D%C͜/8,4w*),aFʂrÔH 7pЃ%JraaaaaaaQ./~ofjh ٲJd@JZMMF&Ada2R>إW0ORf%DI٢yʌTM\*ff_/ IDATc!XXET'Z| SB!wD>n6ʺ8NyhzX]^q<;=oz{4՜F |<%2hU {Z :NGV~;p"G<5h8xNny?٩9YOfvꕌa{;͛{͹y3k# =NGY,Pf Fr3zG)6)bSkOS)|֛8t^?x<i!ӸZ@RzXħsE/,,,,,,, deY!osꈚDCZq*XϱZ <='aJ`ĜC=c1 :PxUקxxN]pG`א`(`=%Θg k\m}XuR 339itB#N*(7OD0 a(;t3BXm0l0͘Htkhe;OǽFY?p`Si2jbep`]@@LT1bvgll蹦 ,Oft(-D/ޕ!j=q>(ժT1lx< &3 x b{I¹̿z?xy\wfp8H(}C?xZwߏs%0qRsi3C4ei- I;Y n4~<# J_VRJ=2]mno'Ӆ~ebt/I4>Xug4u6)k"*:q< 1Y ۢ&p/O`W hQu8)X?{w#LouIpS,\1RAba]G9T3ͤ0B8\Ys̚D:@j=?N*R_ԭOzwU<q>9`14*08۟ϵ+_<T+ns;Ly.})8fzp1%pÈaitZXXXXXXXoA/7J|DqX6nB ~(hff ǟͣQ.K1_%,x??ї_9~ u=;;X ~Zq~:ke_yJYq(MsՀ_~,,,,,,,, ȯ f)d*Em}N8g UwW޺8H6͊L6"cQH y{{ U4Ȁbxuk7֊鬹52AY~z(ٯfuOMG;$֜gvf)5E !Oo}0Z|ܮuN"޾mןO|߿ TkI33+@fV \~ ,,,,,,,, ?H7 !F$ hN \\߾2>Cy_SNg7~5wW4S]äyՔnJ~]wytj7YyU9=1\w}ASgz8;VXkK_w#j^}zs?!\wmqNoWcNc=Gf{w͛߮w?sګoʰ|tۿݫ[_or<=i;$8%D5x ЕjakY*]CDa)KCz>Zq^~u;Z?fv֙n⫛ҟgW<رl1uNG2b߬z[;m7zx~?~}>Ͽ~oo}|ni?{hΪ;7H!$!B*%DBƫ^"؆mxիrzQ@( Z @zNr=Ϝk}jШWp}묽~;tѨX pA`%˅2yjPJ7,gP @c@ؔ-"R 2"6AQ/h5ny+j?ch7` e,̏?g{_:]ۯ~oCilW={>{K{z(Z֩O{S.yg@>>s}P̜٪K`ڧzelr\$NC>_ao'߀Z"\~vV+Xz+29uK_W О7u-~l˯?3 s3D[vx7|^(^pg5~q=ؠxrz{h˅_}U˱ka0/-ܷ{G`n70 >t͍KAO'``4?ő_w;/{k^_ٽw2SS\gX#x >qHb,F"1]kXʆO )ltrP5BDȊ, q%m [Kgg`3%t{^7T,1h.K}h`qa]Lq~e nn1;O9mSفW:qMϼOwV3Y6|o.xtB=R`7θ5Y+&1Bcdx9WtIAPc,ٝW_]fxpa۶I35>ѿh8ؼ}pSx3uG/Lvj/Fa>?Q4Ogn~؛d0L#:\tHi<3Ͽ>}p)0Zf-S=߳oa>̥+Z: YΦ~3ZÕ47n$s++8EM vڳpy9݅pyWlOR8 mͼ Ʈ( GIVTTTTTTT 8dMăΑ@V c’ %(`<8e30X )К|;g3SO{s [߼>n0 SG@[uwML֐._pӵ|gN}0?z+W\w3@wO7|XVZ;w6v;w'/LNS8_hK#@-wmj;nZB=Y2NN`z Ltv]wیD+E]Ba-aSW߹3 w/GTCG>lƣMן7xGa[^O?>/kfO~~qg#0pGl\x&ı-z:_{LywwN߉- \~ݾ_Rbh!(h c_ziaka8mPFqAaGRCUxi0=w÷|akq3ngh&&sY:Ιglܬ7Qfބn߾} .yZݴِ'&?o?;YӃtގ-fi֌|q:(  D#H:b8$%^f^E#h &IkS:3w#j)h<F1qBRpAHVL̏3P;lZ4 @e2ߚͽGD|+ߊ<^|#&:;(OxXؚD2|s7 aq8 wގ0Rhf0#Q%V떛+"#wgwuK]nX8ꑎ"Йͽfp8 QGUæήQKg=-?w?4Y` ʡaIk!︭a#sނ&݆T_޺e@k\ԥ1Qnw߹h mT5`-~ m峮b! {{3׈K9af38XС/|u W]=73EMш)c?nl> w< ~a_)7JP|8v.lPMުq|'2*Ҩ+H IDATɓ4`+ +I: k0Q)Θ_}̵O|j_3w7(˃Z4Sw!WZB7>/=dp?q˳˿o~>w}w_?\ykw0qGX0O~> CXı,X곫ϘN, =8x'JY6B%Mm!+=XXť7I)TGp ~`vLYq'kQP/SZW +CL ʳ;0p j(|n}ϯ,Ll GpA0Vo5mnn Ҹ0GVg y",Cs#2y)F{ z ͅ~_`lacp1p _ "PU ufrKFc{P wTٽљ8º C8YlO"m^f ~M^ GAp oܻxq:V\,DC>3xmԛFq< H>xM_zߜ(r|kwl8DLM\ C  {xxOS3rkv4쪌8PK/q1`G^f3_z+F{^w+.[V!fom<  3_»~vE%w'䞴>.v`:ՊF_/6Ÿ?/ީ+\<̾/ - g@ :#r(Hr@A%+******hcKz"*kk2qC~L0g6Ȃ8 ydf^4;o>}t挙liK7:nZßk678}3~5z_ H ?{Z7zq(btgn  _g_~1&.2|1[. Њ@D[Ĵ^x+߀U㗿'{ꖁ 3n ia HXsl f &`m J! .2f2A+2&Z ?q[@_ᩩ[O~3[_" 0(;[plS?oܜ~.1!P84%}iϺ|KқoB~zpqhm9GeCɃ l(2>cxW KQ$Co-o}/[W} CA?ń9x,4.a &LB=:x=iv0ABI}aEGa@ʔ[SEKI5)3Ff7j~ .hחƖf^2*FE׿կ.;r%WچGoxѕWw\16>[_LgE?߮~{zgl'O91!_fSl&MR$3?Z t]Z4fj g 3H:[.z_9W_}'ﴙтhս=;vţ_E+b_ 3j#'rr >pIm$wttݙ_.{`t}ks}ܿ9 W>%FcG?u?uIϽ@Z/O_|(ɩ=dKOO}䣯ʫ~z, }޳K΋wr}QHFpS,E#96M9~_sO<Ⱦ뭿?] KGPT+r _QQQQQQQ)Bs*(@sIXU,"JAi°{x4LuZKL5i8iHx+GgVf|{q_~Шuo|U/$- :g-o#Z;^Ҹ]4y3XQG衙zk96`~\c4>럍]2s+o޳R_cң@{y(:rg]9vn] up´;~_}S{F0FU_‡ TbMZ{Ͻ W\e7~=D!+crཏmQ 6z+vCMϹ6![^V\p`~;?ܵffV{=xdaiڟz]=>>?٠P&H7IO{Ƶ~!:I~S҇aG>IaSA1Vr\j 05}snzZAZ][s'Z`>λO}C,g`l؛R؅jp`?nG9uHr@u0i>m?|KgTrQn.޹=L?E;1l(y-n-=%۳Q?h7I)4?t۝F@tciq\0EA;H4ٖz;̯:OL)ruC}Nɳn2>b̠QwR8NO  ?ʜR֘AZ41Qd3Brh/vvn.M&5,\^tUIRgZ#.ڨVh? DyrlG4Vj;ҞGEMenPNx8(fv(Ɩj1kaKgta9'k}is-/EahȄdFAwbGZR&g!9D /, 4|EEEAU-?nW6<03!Y0 ecZjpFyZMw$xdmq5 6M0UoIK;bð1ma p5ɹiͭ f#d 79+ Sۍ&<;kd<^Ig'=D5 ,-Ia0j''I I(`0yҬ-:3ȌbDǛSl)F:j4 uಋL?#h0.&xֈ >( ,yk3 &FJhƘ~8asb-?Xjwú 8H>-&XD6l9?uSW 0;-$~8X VaPgVIǵLaJǃY `v(ϳ8=0^<"6MO4a0pI T֋ReY[c xLPC Eg0zpl:bGlh4[9pl7[.%\Y 84:ԱS4:Nxxg(insb7AL޶| 0vzsy_( ;vzxqF a:NhBfRp`W5OA2NC7.jĜ'&ý3)zJHp x(ByR&jh֛J uLX/0 U8G9RvbHVf_#0ٮ 6 eQ22i W@=,-/1C̦QwT}դx*ʝ[a"6-63S7"/fL *M \}q<61=xpmեz 84Φ~{U o. НCäL\X|JXIpJ@DH *19PPh*******hu`HC JCb@mTsRNٓPy69棤ùh&E~&0m͚;:Jd|ǺIr7V6^/Рz2>I9D?20cyg(5NGRǡyiZ,kjȳ(؏tf'\n p2(|\gF HظNӦɠGPa&$xy7;qjV֎D( RR-aT3Cݨ&bBJ10@ZJ~PUca>%J$d="D$=QPWu !戁&F (~֢ l,PI|{X4"Mƌ:4F5ń "19V Q並AxU B.#XA0TBV( V5e;"e607 "aK,L8"1qNYUHXUTsH"Ug^$d@L`4SK&c+vLpw* Cd^T=q@^2T^JF:"VPUĹD Rw QY"b*FY-8} c`WTTTT RO,  XBlElwp'ʢĪjDUYaZ- Y60`U@ըF l} )[Q⋢POb}fL,iXFBk*!iݘ) 2!%%xٔHKU @C b  ,CT~k0C`@F3IUPU9NDPVBEPT3$ +INTDՐ sS!z0dȩ^ QAD^)6lj99*@ȫzكCp5@DlLfޱx|*/J=8zҥP6(*~}R@Lr)$Hu}jÀHˈB`"%#^2q.GYs\}reCKle`񅊊C)U{xgbbY6zFA-ET3,!3*)D|h]ƃe.A%R"QWWQ9U!WN QQCǓ=g1y6L^EbL/-=u@u2.PjW/-:8B8_IzUP%RC^IBăHI|7""eCT J(x0䃓-R@!B (6< "RB7<V HO@D9E%EqyRxaEaE8LN C1C̺zV:U+01P8Qv y*!pDeL_+;()KWa8"E U쀂1yLr'ޫ_ ADS=CHe""%^PQ-(QHDTET Pjw@ RZhaRDcJoX𨀰TTTTTTTT FY8`2 ]3dxJ(K!A;!U* %6 yn, g 1z!u^3U-(Ψ9c H-C V@S"CL  k-BA`J`\`bH=\J PE D2PE!!(@ANJ3RR'N X_1y@ ꅄP_0eB(/ev\@Ot2u;;A@)Kzцyq E9 t7nr crܒrj5ݾ.-%BkNjb`a02HDfE q"H9 2Ď)Pr"9 P&PKdH@1({D0D QVNrtYf&ˬ70BKiOWe+ TUSГcBUx┵`S$$9SnIJ c {#yvb ^֬P(aCDFկgT1^$ IDATr (@TDWc{ UTTTTTTTT Κ(VN7ױSk\(֜E֍`Xò=JEaad"c-3DT(/(P&F6`* HQ@`J6B4* '2afd4dВdm 2Dʎ! ڈODEZ.'WQA;AWuB2Tz9B) UG:u9dBVe)ul^J2Rf"CGʂcVUP07n%Oʘ7G'0 K X|EEEEEEEEeyaQAybIvr|Yx"t< ĵIVؘl D^>_Ә$kV @Qu 5egzQ6jJp jF%JBިQv-qaBKX/֯)u23!f;':^ȣwnAIHK/"nDQg#YWKey'D%.-' Ȁ6:Q5 P>cO+^n/я\wV_9ִ;o.a .#u “ ɾqeCNjcCcvI$"\v-PQQQQ)JW<=a?Nh8<q>^OmK(56`qs :V/mKkʕqj'׶{~S9N38 0 ]a'l޲I 1|G9w^Q^Zee7M;~LCLJǯڑO߿3[k^T򽢢ESZ7&O,=SYGXeHMF5EMz\1(l<  (`N˾kkqa̱(NPr>J , qёZvsNim#f> ( 9p'5M؜4M08*EnpB0s'.7|b9z=ވW$!wWWW'&&DTJ?>>2cLEes1+YJ7cYe7&ÔOf58z @֓`t|<@X!ˣ0 &ULhWIH(3N BqC6( CzsG #"=X _ J|M+~ &[`G:0Ck?𘪿ap8********/,"dzƘk!z|^wє]JG+?*6(e.'ڍ!cYf=&X0륨kjQdʾFYԈHUꑾ9|D6jl\QB&@G:E9$i{$IV+_NNNfYVO $y̆%wO][N&uhtHl:C&gx'2fCP/_D;*{\5@U!PPX%1*;twTL:mb;$jǡ $(1 TQc{남C<_眻{oqq=eү_&ql'C$,J-aozˡGt2c=/Ay0c1 1c1 1c1N c1c1c1'x1cqg1cqg1c>EѮ]^״m6rqp1n7MS)Y/z=+0,yw0cqgp8t]7/˗\r֭[}};Pf1j~+`ַ֚izȑ/~8o0 Y1cqgk.첥"K_׿|;ox.2V%PJc0cqg1"p7A066~4Vz;wn޼yii+'>l61Ƽ//d>O}S'|_}XҵDZR(R]Wx(8Ac:TvT*_~] x^juz_?֯~] ࢋ.曳,V7&=c1'xvzֳ?я.ݻj[n0LNN>OСCe:?묳Fr ={r)V}.n- CezF4MӴ( ugggGFF z^P hnn'y^Q8f1'xvs]w8a|:t(w7m۶{7iͽ=yK_JDexEe;wV_[F1c?gOy[gS1Mp|1`0P夔RE,繜c18c͠ZJ)u9v7c1'x#NCDEQT*J: |oIb1MI(ͦ6㲡}8j~0,Zc18GYYYk1Q "u[VA`ֺ[1c<{4y^T*En;4O+ 1c<{y`+Ϥij)$дe{1'5  $P1=x(pc0~Ygc| bcL#$Ya?֢ܟs<$Y^ks-S^rC$4~W!:-qZ~ٝD^5ϬdC6 *$0<%ǠP-/VN+V[ FxcԻ=OШV<ǛްY3l hG#Cf6.! `\I!`.4 D7ՊJ3וGBVN;c1N;%=7˕ou:~O6oL'FeWB!|<`r/hnH"ID [#cRр0q1JE03=?55g %a'}G YΒ1|V6|MC^,6h߽e^7U M,'x4-['̋X0 y\{8W:u(PwPR# C+VF1'Փtyҁ $Ŷg="JeYEQxC0YiEQiJ, )|H@ϯFYхtz u P@Ths aE@Q$dN#B3 SSh/ [#5y.@X"DZ뺮 cO_3ꬊT@ O:$JdX$'x{9Dy^dà2OL͑h8Ȣj0 =;$@mpBwĨ5*RG\aY*NŏRd[<QT^uP>ah+Em4QhۍF cU_X ZN-|!+!1~ ({0*J%I8NZVg1PxA4zc\g w~fV:ʔn"*h-*SdsYv`cu<- 35t a8=bÆQk!PFVŻ105X呞iՐBB1~kxmZ6 ,u]@ݮU+>8X [' }R)A]˖KDXB*+r@> 9DRYY6&h&M*#4\ @ Qx2t7-fiхZ{755UI1o ^,ZX m\+ , Kʐx:ㆲE0 $ ðZ4V+Xj'Ñ BlNN5izT۝n̄eR'kAd)B8%k˜enp=D Z0{wJtS CX/~x^9jRJމ1'O IDAT7 ~u !BU4ZSU-쥼aXZZi&aN6՜saN7S5 LH;*@Z2X6( @ ?L.:9\U.|[ [>sq+ˋfu)Zt =7ڬR1Bzyy2{<%2!}$ @̀Vf a4\Jdl7XkGFFxGD&``cJw^]NoNw B E>"x BxEQdbeH=RhW^UC`0dQVXTVP2$AN3qºpd'n 'Ʀg撴nk~ FxwsϺ MgOn4/g'lҩ "'WkރfyYwygȱ( 7w83oc-7߷}Ԓq\*LY9U("qy.h4,   ul+n+Q (pRmEؘI :͋ttֈ5Kd:.wyY:z`j4O8raoJlV| OaVfc<cFDd(p({Y=Zl0 tn#fEfE  /Y=Wjӗ_9 #պ KkUk<@ZXҚ(FY=hTxn%gJFUjBP0yT΅tBPuJ##8_)͊n?::wpja$ ֏:sOm߾=ҹ1"ϊ=O^XaPMsd~j?/ v}ȅ54>6joҗ:z k\/_~s=PPv|WӬVK^k.hLժ[O"Mc(sڝ~*)(s]_+3(‚17=,T8A璱*(3panSUwǝ3$ެkI+ PE{y4p3W=hur _П Q1 B xSޖs'[k˧xscͱ %@5Z峡rQ8-KI7@@lh7w%Jv7G,_=[sqyAŅbʪjm8Ҏ28Tl-Bxyn(eZgnnyu |>N04A<=q۞xkcBN3ӻݠRiQis)9Gy!o\[wvcQ z[O~ۏu)s-dXFm8?NLlLmTO L-3[0 mȔ[ߒp#,9fU,voi᠟,;a i Y&ht5jnnwZbIjk`R k8paE3l&Y7cao :\JZҠeثzK[t6 +'WǁYeŚ~6AAcd [t{ ͺwxR3c~@8|:p3H O: B"h@1Aʯ InD!Zsp#4$3 'p{p!HU4! XjEbSe U;o;x>מɉV^T;~zχ>6.u眷-v>p8e'ͧz.:֜O_ԛ;>7h|:Bjj~#^Ė;{OyۮzKfvzx//?b{ ٯ7o-%d\~p?8xO>^zv5:82 yCꦛPsfz~ _t/h=gAL_Zȇ>TEnX?Xu22Q :$-r=Kdj\̎ZQ^T!^ vlK3|ajbjvNz_N,`55u{K ƫrz&gOD˪6 w`W%c)9c,G!Hh@@("P2S,B 팦nX@%?a%̝.2KUa_i mw}뛷q;B'''2Vx#놱woy v}&jZRoxFN?_^_~cSN|fw󝟪UM|{x_{*\?شqQV[Зk|=?sY/xa2WpYgM¬_}u۟{g^go~֫z[ _⤓OL6>'_g菾?{R'w^{W g=}黶MLT=xuo}_{[#sBhXkrv_.)xNPm4N82ә|{6x 2[{np "a<&jOg:HgǠSϓSEǣa1v'x Z2#!! VLW^;.(fU+@y/<Dz2(Z/}BGkmzMǃ$v'67~\wix{NٱutbR&Tl׿,;'EY9ӿy- _ff'~V}_.|#/CޭᓟͰM/&w3vnZ%H.towMQkvGp|sdΨJ0tSN;9g[dN3g _rᗮ/=9nxy{0:2򶷾yfhb_~t˝W}i<3&6񲷼[~?s?w/f#0H吚(|fbp-~.prK>Ԧ~A0.X4i;5f=~9ě_u7- A _ A8~klLQbky3;`BYVU "0=! e%1͚_xkb-dHvՊOaQKKi)~;w{]PBtzLLēZyZ g뵱F6W}doÑY,,.FEugu'49hwgC8abf{zGZ6a&&w,/* 97oݰ斎[af3զm`?'!b%yR&1vd JsFhwA~rݙ/L%@<@Q(\)oڴ[Rl޺'1HRB>b5qd뉵;\B4HX);16-Â\LNWɼNXN6O( X1&ݧq @j95hY΃eC n@a >q#fERjʳǫ@:Jt]m\c,'#&!- X!,\cc0 EB,#_~uՉ>oxG755sxEƦ]ӟW~rb-GKN; r׎'>-V'wt穲-mS`Tfn?j;ם}Ξ}+:dzqRZ#78{knrrw:>mŅC_x+~&IC!﫿}*xť;r{"Uk7\: 95p0 2a?Ra:2{@k]E<+,3k^'RAeJ&^ى^+_muk0 ,+yˈOD-Yn2qr5)eAq#PZ8'A$6ddzL5Z  k 1$9?Bck|#(QP)\1"߀%:(*'G2c?xl3pI֜W_d3w@|C$vyN hM,p)L CFu @j8vl: _/C>_qROdat %"ZZ:{FZ(l9Zk<*pe #c7lprfm<vwxi;' xggq>|Ƈbj~ .i$o3Ә[['OV9?}[ߙ}wM[>_p*>'~'HK[Ǧs_pU_1FJ4Xo$elz/['e.pRZkAB^:`dz,֮okz-nh$IVZ}7bP!Z?ָ?2}Z t\z' )Zx{4(gZd^YI7(?6Z ,4 *7@@Nd~Nc~N3Y<<R+ >pɐܑګ_%UgHEߓ0 5i!+u;J#AJJa)P*D=!F,t /h_0TȪ.`,B<o n(]W:7\ #O ww9n^2/UFeL<691ώL4!TBV (N{5p8<=j}ȁ͛7VUլE&H, X2 4 ZC@Z{%W|.rW 'xuYBWt/~OR\-)yy^y-Zc1U.eYN0,/ʯ)λ!`!m. ~V lyH/XȒ;7pNFP_Z=cQ<#c{ hMsrRC$  J $5AЄJ V%i Y ke!VZ#ճ,'tUX%5V5.03m- HrAu9S%i֡u]υX!a %[éY}QG4Bwi0sI).fO=iaaIazdjOA''fuv:a:2B =ɽJU=rMI{AiԪ&aon9>=s]guϝמ9ifvݛ޲i|f^csbZؓDm}&l;6?F4@cJԡKYP5kf@S FVKhhVeE{3N滞;+a+:2޲uG*RzZFDeCrl6Wp8#UBSQR{4-գ(*t[+,<5'IRVtZy^W R NZY+(y0,`0(ߢNv IDAT#8V ZҨ"-`L-2wC2V;AX8u:Ll^?p~F,4lҐVZhǥw8BM+ծ)6xcCrs4Achr@ Kd_mҖm09: eɬ%YfA˧sKuN 0dCd!{oT FyBIctkn]j J4ɒ@ H tݙ5rx##n^qܺciFp\T膭 ^w|WZ릦yn7ly^M'R% T8U".Y\h؁ʒxk0;V!G,iQ ܸ;jIzD\%p(|)DD_1@[0/#D5$ Q:LOO_zk' SOMWթsjꜽoZkNXm,R:lfqEk5)Ql'Q4JL1,˔RD8mkՏ 2ĔTB$Ib۶eYa>5!C있 q\* )El6Mu]C7 i~LmF8H oHEaY&( SPv!ƵtLݐD|RšzsEJO>= Ԟ86,q )ɝP$_ڿ[ASŐ10%J(Qao] H@si!!*6iTҊi46g E S'hb@Y .4j6cPs[io`,׆*4=sñZ]+"S8ͤ9̗W6 MݵAo5^-VSqH@M1Z6-l5y幘߿@#w̬,zQbO'y;̓ـ`-7 ),y SW~X MNR4WJ4z -[68Zu Vxpo; Π燾cdSy$ewЍ'&6YSBBZU\ghiLLuJ)뵱ZGIMl_a%X1x d6K|LFNv6_9V\>c[Om{8 >4[x(9 BfckѝP߂'gؖU @4 J(Q[n4 @ra˖6\mK [ R#SHH*Gi R_rŹ\xt\+0UsCcT"'.`#,Ǔ I}!@ATdAau2t']%TP(/<RbQ I;U[q-ru㬣yTAj2mv-~MҰ2 2;cz۶ D^ 2Y-'Ts'Qv7WTaIf3p B3˼^MԯR3ϯJrIBI )U n[ fy"f+ b s^PZ9g&i! ^ݏoO߾}O~8?|BbvFn^$(8G$U1=V*K/tiiiyy_+^6,ֶm#81cَqm6MSG ͳy^Yy1erSt:^yhkXRfgl~Z58hJ`1&44fvx!j/8vv_r%'pBEZjٟٸh EGŴb倝 .œ**)?`| __(Y߽yL4֏Yƈa,Z |S.gTKm:#stS Ҋ:pZD%J8 jJ;.lިv$|˭eba1.qKDɠ2T3fq׵,^Z:5^kkdZZK)ϤU8lP0ETz~$'6MKP.a}6M' R5g\WxֈIWvk(`zv$wȯyvh"RwZ7dl=J}0BH"H+f&Cuם T 1?عu:۠Vk6 Ԇn{fi{x;~8S,ZZZzްk׮??سg۷};ӞԧxwU*۷{ "(:1_T*Fc׮]W_}qw%[l[or0Ї>tgqOyS?-[\qs1I's9'|.4r['I繑 ih4Fe]uU;v[n?n{ꩧ| _xGuY~ѷZE6mڵku]g۶Q̬U*8 . "Ge/{ٶm4KA8cYVZ/~`ioYu{ݑGID~0v#NZ!.R7dkB7E~Jo'׭nOzw;؞'c(NJPP^i)ENPwܕvowJX$_L!E 17.6`K(QDÃ+bJ(u2C/EWJaXoQ_W_xų{箻ky7Zap]wmmm0:-2 4ՏؘmEQO~򓫫emݺ6m27/;}_<ΞJ388sϭz76,^_pf7m,_<0==G?f$%\yfIj5d8gg\ś&''F177'ܶmM7i;/OO[yAضm2h+T[smfGEB⇃BYtgAsq䣞?)w`!pL@>T*)Ÿ"RJ1hA 4J{+b%J(g4 UIp&$ЎKp$ Sxn98<2^S)*>| q\9CAiAjxIj`Im1H\Aye;~[? <MEotue5Ϯ>\/glݲYH]m۝|fIv{:psy$7kǗSx+'_g{Zݾa2vC q٬`ffjE,;7{ff&s9ꨣ(l6iZI{glfƂ& 0 oS')8pB؉'hhmneYyOMMEzlllqqNx' 5j /|ӛޔeQG{>v|W_}UW޽})={l߾=9۶8<$In߾lyqm۶v]Tl>#9rKz7t:-[q< Rfoivy5M"^[[3 A^oڴ)˲ZV8'?֦̔<}'BSbuNO%w'";[BP60(/› K hۂbS"@xL+̩Q̌h*^D%J ^t!tfOSSsv_2BT@+@ `Zs&?` I֒l4Ki)L @&i  RkZЦL5Bm} n-{rv7Ղ 5t 1 _w9.?7_I'.(ͪձ4cZ/ VOHn۶}{UW]UVWWW'&& Ϟ<99ib,Y\\ݻ״lNOO{vI"2Mq;u믿/~q^_ZZںu}wG'I9OԶɻ|q;v$In߾}wqivqEQtxEy&Eak1)Oy x|vvvrrP(w/PƯxb[곟?')dzq&Xʬ*qBp9]v٥^-oyKZ;;O:߽7 oxfff0ڵ0͛7?Yzk_{|Q5͍BEݻ?}{߻馛R6m:cqJ3g0n!D}$uwݱ1CU򕯜z'|G?Q)gi:G+aQ !86Jj?SN9RdW?,-s3iv`b]we+9=v*%tcMKKIGE( z'~2x!Ĺ'?c9F)5;;Wc/o~ۉϿˌbV[\\4->ϼow}ر/x ^cb϶m+>|BڵYzw;v%\r|󟟘8Ӯ:Ȟ1q7!J09@~߶텅 ..ۏ=o~JIJz2/ebbwqAܹ/|*[NcvF|s{O: WU8>>jo>//z{;쳅&նmE)lmۮV_q7x 4غ`m+b2RȢ>Tʲpl1 M8cX\\4SQ)Zǵu$ILV5]T0fV6dzl6_ڶ4=P ,\ZZ&}wKˇoEVPİɛ6#+0G/; =t4'z(lBd' bUD%JƸǙF̽>P*Ȇ (Ӱ%lb.bϪ 7ZeĕP4|V7|.ֹ>SǛ_i,ML߷^X^WkZkjuhRӳ[WWDkuiێ$W]i9B+)~'icl*'$#7I=t8';F?kVbhFH979h(vFKy& x0Xެ̬J%XZf<^I?}A d?\EC|SFAKMJod4bJAuGsbx#Ck $ _ 6h.n f%*Daǟ<2T!٩6y(-.8#YfqCP"L 9H̠s{ H(궫FZ$j)͌yj}xZZemeٱyo&i?ZTY5=Uݻ+D{W]4=;Vukm;m;+O޵46VԆ4N;ڶm(͵R #6+{('q'i9TVEDf45z` kcnwlw ^??$ @@ iعGȁ m\F . _D% ~}"ŠLbӆPĠRז!L8fuFnj0HP6zZGltJ^]IyumH%rx-*tiZZYVuu~oXZB#3̴T4,2ք" 'gshOEg2&:*soZs"Jdllt>i8NQK !͛wۍy;II@ZAsGͪMhU3M X3x2o\?Fz /{%J8, S0 gJCqFI<4Ć#&  Y`bbdR.= w85ꐘ)E&M/XW'so,K3=NӼZm42[LܲQ Cf[~.6\FѨ,,;;?stNNU B.w9m^O=l^WNkNMHh9j(2j"!U*(v{ԥmֺQJ9dflP#Lev- Hhk`a=j/0ӒmfBԲoxW!k^R?SD%N7M[V hAiƪh]XJ z\KdAr,BRG%.պTΘ" i,,RچfN96I<#88X䦹vO͙msׯdIt^\YZDD3ܽiv.^%ˊFōzwT1kw4&FVWVV\}O0AvƓ.NfYf軩.zZM_. pƘ&V)e|~?zZh,V85o ݩH3@pAN )Ä)ozd a)6,m(&64C ogL'auA>H>Lr  lXn-PwZb BH m8Tj0B!B?"r`|lQU"ɧay"mK(@D&뭬A((Vaj:o:yR  D#@G#mi>Vkh`PL͏}̵-p 4c馩ݹoIGc$HչU)b0XD&wD!z";d }][H``3+Di(S\cRH)C]xG!Y[j-.-ޕM|O}kyQl*Opگݭ“~>`ʶN*Zρ*k%J(Qpc PdP( Ĺ1hԪ"v8H,M644H)i4:ˁn,E) BKm;(a5bv\6sG ehyBSiGS/v CkϠh zM=|dUƠpƑQ4Z 1ej]ν96nyw~5YVj뽧Lm}wե_w~>>7ԟ#ƗZ-q)xuJE:N⨣p[秲b=GuH3B!4q6R eeD%J T #(W dIҐF"hR64F$I4sjf=)(bҊA) -4A1%1P>(aXOX/Q!B}l@H;]B<'Je`α\n5 }K3y%_?yO>|oݽ/Og6NcOWm Bo_{~×>u~aiC6MiWUYkkkZQT[AAposi|c_S0]놧5.ءNֲ_D%Ո8#&E2FfLDLA3 KÆrma;q Wخ]ars%\\)\)l[uf!tfV['و-$!eK=t?Ն38'U!SNC;>8*~Wf3aop8,Lݗ}^{?NqB6f{n2Hv/|}TpVjD?HEc'/[_t֯s㍿}wWa/9 +6J(^ Y(QD?LV'<`B Lӡuqkdz>4b'E빆hRrH+iAC<&i1Fѡe${Ui _!g n!  *d,뜡+mh: VOqTU{ʴ[iOI hN_DXRYxl2x_;t<ŝwu,׀$ 9s%%y/QDйm=qQH3 fI@ \ .%P'5 9R%iƤp AiƈH 4c1pV0#a=q̦D }wפy@~.cX)BI$]jd҃,`p9BϮVSi qOft;oy$&V>$P-{H(MW^+ &._rщΏT. -*^))QD>W]3G$H@ ARBB$5)c `)X  iEbbf4c1M4cɸzXlT}({]o` kk+"+ ;?~Yq/|Xܗ֪O**$Z^tlW3++HcY gy;pn|m?zZe?{wmYUߋ;~(sA1JS{GAHy& KL& rd\:\QcT)9uݮ~6ϮSeEF }{u^9|RcZBy*ϱ6<|]G56aE1Va km1FIa0@or=;Ark1hnz2B֯3g+O.@!Ss*ϋL DQ[~ oy۵:E@H|S݋{>֘1UxO\~?u|s0 (:Ga\lxL]*`ZZl#b|Nzh =5?vMB!Ւmea T@.lleLpH k``-fw7?iGgd,3EtSxͭa0kE(9 Y,0n4faX-VBkf[ˍPr//.Ưt74hW(?sy,f팪o?~ a}IYe3S|v(+8 &D=fO/jm,䅭PEa,˟2=K@XozOx LmQu:`me@&du/P=!d45CYQ'<?/v\ @I50 LF96 sZ|cdsƼk@p pjE#{߹s17X]WJCs6I5 pVsȌe &r&8-C`a[~a>ka$A,8(\YF^ IDAT,J20>ceb|,Tb<۔[c1ʀI0s ;]Edo!h ( X\vNҺ<a{4(F&נ3]X>XFTwI?MGƖaAL?05P`/ LݢfX:>:[qg$SCYq :Z q}U'+B!Z<dY6??...t}7 dxf*`v\VTWSm&l,WVdyRT@ɲdۛk !B,OX<@ZE}x <v2 z ~k'a2!6c/= o4#1@Sxos-)ٮ1+RfYyB!<<)^hcN-,[38YeTEрucL"e\c=,Vg s qjRZ-RJ=O!B }t\Lt:'O0`[Mc0XcXUl؛Z{T1-3OdÂqc*MY16b[gfxB!I@[̬L+ *n0Ϩ86{3I !B%6b 9``(9b=ŧX2;)gаӯn5o5 +ovufH^`0ZNOWH1 턧3,'=Ŵأɍ'I&LљBٶ/&5 n* Y 0XX;?$8,-ToE9ni̠P X4Yl{oBr0VNݪ;[d-e* !Lg\&qjcZS)@Biqn1j){|4N~R9F:s(VGՍX:hBu^WylrV81cm)>UӱO*ø)DUֻ􉦿fZ=Ux5&BLҬI 7߬iדUӿ?9:r,(|\ATa*u_ >_^-UԜφ}6ӀӮև 6ĩfw7vu&эe߻Qڇ7zҫߜBiiSjx>D',6Æ4 |/+K#XlnvlOC&Oذ*[ fìj)@1k&U֍˷;ֆ 6Xn-ޮՔ3X7쮍ϰvL/ 2jџBQHJ#-a`ن`),3|/S2:c/p@z/ l\D:gO+ݝKzyPOKOj20 P |)lk67VM[xπcdVfڻ(8Ciڤc@Uk]N!No 8iR4C{;ZA;+}r2^d;f7zF[ʸiZ QiVU_j;9a緳o ƟaNqɝ1ce2!e :Vc%4K`qpn&=yf .Pi <BcZ7lRJJi|~pd5df}oNިBe,P2T;I-K)$ W,0NQBD-h_Wi;:x̫{XIcY%ʪg-j!FcZ@`2%ê6R[j&c\ö!hrA 5 g'u6wEJd+@<4Mک_H3?rty}x" b3>P9f*JBz5%gE*ZI0f,S5HVgC7C!@jaYۺ(`lB9.6xS +Bxɰ3pmz;+3)/a!9!`e X{e7hܳ/KZQA =-jc Q|;Hrx:L7shm+<XG۾m5AЀa÷B '%ǞfUBȎ~o{?1[=I<J]e^C_޿S4u,..~_.BJ>~߈|cLY z=8yvı]v˲,r<{7]O^oeYp 뿾Zs]wug2333wcF.x[VGeu ^{4ݜCדRc5M5y Rn馗v0x+_}m^/cG6!lo߾|#w7^ZgϞZ6;;v|0L7mnm\~u8t<˲ԝw97771]vG>򑪪=pwwu^uU(\|'ֹꪫ{1vQןO܏yt C!O˕/"YZZڽ{7c <5A033zOϻeY<nfOt]RRJ<Ct% nze)r׮]Zt}&:e)ܿ\gq \s7nj1c5\$It:?>î'Q߷okZc<{]c5\ReYrxv}4M[Vܷo7+quMyK)Z!DuUU5 ׭W^yuWAg}6= !;%xByc:$gffw.p .jiiiffs7ƴh*Uܰ_W BL]q-pEgyTJ})7f|=t_F$." !F[aZk׃s}[__^oϞ=EQc\{PWQsYgo=zRʷ-+++]K/]^^BLgSB\|t]W)t.gYzZȺS!>;2 C7̮]܈:BUU)"7f) IDAT-o1hzBBu LlZ>_^^.oo~ _h??zo|Im7yw5׼oeyY1ƤRJRri~__}s7tS}K.g>d?~.ryyh1"GQ4`e >33W oxÃ> O~z[k]ݼ&c(EQeͪlNwޗrˁ=z;@B BN? /{>O_߿/.jza^uU_~{˓$v@)~6s=\{(2ƌc`0p4oNn-///--]uU裏/ˮEמjfffRnvR37A 77{{u+rz=tJzay{=.~~G~5wv+5{{{ ^Ƽ㏷,8{޽{o8w/ZrQ7mÐs~,,VVVdR2CJFtyO}Sfu{]W^ywWB¦ӃS}NJB'JyUUskv'Lkp38xynMߥn|IF>(wWId>iy*B BtdOȳC@!B%xB!B%xB!B(! B!8RN$Iz!gBȄߪKBh4 M kkki#=!B BMRJcJ(cfZey:\B(BȳU$Ibֺ:N|j4^OANJBȳ !d,˲,6fyizn*VTӱNj%B=Q$O! !;VYBznͲ,yX}Z] G4ٹ9Bx;9ZhUx@H$'2!k 7"(;Mִ[7քA9)@Q1H.5kmh,UӐ UJw(<ι4 *jg'Z>`eUҲ'&x><Os=) !%Yc"y[oMoę_R|YZ0)$*/v~qfU~ޅzU2h4Bz}{:O! !;!e$Z-IzGc`q:-syܘ,Q4'5;w-*w1V &ZB EQ 6 L Tޚ}T(aT*vr5 UT!! 'B rܞcќeJV1}҇u BO9!<K!og1hf՗ ;a[P|'Jӎ 3N{+ M[ 06 B(BN#5XEb` U-`̺ X+B rj-v ɸ`#P4B r:b!<:;#3T*&-jb:96`'? B \K+p\I23ǯL9YgR.,3U, a=]6bn-#s >i'Zfpl@ l6s|(5W̸Spf,ߚtL:rh00k&X,3iGR.,[۶m%+̬Ma[0Y5oXzD~nByϻ ywmP?edRm` I}|7ZY^Y,/+Y)LG#T!F%d{%XLRxV#)tOa ܏a2 de diF9lu$(Is e ܳM.==1SU&Ÿmqdy9J{ʄc!Zi$lxVb8kV(*V(V"UF1 E)y #<.}a)meb0ٶ0 x@MJh!{يO B%xBȿ"g{;dIf;Yրqi #i!`Cks0͑2c5i[DX[1ΙI6=/d}?,re/[eQ7פq?rve`5jZ2J~{a?z3յߗJ)n*gG6vH釢S5e+jIudFl6I&f;=̜i0upTzܘ)J57g3t]T 6#cƮ5TK]tyyinfWLx333f'7I4segi>Jr2C[,6r$!JpcM줫Ĺ{/[\3GjzT LyVF O0{ A dk&^8\UEf$/Kͼhs8BͦeQӮ\-Ri>*rvv.η7}g]0q."kN1lfY}_ Tp]gCβ^ltWև{^ q- 7J:2v,`e3mųz<^$\Ǿ3wc^ku jćai593~?WZ87:ˊUX=/b.-vgQ@J7.L2&9837UQzB%xBsއu[Kv~b̧hu}59h@JhZ $ n ؘA @p΍`(*fM a7+y5LVVr;\p:QYʦ\^|=*-<.eJY&uw~eJAy*Xd\ 588I^#n6<7Pu֋~[Z75 .^])_?\i-_ϯ5P ~wŋW8WUwaj8,uey,Jvi!Cҕ\]]m7E27xD\U !F2}X결,W!P' s'Zpp!h`yiQ0h*O4JH!Jn9L0Q(]A( |46YsmU75ad9C9?UUUd!76p<8s_Z?m-,n6zIVV /f'V$͸` <(lEJٍ"Ծ:08rڵr1 Z5evfg6c: c \=IUS a!0Pq 3OT"Sކfr&^9 YZ>Z>^x+_přcfvoa8k~b .E]t;ꓟ1ˮśez\W^-{^2/#o/~'?}Q;ny_3x#4~OO,]9#;oGs_̟Vn~K~H,{o͟ᢗX|/\MREQ : _+G{9ڋ_vչ147xc淖n/G~?ug[FP(VTOkB(BvFIrwk`!x&Z7n8a[mHa[.Q|D $cLOeQ@BD.n@ 2LOKm<?jo-]szLxGnwL| [q\1m;j!lBÛx#æ_xx,[|>+?zQ[w_5׮[y7|O8cu_+O]H$`®5|Z4?ɿ,ؿ !S{_7/yIqʎ{l;C?`:ò{ mdA1 ! P j 7-KADpfm`Fw~7ozz>X=Ugt* 6sIy͈LˏiW0ù-_4\p9雡6}K^1]?>+x7>n靕J) Ʒ^|ӛ/ΏMn~ |+ͼ]:pݶ;!Jb+lc IGua2]oHf5fͪsu֠Y>3EottڱL}W⦛.Z|vVUf5 ]|x^p$we^Wǃ>3sxg dnd B r`iBp@0d?3I C_^x JmA]d[<ݫ={=}Ʋks%PRӴ|xrϮٙ6Vꪖ QԘiԼ@߲e\ƅ(F2Hb ͎/䬗;n9$gp0Kǯں4L GLǭY<&$;pWE hP* ɱ.]OIDk2sakgk=Pرm1Oi5P,9vnߓ-zB^h3aK |;y _g:^ AcO9TUjF nڙ(na Ӥ?BO9c춯뻆1d$'{sͦu'<ȃ~`^|.8bcoӝ ꣏ә,8NCzG?;#/<ᘣRsN9~[gwcٙX.88(1&-J! !@|\\[n".ˁ@ + <z!?85 * %̮LȒ7lw ^3͓ IDATskyb4mpj+XRyϷ{[6Ч'}oW>l?=~|];p~yUH/Wy*zW9#65?/8|[vjo~0' q [sk]5R1U-[O9jұfZ4v9|% VV;ȣN6D3>84Skz}ڵ}*N~^Z~owzzo9G볊I˔o{ދkʗ̕/ִnkQ44]1ʮ?Mr@3ƔRJ)qk&&3W&`L hH|:tw?Dl%m!RhX/sI;#~5y")x!)uq]d;UXvDuGKV_Wݶuw_LN;dr2xmiÞBov`0tvچ}p锬[j]'^9qx[w#.{heߞA;أ6 n/]2육k?+O{tjGqz70<^j?/}w<Ϧ@q97mZ51YaLL'[e aK_RP(ڮhv>)N wLܹA,_2 eIΥ'nn6kKuu8jh Ŕ>ae.Bq1=[)~.B GLr>c! `@Ŵ|݉%cMY:†i.'f~K>k_{c?c:3RLXӌз ҭ$-갬L.M3䋙Ќzmzdl :2I| ' RI,WJQtwwB$ f'׮Y9:>"Q,PٕJyKQRS*1f1TJ&gU\1t6ۘL tGatH拥O 3j6`q͌XBzm䫺ɰ=l`r˖REGm P잞+FTxf0Bd Kk48g-Ѕy&v;(A[Q(aZ-δU)J:;Jq `%Kv'`L!a`5ˆlCqbqd̬^8J2G 3 #["t;qrOi1k5'*rXۭ FѕBG~v om`Ɍຑٻ=5z[?X.-әf\*=0ivF\ʴթ+J74'F\z Z3 QW\u|/0FN-%Hzzm[Zdel׌ WVT|Ɗe2&&d4׳*ծb.w\.\6LFA P Hia'8g\|w2uwzGB OΏs\50 ! ;&uW"ZOLPbVfb"+źbyJ3hfi\)".KlllPmy2mh4Lfs/ƚ{ҞmOwXJu\Cefw{w-_Omv`a2;nu2A0e7S#yqV.f>8355Ņb/lw'l0m\.7"oEImjRۅQ]>1Z\mh<#)%d8 ˥hmqY'S*fff4 ynQTT4lTY$}J#I0(H$BIQ% !U%ϣB,30ڮ0B֧'MۚL٬.#gQ4P XlٚNr)pTԀezZ>oH6^ .I"ٚtJP=:qPUyFZПXPn^Se][̨;`*)BJ.g([REmrV3tDĝטa[dqB'fymap0bZ$4tڝ8oV`0+M(息,Ia+0B 0 "M҂-ڎL0 l;\lLXb|yȒ|Ɇ0F>a9mCYنo7K3Z+W*̂bZ!_1v$R\>-4'fQXhLN,_b˖-evwWXz^yed3]Ip&Y3k5ZC+x⁁Ctf]M3Ni7 `[*rhH`i~I.Wsa_kt-!g*tu9fܱZ}rhpYެk(tjnOw.[0Ȟ5vӲ2bhNyn=_SIr<;N!Y3DSM/WcO̶J!xَFFGE$zkxj z{f޶ .g:p ۉaZn뮽RwXi 32nfXO|>l)F/BOȡ٢9!$#?zJldҫr;!X>x7h/iy M%۴ m(8bhّU:׷i>[oZ驆 ݪ1S$r LVvЊZB ;[ADr{fgk^ж6$@SPq ɕc5i5gϯ[Cl͝*HٳͤD%ߌ,]u3\)aQÁ^FO@B! !G` ]4rl0VSn:C.H aHxiS!MLЀLNF'Gumݏo;=^r΋mr&W@]wmpuǏ> /}ͦ 2W\O੭i׼oߴwםo-w3;W<|^ohM7]LOq {Jupx5(n-/dbr&k O!>5|UO=sd~5\xg>2;vpppG~tb0 箹ډY\|_??P۹z;Xw_뿾/\;v\>gk'͖O!wϗɧU^s:^pKμS?y[jGlX+=7_}7ttdĨd` Chh7#Ϡ\,3yѡ~D~8xqBO|ן%iyzI Qg  4(Kp:SLh94:QٺdW\g.cݝ~kwcR1LSVݳ@WfV}/{KGծrcuos ׏q+[#<-lV{2-ڵ_uh{5WҗNTA;M08`qe5g{MOzz^* q,aJq"Σ0|!?ڌC?k^O{/!4944%-bG$P`Jq)LI'>T>kǔ`Y,i=bp>ı`n5kSWvX6`<5Ɠ{]swk^ly]DT˕ fK;]q/-7>m.f ' :WȞs: YS ֜Ew9eX&W !P C[9z.bV_OX(C"R DW Czd$ymw}#бnغ9 S#f*u}otq]W'Ggp٪(F M]so3'r1 7 }D/e;yKNYjÙ?y][67yםCOnF^XqZz"9hƛ\)_ " BcL)DZiRJΩ6OFAJ$81tsԨkg6%8B)D߸0F=CXDYwĚ'hyٻǷl1ǔizmbhLΙ8vO=kt%{vQGQ*NPZ. M_~]/(&=eY=|͏T3JE^քn~b0P+W]o'2ʴ-w4{m6п^ێ,' jG]Yz>03R'Xsf8PL} -9hpґ1@)~.򧆞R䢌:Shn&x8g8ǐb.3m>Ml#ILCs[3j.IG~/%$,2&v9$T0fcFf!ض﹦i=OyL͌/[qƋz{O/V* Q+cŪ-;V6|SOZGceܟw $|¶5VGmx,( !vA. PǦ2,ai W .yqnO@kD,`!X$-P\$"3#ڝcw`-=V*IC컓c|fdx@`BeiPlw תz*]S;3cxí_p@Arj|q,%nkja4b<7 O0>YIi\ByS{l>tr^gԕU}vIdhq=!AP !ܲ1% -`1Їaf0=-!*FWWoҞ;ߘŮ@j›PR.s34u8N| PH$WK!$%@H2H#&ž"`\ǾҠ0xUŎ?q)5K@-,Z~M⨋II!xJ>VC뵳f&`H34p z{jA)hRem&\m-,XRR R @*@PW2?GI-j)| s`o\Vv&ܧy⾣ͱKu !P'PҀWkV۫4ɣhx0083Y(=0(#]uްxq}+Ffr"h4Pf E1B! !Z|~Jfz\'DZA[5[ `vM;h&]ђ& M:5wm;-hs$@ڠ !J3m8nV să\ fƶ0 d@X&M&|la)E uf84.**BOȡ%(a(Gq.p@6QϢnޚrYL!TmR4f?#o!B C;s_DVQd,[>RݘNT" ahfGq*2đƸvs&R{]Tue\y]ׄLϔ8dB! 9$|_ L3yUT/d]Y gWNܓ˄,C_ONNZSLg;gpP\ #nJ PjnB!KBHjj!b Wap X(@pfHb 0t\1M%TK;&Jb߶-K/5 !B C[ӹ`8dd}6292x h1琀B3$LI07,t]X +pN!P'9ssI}ھ"|rK D,) ibxB!틧Y !.%PǞu(@wdr0RFS` Lq&l_|_xRiLqZưShH?&%;r3\~sUc`jsO*&Q2<G3gZ8@q00#0SX8JHNʢE?!BO#?̏ [wWL'|晒9|B<.m !\. N4L^*@"-CPR b 1VpLsq|_ O4B rfa 5JhXmq)Vl(M\0fd8}T f[" `\BBC! !80fayEQk:L!/$l9 lyF>wW8+;DCF8FY !ƁwB%xB¡iLB8בOXdn1pqPd쬂y k0w+ !?!?2hB!JB!JB!JB!P'B!P'B!P'B!pEa*$7^,TA,Rjᖦ], {_W{I)3 nf(RJ)uꩧ2L4-ϿUzы^tm޴iӗ;vAѠ1!vm۶R*ydLӜxF>w޻/>$}qRdYVVU(iLO!?я{g׬YcYƍ/:WNK@P(r-'x ~_]vejϷmB0FRJ4wuq۶8.J>h~!D64׾v':s1Ǵkfpppʕ_hnݺgqivQG=csyi4Ͳ(<3 @ZmŊMOO_uU~zZ=?FQdf^_~>6lx^v=mr| '|l6Mai^?{{{7mtڵӟivg/41 R?=!,SJEQ׬YS(.&''LO!'xb˖-z׻8Lێ(9sӟtϞ=|;$Inݺ뮻޼ygq饗>;wn]}P(0ƒ$)r4W◿e$J%Ƙv{pp}>zzzzڵ'|r۶m'>q饗wݯ{0zץBL&c ˲<PT暩믿o뮻}{vۖ-[^]y啙L&s=4͇~zGӏ#c7 !%\iڮ]vi{ oo}[<Ȇ ȲjAii( Bڍ3000::^FVApyuww3rIgi[GB^̅JԽ8tOno7oޜFGGo~iqZzM7ݔzðjMOO lݺ5VAN:`zfPJ}Mv^~?8Ij38O[tn60Bުfgg{{{ZqR~87Zߟf<-oyߥeGB<#/lE07n۔R۷og Aڽ{듓֭?4J: ʕ+lT/~q'ziƍرC)TJH\ > !~lٽ{w.qM\׵m{||r9VO,kxxxŊ祥t˲Ҵz +fqnBaAeY|<,✧oۙLP((8bqddBUYhCOlֶ^J900`fG V^׾/n6Bj]pۯ|w8333p]Nh6ib裏.I4l6jR###LzXZfi==Hs. p/{rvߟd2[EёG~P(6B, !iӦ+Wu]sL9lV)uGj4+V\.8NR,k˖-Ad2 $I$i(8|zym? _0 ٰa}79-Nسgϲe˒$)馎 Jj}}}^訔2 i C p||#_|yv500`jj{'{'x"-OMM"Bf~4niwRe]scT*x衇l$v;˹kfzߦǭ.< s/_T*ݻ۸q#͛7J8ӍY܆B O!$I}cfff(zGַ>uY]tQ:{K.$]8f0<#N9唋/}0fggyzLgǺg24v:V{/Gꪫ,jZ+VxMz_(-[Emۚu:FqZVTwNGӴ8?߱cmݶlٲtt 4M\jqO}*>W*t]RQ?.zӛ !<׿Vփ H̕lۖRFQٻh[ϺN<3wMrdDh%R8kKe[8tI*V.))U؅R b!Ҡ(`0!$$qxܓ^@n:>=;|o#l6'湹NW"{禛nl=QcO#DDѿ]ETȇ1<8=mڀx8O?[EE'nwvvr{}m4UUn>}}_[.=c~q<`EsW?̇1'{_q} L?(]k8]t|!c)ALHj4!V|.҇~<ϫx<7(e$I|ߠl_*u8j$I~}}ݗ}˴HTeǃ MS>=iN&ӻo}p8;;wVy>}a4( _ ' C1ccyMՓɤ*}i0O>{"I|Y1fZ&"“$VkuT>[5t(t¾ OcnwEh4|'t0vcyy3YAiW vVck4Xz^^G|<P%afs4Ɔ?Bv폃']4#a+ܻ꾸OGm?ﳩҷ`'0 y>OgWZ}} l"PRJ_HʲVLvzK|;PUU+?Eg}~-4t'}~IZKDDznSOR>~5 h'x4$}gN?O.(mZWͧ4 | sO/dY&9|G4{ -hmmmee-g&4}/>o| Z-\>z`0S&ˀ/'qCQyy/n4% <c_ >J8?!&N,il":hۏ;˲,`Z1p1fvvVk'Lw5sbzxӬ?nH)5GTʲL|e~?EQ|Վ?>7L&Zk8\b93N1v %xO1>OE°ʝ`:;eZQvLM?L{ZwFmL Ƙ,$gYoOK)UhEѴ/2n9wx}wcz?1H?_]%wqA <cJgqg)x!`1c1cqg1cqg1c<c183c183c1 cyZ,x/y.ZH*/_0ad1 1ƾDRafYVRjvvVWWa"Z\\$"!M0 04Xk#cgYJ@  9Fc_TcyUUukB)/ ,Qq< Z`0pt:Z0 <&c/3._>Y $Izy'Ijup9;gR183ؗV$v4eY6L00L| ---/?Lsac1N1ŵ04Z !ͦs^k6uEι O?Zy^wcqg/4Mf4V眵v2Xk(B)EDAH)qGQ3t$c1 1ƾ|2Fqo }{^A(cqg/$Iֺj={R,{Ec1N1(9o}<Zx2kٴr;c1N1ooo.(_yF镌1'x{jƘy!ֺV884M>a183Sϟ : (<ҫ2 IDATGZaH2c_zDD9zB1v *KD] k*JX8!hZ3cc$I 5A{q<ǡWrTD&DVԊka汌vM;l c] @ Yc{设x+ e-H*@HwA #uF*GFg֕ DA($dei(Hñj9׻AU2z}ϭg$nΎG=&ןZ/,t33?xOF.Io+r~ç/)zГ M%YcN*CI^dH,iaΞ><µJqZXgghg#Y~25hc}~ awۘ.'jٻ`hi,!&at& h ʐt$e@-J2f 7EGuW`}(fZ3MKeoa)O-Yӟ{(=}W7ß sk3Zv#筓R8ΜZX<i ZDjs$gBRj"(X&!byjQzv]k'qH&hєM*[zNsUUքm[TvFp 1v@J{qq%l- A( r‘ h,V$$+Xm*H$Nqsfج ]٭ BTqԛɰFIDRfZkΗoeY;Cn摝ѵWf3jʰ9WR'RU%lmg+++07UoMt!J^Vjčf [_.I*։#YV$֢Е B183Ʈm:,`uin?s 2Y NXWj`ǐ&qM.E9RbՍ|˾9G.-"C(ZI5wgA]Ꮪϧ:xkxC.*2%[o綇<{;,&k_:vL=x 3 UR#z7,w~_} >:;Bӛo?n'tAʵw'q~g1N1N>M껆s@  Dː~9^-)-Y"p学PC g$D@"6hS g?~=?ϴyw7ݲZ@QU?`y /n{ ' ZVVm^qw_xɳn[y[~uB=g VrrOݿ8o\]9rUo_~wG#ǒ?|W߉0kw||}o|o:/~3kۋȇ?~^'|^™g ++0[m-2'xصtژ8C(,!&% دGFUP#"'^cY)Y&q; ?<\م۟w}RNs?y߻u|mxՖ (εx0 bPwvvsx7^w 7 k^OϷvkkyJknI&d8zW2bg4kӟ/O[|nn}wӽxÿ΢g-}#|ɓIJ4wy೧>GUDhm0߆ҩiLݳQkn?oG?gxoߟ÷=7jLFM@F[Aӏ>4 U,|b8={r7Ͽџɻ/3gh4h2"\D:@^ozz=WZŒ9}s|͕)&FLS'Cɓ7ݸl><+cqgX^ b t{b=> Q `?2dnBUA(K2lk8Ivw|K^Ui:TJ>$Or\>w~nhףͺQTR4RSGH&^_eY`Ժ;Μىzu=*Zm,5zQU[v\/{/B0O~-:z׿,jruusW/>)y73F{" lm3c،wمH%E> -2:#nwjc183ƮqvT*A ($(ø P J@=1 NLP {q=ŢҝJDg0Mq}TITXV`\v {xQM@:Z8Rs'_ 2>[NC!m[\X8g_x),{U? Qݹ"uE7qb;!wxç[٤F#8qPYhQڍxgљkť&PIl[zzT'l(mHI𙬌1 1v-# gqxB[4 mfb 'a\5 rfx 8+n-VET@3iPc]Vai]G]2jZ^ ,@z+xrӵF{qvI;#&i8\T<VVp4>x~mk2XO>G??33M'_[;.J6ihFOf F{Ni P Z:t;H?'?q Npsj83Xh4ZT #(Hǣvh,EqRR5ֺJPE$,B[cvot! UF"DĔEu{dCNcI [PU9k%HRt8dZG@P Hg`E,^o0Uf[p<. Х:Nj8V,uBت'HB8X;} dVgFNlY%g:xkKei;y8*HGYtj]*=3jePZ= ,'QԒdB3uܬp 183UÉYTXїȬYiDA{nf#F+]ں 7v6YfG|PvjX#-̬ V֙Vx0 HP(6zxuu:ˆzRVyULPXk,H eId()H9Ii2%aQ{_g? gұDd(HRA8fȪ4֩Wee1N1}]I N4&dlMTE4 O }2@Ð UAZflbK-UogQrHkQfpր $5;EcG9Hʼn2,Bkk,/[[[\XYklm[z=YZ?\PJ$8Xҏ{d kX$o9 >f̅Z%Lϸ}cqg]7@Z 8"( 8eV9Pﲹ`ApѕFxh~R ұjD(h%vwc(rdդl E>l z33UըAE;ݝ(hլ//.fREijōdckImf9gέ/agv]%Bcqg]]|MGR# `,UaGRUqH+*+“&)Ic@]bL44ZueuKgZfe7rⓟ~`av!I\)Nzr|xGGy9Ѐ Vk l3]XXHd0%.-/{;#yi!cc[;@}Ma X;Tq+4ctčSf8Gn H ~0ՒFVt4TÁgV ?ӛ}͡~Z,Z)@?߳oVޜ9]h{VچPoeYicO 3Ʈi wX@]Xs|',Uvt4ABP/bԃ.ct"r][8{DN{dp]sqhb0O>| ?o8~C\w~wg߫%M~t0.ؓzpup@o@#`xmJl:ؖdn[OƓC$ 4ZpK@늚qivv8?m;goIBo}R[g[Ǐs8zC/'nOuoo=zqjG}Tk!?c=% _;NHJep(! "KdaVP@~mmp$r [(\%Z͔[E,&eC%I(;cePZZۂgLU?$ΞÛFqѷ|_/˲ Zloom"yn4MgIccWY+9mW Dp ww F5i%{ŭ!i(),Q@D(˼,IiSV%24m4Py:nHVt_ ;ۭǏwyaADr8hk6gy jOaUFJq1'xU}^8[@xop <`A( Ep^q JX!M$*LGɲHBF;Im]X4g77ѨK3vR)[aXfӮ$ӓv=JnCkg=~x=ul;nc=1v ەq IDATH.̇ e/ېlhH&'ȑ@餀NI: kᖂ 0ol>ᝳ/z;џ&~׽Ks'. l5>(ufڝxjv1c)5xݕS^NPF*M!Т. X`m+0ꖛ07 ld+:qfaH{_>"NQ$ w폼Qg>#:bgPF Stg;a6>ʯ=7[q(~ e1 "r9hRZ!6صZ?&鉮bwJKLt$`4!?޺[;BbbdL.lԒɨ'ʑ$,54ӡSǭrrkqMS;Vm<٩%FBV#(!ougnq$$cǎmuߗ0VVTդR9K_}W%h2Ʈ9BK%"9)>\jJ20n7%uBJ BjYhpWl("ai49)JQhO˽Sny @Xho|"(  8qmma-U<=f jD1*lX[^iQ~ @טI3ITa +Iw cccAL+ M6[.:o*{.mfUYDD Dg4dm|fmФs^ZKW r H9"Fxcc\ܛuJƐ, oNǻ3I\.PJ9h61!;ըKYkx#Kc1 1vxd\@ FG 2Ue |otZa e'PL -̵ '/ XrEcqg] ~_%>M>CtLq#TK8HDIuuNkv{`d,Gه7s._~;c1Nkq.Bp@ḨGd :*ݿD-HzǍZ5Ěp+nKJEe94k.t7GA-ٝsQ1'xصk-V hDZ3dZ ] ! E$oMZ F(C:P$tG!$lnOYOZ41ؗ3&{Ĵ/@ZXyZy`2N\ DElQ( HG@[z"e'͵X*vMNw91ؗ+3ƞ8_w`PX A2]( `4Bf-@8Rs!kNQO8v{KM~5ycl7 ""RQ@(|ZZAY bP, Kɬr\3O&!(3p_yL<˙y>~AcHz'J0'{Jh@I@{q` !VLQv 0>̟yB! !d')-JTJUs! ^s8|j#p*&u 4׀c} bLWB! !d'Y16hk7n*L\gq̼)\OAx=oarSB%xBkr,˂;ZwBkA0+a90Ѐ$8XǿS !P'g6 !dJ38!B! !B! !B! !BO!BO!BO!B%xB!B%xB!B%xB!B(B!B(B!B(B!B B!B B!B B!JB!JB!JB!P'B!P'B!P'B!Y|j?I,wk߯RjϢ}#kLZc πxRR*8dO!;<c1&IbY" Cq86M1h4LtwnZRDQJ1peij !D$s)e$xOj~ J%8-jċ,<B@AnָgyB1V׫jEm+0Y1qezzz6{mP(?><c]leYs?(CGh8?mgE&/0ByeY !,hhYj !+[lBtww{׎q;!.!DSQ6M0 )%~y휁i5N4q˲8N3A |x/x9~ 8ގIx{p42P(Z)yaYi*RzGGGc|j5M>22$IDžB{ [qc2, w*[%JLrh BOGǘq=52;-qާlv&3pR{^/xFCJ7spZ3'"NnoѨT*qK)1s'Ib&Hx,<}/xkw$H)oP(o EQxGCx󡡡. GR_e o1?&?hYӯ LB^00l6a$I0 `a ZMn^}F\4Mqh $===X㺮i(pԼT*jV%Ķ08F)6M4M$)x#׷y ؋ 8*0^ٯR:n}`` ƍB`$jYV\жml\7ok9z|yvaR) 4MGGG<ϟ{s=uE]|8 Gy5\rʥK>7o .]hѢ .jZV,1 !k}{o}[/)eZ{<0}t{hѢo|zigqƆ /.\K_^ZXSq!O=yx]0wݮHIRۿ>8*1/_K.9̙|(0Xj뺇r?l6ZZVT믿{iZ㌎ڶ]<ϻKkZ__'LSZ ! !Cc=>*>p8<:1m۶z>jtMwqǺu<~~_E,,Qy;]sI'=裎`[I,ZJ%֝3Ʈo~Iض}{Ou]gׯ_ovk}?c]šn Zrj"0M; oWrwcʯj?Oo'|SO?Q裏^xqѸ馛zBؼy>822瞫<;\fͣ>z!J%ιy]eYq1xy~׭[3l޼}o{-BN&VlE!;i`|9-[h7o [n?OplxdddժUW^y%i&q֭[5٣㌌࿶euQWn444y3֬YG}}b1c5\޸q-ܲ`ٳg{Zޯi6 þ;[8 ^{%Vbq|;Zm۶JfSkzo/ _=~~z|T>( QbA̞=W8_{h>R+(3g}?MnLcRʁ͛7/Zhٞq<r\T>u$Lrt"WhddCJ9snCF j,FQ|٫ؗZb>uc c fÄ톌X?Ro}ʕRۋZɏT*  !m6m4(xw]l6׮]dɒ0dEr\.O6Z%Kg_CIꫯO˦bv?< r֭STm)N;ϿkZǍFGk]kFGGvgⲵ/X`Μ9q{,Z6 B<3J% C4M6::bC%-BD!PGGFիWvmWT*7n?~~˖-?8::^xyavTX=wc=sq]Wk]o4Mqvn0p {˖-~k& VXq뭷@R馛yejS穧>ӦMÊT?ڵk(7׷~Eǩ8m۶m}_J5gƞ9ַ,Xy?qA%)yz/BP 뺵ZmttO=9묳6mdY0֭[WV NP꽽(OXT*|{~xxjF$ B(B"Is=oGN>ꨣ0[/^kG?twwoڴ ڠA{*eYfhgg'pro~r|muvvuQe-oyJ$ qK4ɌM\nth!OiI0ưb;9v 1|EPh`-MAJO&-YޮYbnx=^" {$I`o{,>r۶zzzI###bfY.dk{~wzAi6R {OiH!l?QB?q 'c[L1q ysΙ]ӧF -6NeB^;t:&P8V'tgq˖$7]H^N(P|؉/94M!DoooJ(4u]P(qy^Z-2Ƙ8Zk{4cZ<4MTaaB,d1 2s?)؅8- `C;Ps`sYTMXrȕe6%%xBZaB!˲;džέ<嵶q%SNWef{`IR' sP @1|Ta1! c3Z8ka ¨*ix:;ΘA˕L@K ]]]CͲ["_C<$֮Sczgq۶ϗB>2$IOOO LimX&< S%-/+aCJ#IxҹmpT)A]Y]azgOWpS1_ZPƾjZ{mf 厮W}/gaToi0hV&icȈi o׺55}iQKJϙO{`-)VS Z.\YJe'7{NM"W:ʓ4RSraZgm $A `*muJG1&WOl{bm=]iZk|{vN~u]܎:2qlYE (I)%!O% Cq#MS0 NXf6QfRAP<*i 3tn( ALNME>vCZh]>틍‹bwd`pU)$l2eLP' D(1VnLSjIAתhyʤs߂HS P.@M[Y}i3+yDQ E,UE^1Z-wڶ5btz&JF +Z*:aO i߽-/߼ô JUf\Lȁ? >ozac{7|O@ >K.uGo~~뷿r|;뎻y¿;oM\;~ p3;S{\|}^Y?^w .>7?km]]p֭/D@ xad^}ܹs̰%sn^Ѓcx{Oe˦oW^Yb͝MlJ% [_a+a}7o>ck]rz0w>kR 'jպ=1Ci9}B:,Lę x׾[EQX4 Ckl6+Je1y+ T*x8n_'܈'6ӸĘeY "~$IErNS,ăAjbXqd90#RBs͔bj?_(2;gkX4lֻztڵk|ʒ^}Ŷw˅ok.:MC_qg4●S2f0pGo%Y)@ϬaG/y'O8a/:QbԦ>tKO|k͘}I'D=6>у.5W^->a_idsÇܿ߯񋏘=w9^k,\{A<`Zʏ9߬}{Ï|V}옷-]~b˵A&Y!eE`6.@eK4*R*fPdLcd18ҏ&Ry>)y\w(Rn|NGhdYiRc3M&^aL2ڞ'~qW|& IDAT#bN?87|i`_C6oZ*Qm'xyVup_}zY|{~vmO8{nh}تc8/7=7a{w_=g'I}R5r}$-貃I`HZů`nQlى}ÛY׫ժFFF:::}o?ݻ.|hhX,.^CͲ ڏybE9ɤ}A\wR%mgEg !*mZfHiwVoWȼ3r !@b2=h!0%0MY8O\Bg"Ds3o0j4=),gJg apf̀TjqGHwoh>ZZ~~FӁA3Lݳ.w{_;j;s[G͂ ]|]CCW(' 7nX,ZAM#S°zvɚ1k߭7aņ-[Zgx05~r?Onay Kw(4[MV(\0 .P.ํ[L#VT3 /zz͖oZ{I xgE+ /z~ ֓\$ 8c?V%p] q=X{ ft -cMLr wtt8Smqs|X"߾PJQ|'q56Ok=1TEʾ񁁁JbYTmwttL47}]0>{"9cLkXB&=(6V>22t6uW:Ŷ}ؖi4fqLj(U{?U 5͔bvsPc-w<ӮYkyq:5a('ys[ P(zaHӦMS*3Lɹ<@@g$~P.g;~CjA `r/]W98׾rC ]kSha 8p9sqQie^o?a}c>ksG]q Xrum^sLS>LհbGOs=9B_ EU.W;9F6nY,~>uBG7ᨷ™yHGuwWkUn;’ndv c22mXP5BWp+^uu 5p _ޚ>wy### ,8]:ov{}ї^ziV+9cl6JZj /TK.?g] eqznZGqg>38cnGq|gq0> .{?wqZcyO~rʏhp[v{v>keuLpf 6gLÎTLh23h٩nP^4 [GLJwhj$8Ps"d<0 W^}EٶeY\ꪫ8ZtksĹVZLINp>njaFqR,Iî;T97˒$ S@ )y%Zk!*B5|狵2_yk'䍉fzzA(!rC(l2qUVL1 xxYx 8dbcSs\I0e0-L -["wD@ .Xn2Y+ Qߪ3XҨ(צwLs87tlЩ HKO4 ^557s4MIΤΥ%Z|3ԉPBKBKT\XB$x`йԩd# :6U,Y]C_x[K Z7Υ3c< PLhnB(0:7t. 742S(n :u/S{i#<s9碋.+ }[֜9sׯ :;;g͚zQT՚;w>w˖->M>OlZ8ghfBeˮC= /m{۶m,',ryhhh7| Š+bx뭷h… /SN9eʕVz衇0ׇZK)q(96\5֯0y}f.;#,Yr'?###R?sޛIRY7ȭ*ki@dEPDCTTaQEqqCdDYQYeꪮ=rX}?nV7?i~y|Ɋʈ̾q{{?"Rضm9眳zO?}ddDJr /c]rSO=jL{eYfEQP}?8VI2z%K'lXq?[0e9Q(r5vD$oXEl[Q0]qBjz-"MIfbfxy>\t_7v!R"mo,c!CI/=, %B[ (T,J%4% l]iTZHI2ɪFd4D.]`Lof1ͬI*i(DОh)ؓ:"0.1m³u[ [Ic5fl a{+dA Z88YJZm!XHfCķ!9Ԕ$G*RHTB"bVҬXjKYRY $XKiJrHI]b$yRtQGr_T(>>3=د~;tnkof͚SO=utt'YjՉ'hgĎn;8׭[$I___0nTJJi,???}gff&&&}ؼyz뭗^z>xMo230 ޔ;==544dvmo9뮻я~dN@qwr-=qwGt҉_W\qd$I&''MYsΙ]nݖ-[,:34 2dTj6Zka呑(e`.)s=W0K,Ix\G=Ly7n摑6m/z衹\. Ã>c$Dk}盷ᇟ{̼yf~Ţagu9pXZ_o߲eKOO]tEK.Vy{#dX4/n055}kT*BaڵI阏_vO?mYVE7xc:x^A1BZmybmZÂ6ФsSpYA~`bPAДRAfm#$3g(}l!$ORl2-˚=ٸqcX4ofNaVU!DoooR/ -^XJi;ѷ-Zl6[T|75{Rc7tm]]]D$1?WL&322y1s=1gX(8^`LP>lQz衧zjwww&:ꨣkk׮Kr?oV$&''M+i٬b]]]bќcNi]v1ͼ=sއGaÆ(VXat8======F_VRb .xoz mjL<44GADjuB066;woss(L5leÿ7m ϛf8۶xZfYFxg.]:xj,3DTa;~fAk i kaurCK! USVEȄbqc-Xw1/VڏnahjdҚ]f)ֲɤ4$sF4+D̢Y-+b1[lͲhjhYgޭ*H%C%늠RV)+*(gJV=쒲JhE"GP2QVESW*JŸL_><#}{>Ć .첓O>9R5k|CqzѾZFax93~>'3~_R.Z`֭+WZQ^m6qAi&Rj˖-_c=N?я.]# 4zn404l6NT*566zj믿~ٲeDqƮ(&&&FOO)59TUOdȴeYfB)^{<#ILLL\{J+V,X\Fa8FE^V(2_gff$YhqwW_:Q۞ @d29߮])fs]Y?ӟSVsB>_ IlݷV*L=/.]uA-;" 鐂2l6qw 1r3 AlBb ZBt莹;B6!W9)-bаX6o+뽿Z)xGi^oXSࢱ`ɰ=~BnOODgy߿l23 K֮]}W6l`۶ilێh]vjRʮwݧzj__߃>x 7msg4SVJ6(,YrtA׿vҥFyԼ7|=Yf}9Ec./c=֬Y߿?R-[+?`f83fo)/38+,Y#$A6!7!7yOUUUH!!a'J1LUSHK{t(&?LLn,ܘXZp-myfgJ\O=9x|9Sgv?;螄 D@8PU:o$퇹P_u~]Ex|NSt&'{{])Mj)NҎtVU-3lP$ؖakmҐlLWRYOT~TO)NN/Y=9U\ӹ73]/8唯>@Y=dHaM#UzzW՛QЕ:Ru׿=Hxl ZOk%7j<߲pd|h`FA)e-zj⪨ETCD,#5rմZťrEZWiVg{ I[6P`hJXmI5N6=9K@CmUK?DhZӟ'85n؄P&:)86MFewƬZfcĒ$WEb$u0/:83i5H`H3z*R_@+ƪTa8J%ʓJ*h3[ z#gWq^Fvi*.|쉇ڟ5^UzV숳>^-E}S/w#罝-#H^HMn߿G$˗m||{z'?M7|-|KE~\qR< '~!,cc.:l?qAoW[Vkjq+4+%3eI)%IԦ[׵ۃ=^Poͨ/H7Zoeo|cU߼egGUp֑_>x~{[dfg&p=?aY1~^^}yw⬳׼0+삏_zpo߀իpo'?[Z!|Lӏ$l:>x߿#u{S{1ǭoݳ#c>dɂT6͊`üA`&m=ܶ"뻭K_!uEBa1=N\sMֶu]I%cVI2l?11 ~5lAdfGiⅯcT3öm&!vubkH"%S~+jj7W%45H$1XF'h޺\\UWPzz }~O&|3_=WLU7t-|iR}ߝyg>㫮:FՇٿo?V*'/(չL__=c|bA}߰#>)-cgl' E'|=^qY|Ŝ/9Glzqsi-4X󮍟K{#_C-]=6 'b u[]uw被?QUo?__t ?E qa {E3\C|g>mo~C'i&][H; :RJaj<"fztbn?1||2f`zZ,vޒF*A.@SOf]h4q*NL|롁޶eh?݃ӦY©B9oYۛ?UI(pQTiTOڽ\v3=Vc3SyеxQyx࢞F\[6m5ן]o./_ӯ^vPyr K:e [O߹Ǟ֗C?+w~|}Tfݧ\Cpş^wOy~|q뮹]jWhv;T!0fKN|o0z_+9|: :}0 YmԚiun%K,SB&3,6dK'-8UEdgj$q5gtq)-mnÙg9+(MOdH9n\a h泾lML&P3q\|;aM/_Ó?{%VwQ8vtG۴r<'q[C(:=l+vJ-\P,[5k8='94߻u ͖¿pXWzǻwG?ܞl#e+7m|c{oڴq\ت [$Xt_s3q[ա'xur. ?2agnZ)FWHRQ ǘA]V(>97|FtكHx1vu*zRVZo5D#łw5DC[L:ӕmFjj\u5UkX(qw~tP.en:Ͽ.G̔3uO󮰛fes8ӓS*tЕtR)lؒ 7]-߿š?+ZVhVڃ ˖8W bѪR8-@<ʥQe:t;z`oU-/fsI^7<4j?սe[Gleӆ}+gatAI$IR.3Ks\O׫[s餐sZjSd؀X B[ʵ%zr9{ji$ܴ͆4Z<>>V5rl ޺X5P\:99]A -߼ax?Yo7-O/s%lKa^Y^|Ow+|`S?hTp)zv}$hEkpS[skf3}D1wMz ǟ|v]}nb_B YN\yq;%=]B\7u.1RaDZye]ut_~U8hojy<.V*~;7pmNaJ[&+eIp5*3o `ij'InVbQ:k jZDm[ w1۲^}˗c{ߝݔNg[O87O=gWz{3,n|wwqiը82{x`S?5;9rLڙb]/UGXrIR3$/vgtALO!n[z^ݰū| v?KC՛)ZYk=uQ˗&yr~mb v8ر\ 7ɸkl8u~ ;~xN7I"մ}*ͯ_O`=q \+íVwAVltwwHHJ`)T Y/M-l*%-EfXiJ2%٬'f&ْd>.4%ԛUխ[|? ls Y'$N{ߢ7o;n%d9NLJxArA80jl6kֱ^M۷Mf5- vT\D9+Y&0$` &g|=L2Z۶źeUoV =FլxY?5R˖ᮻtS(vJ%9R{+†xLe&ߕכd9,{k0:4qIP[lI`ⅎt~Wr.s:C}Ϟ۴i333^oe8%B73A<3Vشij{hpŷoe+uRnQ-B֝a"dRiʳra;(K#,2, sm^>󴓮ƫ.O9xAXp-uYS7k M}Sjuqȡ珼첵SF]]=;]x/K- ]1Ww|5;]w% )o8찥W|иc~LgmzI}׺yN%-K›{L*vovv'uB(NK9m/sSv JU'ǘ+w$;蠃6,BLBFQ.zhRT3TJ)8" ڲu*妫f=Cp↤ز(caYdKBMǾu7BGV;tZE^C*o-FGGO",[/䨝fͲ c#җoH`םw9uӭ'Δ&swp$E: k%_ RF)k{ࡈߝ7R?˓Nź-Gy׍~/]伏\=p;x|l{sOsX}騾#ϵ3μU[PuZ$?^@7 eqâ^[ex<3w|$r43ym$5Ms>6M|/e1GNJu&UtL }L B}ϭUT3bX;\oxWj"X10j1K,Nl[T+I("6TVʔtˍzpъd+ꍪlyЕ cLjF63=U4(T]]=VKsN{Z< úNʞ)ٮzX8R,p4==hq_T旅Vd۶c$l6ƃ 4A:;Qz]'h]jᢁ~`pqdAщÌ*m?y:IrDDeYiǗk[uG:\N#2t9j8t~dwAZ'IblZk˲*X Zq_>&34?*όӞnyX$4iH9Di:缴_)*B4VlMF a~|}4;턠4 ]茆dhXDP`׼ RpBT H[ A $ EHHBe@V@&bv`MY&h*še@sU5 (a(h~AnNfU Ѱ##Oev>5Kk2jY$qLRD⾛OJch;'BkFbPۃ&"abM HKbN\XUz;zpiMd,miXh&M\g3tzbb±\IjUXqR)ND-zٮB6lVZa$@M`-* ȹcrv$EIaO >5q(``QEHL -ia5"!|t (q$!"",(d9߿m`_dU]- !HĉyJ*I:AبM H$,($R9-C(ԭA  f -beҠY60.cClhҮ k脅H43f@\4QCpȤ$CH61sYKh#T?-aOlWPE;ž{L|- ]ޖS?͏?sb855eMٔZ,b!ډon53k$E!- le/j$ X  [ Dx>IZ\*%5,lʥ3QD0b͎oVQOJ:miJ{r)v?Iͪ눰5%֭ZBms8nEyqR]hd (abDCywq\ժUıVM& &/$X@ J(iX` %D BH3G{|، @X)bLhS_Ab~:KmÓ5SF,։ZXk JpT 9M IDAT |;NvFS,- KST{8!X|fC!XHR`@ t $L 4(dA 5(ЂfL@v XCO{@ 2&0BIc[)|{fAQ6D72u0 su fjfVf+FB3998t^S IV\p{I`&Wx69J4)Ps5"baC @ohiY8h?V\IB{TAh.Z4exYDc=AfjrMu+ϔ[Ҿ_vf˕ *$J(J9]zh\ϮjA*tgq9Jў`%q:7cK;U:2 S 9cKKLwجmZ[ԦNJB;POZt]A jjTm3sm C[BmKFJBBP]`b;蠃W){3K)M amŒS|4 ɩQM\7ٌ#%,K%X2YB dR&F8.!idCn/}$$@Z2R `Z 15+MER 51Q̭L,f@B NUЊ;*\ݼys&\|Q#WISCXk;fqip$I2Lٌx=Z-hZe"db"n''h@ bh/@w4M NXʳͫV 볕r;Sƍ+W:1Vloٌ#jյa8J˜/dGIYRŅe%jXIJ;*0֬,RmWCO^VRyWJ ]8ÖhC͋έi1I{YB@6X֜@H atvA)2TtMmٲyѢb&J P2]%RJÄS\"˖flД!J hh ÖAte H<]>KD:R6 XUNH r@M$ e8Qdm_Iɰ`f/\F ]a 㟮M.m$46vض]ՌWY{4Ǝ9(Z-r7MGSSSbѬ|ZuM@|$ay% Gqᇞz?rB38wpN RK5{=2>Y28 [X~A}k:[~=2] buȶ@~ӗh ۨGW_KҾF`B #d˶LzQ枴23L 4J Am/39!#b!ZvuE:ݳ`XG'%[HBmGsrL9W!%b!\p872H heMs^V3֤E{4J0K%#ؚ_"Q&iBCshiH /%ڶOx^lCf8/o;:Bۻ I>~̬gfO-ˮ$YF1"pV8dB!a?q`#0p`F8؆XĮvgg賮<~_Vu3x=>Q[[]=]Sٓ7b=ފ@ǦnWU96|~ne(a9fEEE&YK , bX^X(6%2&ډy%ZbƤq&5д%o;G??>~w{}}'xpΥvJ7;TU5Mv.^Tu?c?Ӈorh7?[e@iƇoOՏ(ꂳt Kʊi/249!M+P[ߑPeFag%^,m58>l8]S ZtVXL@XW$7Dn4d1w]/-mX@4N_klPOn:h˽KP5t@@Vp.Ŵ xլ~"EH,xY3cj-Y*$)  \[+@F1_ ]Tijpl!u01)> ,T/]&˿+_%Vʁ@m-g5gxȩ/'-;;>_y|9gT5/,g_5nѤtPE!%DmoԌ@ A\ʺ[p8s99MMQ'W?>~fGx-?&fNd7j{Xg+GIgsw}õ'gģ%ݾNǗygsE?'^ꪚȏ=>ǫwfox.]S:۾Տ>g;7?s=__OxZprxXy ETx rxg‰q)b=Kq,7.$j.xƬ9\% '+'mg٢zsN$m,dý{wL+xFÁHLJLqb&ssqyBӰ(Knq|svʉ`Ԙ93{{{^/eךx`4;wnoo j\+O$8OL.^O?fOif&0OT;+>ͨ)vѭS?fU=/2t)~K[~>[?7˚+&7vT]uyg?iyx${{\}{#kx{?/__u=o~8%6"xnc5Ig7}o1v5<:Mp@g)+3< &Z/F}[ ~mElacdo_/f;;sMk (AIO2ƘE~_D ߱gKp8|c [9 $" Uݫ͎XTEDR,i1hIҕtJR*"Ias\v\Tj;sutʲd8R;;;/+,e;/ُ -*e5fJ gd@2il[ ŠJ]*]O=_mIUU^>~OO_p!^֦4^ٞGGGW98z߅f2rEsW r2,n*IQYts ~J"(NiKz_%qRNN檦 `>W77us'kg$Ii^$|cE~Y {z\A3/:cq5I!&]XJ]H)(%2FHԢW^9_)~5uh|t:DMB̨v6}~C7xu]ý4˷ϟk<{C=( _#)]*n6>f>Gѵ+O31lms][d1wʓ0ҕ4|5:cH z^0f7Mm_<-v/V)N8$'Ь: zye̤L VKcf1^׵$I"+eM~4_H[0PH#&@B#Ko23/X"Q!(GsMZS41w]Ged^-/_4Ɉ'cto&j6I1:ko{>p=K~kKևkG~ÏM7/Dl~|;uOO} zOߝ%B:v܃tUfrAI /]ڹY}Szhl()qT3o\/\S{ow|g~g=Rs|xpP2Sjr<+i[?U<xǹa`秣k%$48ܻCk^~ׯ=ikƝDҲ~Gs4|F;SP8^ei_K\}jf~<:`Oy*a:om_P7`{nol f1NN OS"][[s.gQ#4gt4MYAtz}[EcYpLRKqi7z|lʍOhrpmCNXʦTü*f[ b:\Gy UUn ;!Z׺),! s@ TÁiQõ W%:+IyO^D&ZW ''#2DswynUA P֠]蕫H Ly^} ~eHY,Lv(ǒ%{y?fU/1klFl1wX`12k%CAfb+A a$WĵLU4I}b}&q(5tQM L"41IɉIA`VaA8eOƁ̨ :д ȾEtuJޘ&s2^Bpt:s(Fxg/ffC|SWt^?H*҄KPX47ZAWTča1'hPJ}k1E)2g=BWztpM9̕մIg0 5M֩3/JJV|┠h (D%Nb4 ;9HY a4tQ  HB `@h#xFXN3%>lNhX&ܡ"P~%ߐ$n` =$@p-(ܹ~._ln<_kp`9SaRp`Z Uee!1uiVUI]o) π*; Tv H ԓ%]f/7v*́m`MvaV AҮq:A jbiRtbBdYEU ,8g- @Лlzf1w |L>S qp S[r:pfN&yM,c~sgsw6\?xt֓a[o M&s[Q$InuyPnL.RVBBiS­LtR()RWQ04jᆄI9 (@8 8ֻĖ78@p"g$"@@$m'eq/KbO_?qʠ;rEE;[#`mM/#%k+e p bV4A]u娻'660+0/j,i3%$Pe1wu{ykK`UhTB;͵m'<L]hXX9dЌ$@T2MAG3¤kUR bS$0zmLJԬ&H%aeRVZ@=ssiπŰޘ.ox:NBfO$C'eYCTfpi üwa4fS,/Ң#.zGH!pqO_z9&~ 7ƘJb?x":::zG) ?wqTmdB  /n9#]E~IDATP*@* !HI \N$p̅3k*C}eXJ^yAB@ _9_0LE&yN|EƘ;_$AX'bYuJn/=5AMZO=w>>j y36έ= ;BuS^jvWc!mͲ,.]][[<|s HIp'8:B!D+ m NEFf9r[HA3@,Lp|a !9.\CC `^)Z| 1c$J(}pT ,b<@et8$8TpmEc1ƼBR\Ke2>Hq.*L _ԝy|1^J,c1VP# YFDt-XYYImEc1(P;)o:v҆cwuh*ů ( R. PiaJH@۹|b;,7c1/CF",Ax<D D`U ʕ {/j{a O Ec1@Q^o>TyZ=4UQ2{( A "$%*Y?E)[<4'AzPSc1c]i^ n OĬKo͵A箜<\h$(teage]m_TJY|'<qUĿ1cm{`<E If @In?<Φ 2%U$qLqrf\ڠw):eġ/c1`( B 1 /Uhr8YsPλ d^l't?^ġveVaup6 w ro9 A rbw1w 0|lri%iǯ$D  m/ OO3{Qo}1Vq $c1l#P#W_Rd E]VYzTw'" d; Z"zcs !MB] M@rjXHx f,1-jB>kcEƘF 5gQf{NBaH A )0>p9'u ',zщ&csCwkn/Yȹe L|d@N .S@ >Nf1Xo9{dVM4W/_&i1 ~c^fx!ad  K! AB'mOc+Xh"C q+7c1c^ ddPi loD 5Rbwcs q|m_- #+;E~Vn1c*ZY' eND꫱9ŝsQ\yc̩:xcR0Ux H@ ifmOi @v4&.cMXrPPbhxPr' Oi矨 ?cx1Xo9S(^hpUG-^i E/bǰ['_ܹ;U@1yawtym-mTI ebOjd*.6,t<&pC1/[ܮk}mc{9NҴ{ ;NB8YEW8.8$iq>n4g^4 *i"lTc1Ɯݔ?qKDT5~ E':)U$,Fi}RwfUc1Ɯq&4_{ܭd] PKF1mb.eSfkVEc1sB44 _50Ne /p VB [~JdxYFi >^c1ƜmMGՕ{+u=X rhXk A @} @8,q}*F>$~f9xc1ƘMe?M2崗hjQEñv "۾[ƜDi.y  YocU+YMA+ wyweYgYE^H~;e&ݬuneSv|g^U7c9!C1\ ftVtahN q;NAq֊*v"xc1Ƙ3\FWVf>~ܶH+0`1c6YD\!( 8Yٲ,޶I :M%Xo1s1t]'_FV4icy:Qm,7c9;yJL(ڛvz-mN'Cy,7c9hEZy+/31c6Dۼx%A|5lm 'jc1gX5 @!>Xd|.}ŷF Aj"faEciZe?L~>w:89@DT5>r'P ހNgYVEu]'IۇEcĴzai"t:LUbz>Ěxc,7c95<9$I !n׫*iUc1c) yf3""$IDdkk ay'I37c;p4]vmkk*}b<,,wv cj\ǖ;0c]g0Lpx;cVe1ƘVUBv4 !XsGY5 mIENDB`dlt-daemon-2.18.10/doc/images/dlt_message_flow.png000066400000000000000000001465451446635226000217740ustar00rootroot00000000000000PNG  IHDRo5;$sRGBgAMA a pHYsodIDATx^ui@qh$Ųe Ġd83Ә1]g -qx3ӄt%aW V<'g 7!1Dq+Aȳ>( Ѕ =@+у.g !9Dq @!X! @A6 .]q/ X t< H #O 9ʴt!(B{!JA AEDNQy} Vȁ>g}P @ Dqz  V] <.B rCBA<2m@] ^@@=yAp@GtrYiBQ܅B A38@} L@.@D,k.mxm\<"((X &bH@2$m)@ݠ&;}<4@m RܖA @x7$LҖpG4 0\Jx>I晤H#@-Dq[r@ 0 ݐ3I[c=@Ga\$p1*$g#M mq!$w@@{$\I t3I[Dx 7Fy&i >VݏB(QO g :D?&XRˋjaa>>ۗ’ZxƚZYl#򺺼]m{^VK3mS%LҖSpJQl?C>F*W7Ե T/+{ʓjꍉ6ₚn:>@I晤-# W ]~@F(Na]Z@]ɭEUuqpR$"|WIٯ_VjN.e_橕djuRr嚕3I[ D+X"'fe]Q|C]QV*<kjZxb)uvju]jqȨ{꯫SW}I晤-w 7DqipZ`ŪgEqV#]Uo,Dnj"y3P_f(}J?D|F\ѝdj;%,@6 mҧm8@@R`8\pdjQ$( *-0A9 5$EO؁'(?hq|F f..F ` (  ]HwzAQ,)d%mE9iDQP0 O ջR5Eu^UO5XuyZNoW Tw|-ɕެn Cޢٶ+?nwZx[-InEQfxr #Dqi .KjeWڣQ!.wݡn[7}Vu{@D*7ZPw-WxSQ[ A(vqL `wZ3ʒZw]̗+l/6j'U_TZ޳jhB\KkvWR-r?p)+cZvBh+S;[~ܮ,Z^>@@:DUYSǾ'uϞe|bK}q(P'֦WT/-{z|(Q1ݻW6&#vK9lⅼ8#'VzуsKj%ib ~@?@g}I:Z=UmkjwqysKw1?(~'.3qܿ(NjN}o(~u[?ùzDy0bJQl?C>8)IÞC๴a\PVPU r%FEkź-Nz{wRߛmփv wU# QlBQJ$ȉ'GXV7ޱBJlޢxNK'꘻'N?{ۤ %3'MiDEG W!`(.&5gOU:Qڢ8m/+wWw]{S姓ڪEYS=/KKV%ib ~@?@gD^}U=Nҕ;FL֪+JV|Bxpk8S78U59@tkZ8Ym?(:F @V q'`VlvtL̦MlӦ{Nz}F%W>w0P:ћ(~&ƃw$e$ŇfOocKosQ/^Q DH@WEq":7_T?7/8W8](?tZ<78#1B7Pp#; ۶Mj4+ž` Hb]\~㐳SB1ϒC I؂~!ЙPrs$-aCQl;Bs<'S?tR;TRJ&^CD1=ڻwo;w?r,tNhFQ܌WCsH^{m\ʧTR?^q% 2D7xH@Bd҉ΙI /(]BK"2FBN :Dq^D1%׿+%-?i5 0 @|D&)!L3 5BfC X)nώ;!]Kt)'tzkV ؇(#<"UdK'(hxO?pǫZ| (!JHNPB,1l&)d%m5WC@҉LXס@%Q*@ FN!`@RV: '~%L9kK9)@[@ ,]K^^I5@̷ +] ^@`@[')pzo^z^6ʺ*iC  I@ yz }[6I!+i^t p<%Vd:3( E9*@p  Ȅg^ :B8Ma ʶz_u)Nmc5M.eY;RmK6$MlAobG?ZęXkz^9?]eE,Xr~B Dqz [&%vW(ўt9JW,b1~v@,űD~BQ ".|]E**/ (& g tf*qVvK(ھo.AEQl8#C0udt0pt$;m۲o۞b-  }B 2mK*qEL>7=$K6}LXcl}@M Y^?j;zڰwLb駏gMQ7qڃjh*Xk{1,ܵy5eߦ  DK@`@Sa6oXۋ.۲5ekO_Oڴ4"DY%b:YC@ű1' NA@Rg8{.u=qm蚰9[c1wEQiځDl&kKχuJ\3ALOߊmϻǕ'&7@A@V:0]Ż{'D/|yM |;:mVʵ$ %(b0B0k[6PHYͲOX?dkzϷCvMs= `yڅ">`VtJI枲4@bG4.LBvMkat.Hاh+"#EuWcζ_+z ^mJ|xΧ,W@QL@h+̴mZ"ZB+qnmoӮO\8xE0BwOVtMOk>ϥ O\8xE0BbN! L꽅Զu9HSM/lF!6mq ¬vl:mZE#g-뾺k K]?DI@ P;^Z5Ж}]JX j@׀%mYR}[:;DڷKJwu_mm]]\BQJ$"FyLb8-\MWn۰3!;2!D198K0ӫZ}idy􄸶H״Ʒ Wv > M[@#mYYr-W>}M4i>cT7J . `XB fRZDsֿ'>1\EmXG &#-{a@=z @0ZꟐ^z[yaogjaaaϒ7^57_R jק7_-׏]Tw}:R_@@{:@6ԫ>ʊ&۲u!L>V^蕢I WV]jķD(o!up.uק~ !LKڀ A1K꼚lʰYo_Rv={??/,w>ŊqxHQaph*lVƲG %!Mg}yȮOQ7~F-.[UK?ԗbWs Ѕ =h*̚Y2u}aɇ!;mƃr6ڍOWkbJ(@Gb֗ϩd;/9Vw>_VSn{q@SaAbm'W]u+r]^+iH[8\_hJQܔXLgv 2C׺_;Wa=X $ugt$ 3 AO5šnYה%]ߢPs~A)DqSb1]߳(~zh;{/+D_ю`V7Էa|Oצ¬e|$7a)]ߢ8َmkU-io̞6ҫ(fkl+Ϩ箏D/'l)nt[cbZ>F׵=iI#ݒ-7Ll_M*}~pOQ/"Vxb.^ZO0X "e]r}ͅ߄}f*QSԕT;mQoUDuݎ-SR@ss ! =QY ۦ#-#5m5J:BoKz.+DMk%Wz@CJ IjAtKS_Wj׮_R'^{߮_Q_Fq]W- )ve}֥&b>/YžF{;oUޱkAu:q?Vw}ξSw۴6 fu0S[}f[!;<" :u(zMxuL1?>hOċ50Z\gwye]HA_ /Dqp@]aVgsVgc[sI]k|  =Dq)K0RϪޟ8p]Ymքˇ1~~$d=?W߻jioYw_셮 ھcD:znzrOO}j,Qa:c8 t0y?"` ]?:l^@ױbW0t{mCv5ģU2Q<\5h][Nfs^X<2>sħl.?-ݲO" `E{i.Ru}v!ƝJ79`w7 _x3=NWs_f)vef^4n3%Epvm(21(ٟޅrDq|=ثppԵ͇]E7&aV[_NQӟFNWO?lo?}R ~p#˿T_?~L%,Sʆ̬7]qDq蝘wR<:="[kAxM&(* 3 |i#Q%?,ܻU]u{-vW&vR~wfjQ/)[Ej"f-N] _Pp 93:ה1j+C=Ws?yQR ɉD^?+gjꕧկ7y*#{(*&zkL`'VV@GK~UST lQ*o!ǫNUO?~R>'W\#S,f=$7e!oE[…)bb&+;b-,,N*>2"Z`_Yado;?|B==|bJn`P;#qkZ0{0k[)vŬ[2<SM;%Cx "rCOKC-t7(cb@ZĞ~c*K xm,y]ʅ}SQ<ږiXS܃rVr`>,A-ْovd+R{Gʶ}?XîQG8yqDq ͤЍ0W>BN3ŬUNZ5o+&|6ۖJ쪶 >| 3OT(_O}+w>Y)W?Ľ'vH7~.}mɄ8 B>#+SǺ5ӱh)so)pَ-Sį׼bsv WnC48KQlhl;VCeMqqC|b\<% q},fmDqR燓դbyO 2A7k|]Dq3۰}Da FQZD  jj*C7.%QaW(>P' Oq~p+)veYZ_<e DF Doߊ$OlɦWh=-*,=2oK4ʼnvU}Z Ϥ[p7ۙ%f=$V՛UIGƫyCv2}kQ<@ F^SƑ|kg)٧(~鯫?M~z`FC7 Hɟ]ODwjݬt%s4Y=dWcn@ M\\\Y¬MM׫b[u,^?dg#f! =@{%ִ̚r]u8K -ih@Kอ;Dqw[%̚)v٢Y/$) (#^Qezuz0 XѦ"׎Znl[Y|)C0@Q@@@0ӫZ}qlRz]hY)!YuožE !*Qt;6;UDy(0#y.̠8x[xEJYӧi1ǫ@هY싫p DqQ@0G?:uNe%U1u Dq @,aW7)v^ YW!;2 8/@@Bq]D%&eyȮK$(3nx (T&۱Y/UeeyȮK$(3nx ( cˀhW@y'P<6} (v#x(fFXjyq]JkeyȮ>O#(/fx ht],;8x ;Zܖ=( r9 DWYEL#4lE@=|@n0N <[ZX#t@Gh  Eq#:l~up];:^B (!(:Gp]dX-@  Dq(@Qk6o;6N]W^B!(%(:;Op]DhSFQp% v: 0@^}])vIŚ5/@!@MEqNN;G4ݚM] Dqh?@^M]/<)vd-1.@}bc@^;fSڧIb`kϙ;! ݎA jyQ욵uK:jy@O yQ<@NJuVقc&(v;>x EAb` o C |e!^-[Jhc 6X%(v76x dX Z;T)[-f 69X%(v76x dX Yp\|J C02Qӫe/N>(f 6yX$(v3.x$2Q;fMgf5 e@=1?^=ֵ %O֛|OF(-Ss?e{+x$,B5 }@DĨK'NSӿ{#oWm)KZ\$`kA  QQ늋gyF^fzS2B>5 }|@dzʺK/kM *[Ռ/@`R\DŰ'e7%s=2 [ؗ ODH ).v}֎b2e[oJF:Q@+DWiveElom)!ؚůj}noEFeTnwEJZH͇lG8B ے-[oJV  ؚŋkjZ^nT}Z\\Q6N ׹ ƚZ\XR/̓T7u.FOw~2֛R?@eOEqkjkP";*}U]T+ ^r%ZoI5#/l:36y[5u©q[+ԅŁ:wF˗CP呆o^cpN'ޔ@.5x.,)pBW^UOP Cue 3]V-u} ɋO6qQa W~B@E\9ŮzSꯇJ( ^TԮ;v$BKv.(^bW*Nb_m)CZ\%`k @O_Zg<3VK ԡ|bYu1)TEq0ŮjN ?1r]wM,zSj#Ba5/oOؕ)ߪqm +]^J,b0'{9ŮhzS귗H(NwrprK2*DjpHoVĎ:uCj%Qb|Hb5a|=2i#|#o[oJ  ؚ<Ź{¹uVWg6jmՅGԡ#hrlKla}qviVKd+\4b)9ŮhzS꿧F(.{,94Wf\z d#I}Ԗ7{Jkl?b2 1lb֛R=E@5Dk?(;; aMNoipQR  0A@Obg')l)-B.5 ]|D1I [oJvzKKl?b_ )QyO֛R=E@5Dk?x $S4&?Ν3! cL~Ў9/R#Ac@D)؅$)vMm]) `$]l;O l̻gحsMۆSP96%c(ʼnsIUc7*74B )?PP:!E;@[s?ڑlM1X|Рc<ƨﳭ@Ϗ W@k4сy^[P?U.lq2@N5P](^YA~yv~S>L'+%öjQsOfښۭ< cwQjFy֯f  =L7]NKd])Uv!1|Q|RTH `eڰbr%H (NS8-P0/&5gŬ8)[)/wvK\)Fx@{حAB2_K:X"ݬQ,N\( a9EFvBׯU tT B,91j[zN8IS-N@[c Ql)4;I(y z#. :xE58>Y)m͕b4L Qw~pW=hA!um#fۉY)nji,zGEQEzd0-3!jmhՅGԡ#.zl {5ʼn/ْ횺|QPN?O/<R#0k+m8 s@NdP8OqjyE{hY-,#P~tUݽAsC-Y*mkj5u۩X>wHwKc5FP,puV^ B!҉LSBa;"D(|j޵P`LV_l+NWἨX%s{Z;c+jSڰͭj/d>WRzdkrUz#6Ҹ5BI t"ŔPJ(~'ԥK:w'fD;ٳOl=*P}5ezCjҚ:<a-N粕]Q=K=HsD~V LO QS]WLJ:'g`YzrV^ { 0&uK'('ۺEvZسO0-/c+KjʆG_Q\Zs- jbv(-|Y2_fX8O[c Q[9߮X:A nV׼BWk/2(U6[ZEqYo&FBJxk(}_UqIJd6*^3oCgq[y(6VEX:A E_͵-,Ղ+J^8_& P߭bYBQgqo2<"\%LKDVJ:lK@ؕ ܏.t *)Zކ! "1ف3vjt믶V⩇JA.14k߯4㿭@'V-LYD&)?(ֵM:P3sO#![c Q^.QG]St"ŔPt Jۻƒ D06X$ 97 -5F@rtU,XKD1Q[~<[y(& 9ت[:A E&znk7.-^' gdF[y(& 9\hϜg].쭇 ȳ(ܸQ8T:$iun.{Q= ؚűg#rWnHҫ;,B.gEmEEpՖ<-J2|Z=,O Ȍ2QL>:A@rj О9!KϺn][AgQq'mq-B)YߥKԹs~4߽ m>L`0H@re>Jsn@[s?+Ŧ"F$!XkH{xA@c\bx6l8\GU[^ƲӒk {_~ū/omLU[@slz(׆@+x<`EsfmxWjbJ'@ [s?I-c6,ˀ1t+)A8PFV^ G'HWm93'$cY{wN %UmUIpՖ4I2^]X҉.ץA6[s?$]J((7 ؚ1g]}Lm[7w J'A f~DqYP%+*ػw/vXKM3Cn Dqq -A\јe4:v'h!PN1Nfb U[N XzukP\tɚ?46xm;[y(n1s`,0)P ^$`kGeڪ$ 9\Ee#_BADyG}P [y(/WXrj+d, | Aֹ0Ɲ  D -ܜd,Y @_=gEگvlد<$sI.tZ@l☳.оK&I[6-;Ӹ.tXZfffqjC$ ڬt,=~``2:'9 IKlRivp1oN@:/* Ld6-~3?fk[y(6Y" 9\U M)1]|e*Y,nO[y(n'`:\m!^&s@2_8 KLS$sұ4);`gL{m+/Ŧ#Z$j"'{vE_re*Y,nO[y(n'6D@rjJǒ\VsMd=sY,nO[y(n'`:\OM1ؤ A; -5F@rj KҴ(~[2_JbaC?m%Dq A%<s.Jh5|un0rfznV^ =OPܗ %V}C:Eݒ8lwm[y(v7'Lrj+ uV:ָEKr ̜mJi$$idC-ɟĈPg ɹ DqZ\kpՖ1xiQd<'X"ݬQ,N\mpՖ!tA%5nj:ufDY?mY-C6+KӢqn| z`#c o~K!FW H&I[r/I-Xs,]%A4ɹ&-c6,>m+5=$xG[y(%pՖ!p=X&Xw-,w=X!67{½f3AZ~U^I:_NI2v s DŠ-ݜt,EE770GupSh}j#[❾+O_<{Z{.If D19$i+8=tHxMX'ruuR($.BRzxd·ͫjUuuW}80ӁpR.YU~Euʘr5+=)اqKMH"Zc$ ذt,5{R+'eW6&V!3WND\&vۊb-2ؒL޵bK}q5#=Ggo Ed(~;a?Etfj\@(@?wFݳgY-|=~bmzUMuҒo^7t,w׀kbKm8 sU[IcH=+_VGP 99j'K'Dq"?4P˯]Eq*V31>(UBP,UI?lV?qFw:$x7O%QRDpVmuXT.N _)ڵ<-jV0y^MgNRϥ㒇2E;÷_kt8(̣nQLjG@r0I to8-|Q\ GRZ`DqwJgyj爬ypwH#cYo*dgߓ۵joQ<-){^4g HM:(nBk2/`ұl*rf^?.}mP +5EtMnf]'\mi{Y HdD4 %6wMY b飭@ǒaSrj8t,Eф(/X Q9E2\ALVO9dRW՚^:ֆD#&UsE`WU:_NI2v s DŠ-ݜt,;%ùR(zh-}[U>Q#FAV?hCEL_hQUߴ,rCCGx!+_SDP:(n>c"[y(v1$iS"YњLȯN৞}{Z&n+2mJxݒ-9TIkCnC`HXBLC$"D@p"<͛;㷶&vGx:PvERqRCq)rkpAHھ|^Q,= Mր"V^ #M8׺-9\s引P.}|s(\LC:_}]}dw@Q{"9\u[v^:E+2M)-WI28;@NrgNHDzzD1ؗ.9}3~'`+/cL<脻kmbE' `ߤ &-c6,K_W~ێm]:_I2W,}X2~JWm9'ݓeS~QW$NJa$ 9lbizpnN@:'SlKk=Wbr28IVp{$jvDd0h5ΦD\IWmQJhG,]:_eFV$SkBV^ Dk2/`ұEO;_:_I2W,}X2~JWm9'ݓ%bюXt:9(d&,bAU[Ļ9X"/GwϸV^ MGLz@yΎPIKk×.@5[c Q:d(I@rjKW,c@ƹ$xG[y(%pՖ!p=X"11W'S̄]ÜEQl14C@rjx7' ˘}t61!̿q[y(&'# 9$mI׶aX' 97(nBk2/`Ò FcK?k ltpՖ=sB2]w/(Ir̦]ZGV#EB@rj5"KI4E% صC!˭DYoU[SsW{}gUl?bsH&I[97g&uHvܸ+ QFx -dtU$b1M8~&Zbr%H% NIRUWڊ!vsm?嬈7ભ)UX9ꖫ%貭XOsEllN$NfWdGI^؂ؚr1RU[D{d,زo NXOƌ@GbnwTrjd,%{_Q][1&K?f DǒU[Ap$c)骫~GIvmŐcb9rQrV[+IVD~]M<3պ&?Νk@E(.`CW|HKY~,4-YrIWmyNKR+նw_mae@h9VE,~ϘZHWmyKRYY,;(RטhNE~5iږYWm:]_QK9O-C{t8դ G@) [y($L{-txb&`kGǜu]rj!޸"Ko:m'xb(;U$Ƹ$pl Dq89uO$%%ci 4{ҥ o鍣qoBիQkipoN@2[Y%Nė}1eڰbrL\soάJ((B{!&l&QZc$ ذd,$ֵY%NaPct(#`+/$-+tZ8o1|[uV^ [ HWmI3d,c%Dz J'$båA6[s?;ભh)QX  J'1ƭwq[y(v6%p-$imbv/tN h15#c:.9\no\7v| ŹsB%5e+/B$PEeF2Q| +Cc(#`+/$%>u?p l۶wQ6b,$iY`;{%ϟ-C5#M9:.9\q? L#/%Ǹ;“lk_pՖȌHEX:bt~ Dq8q!U[mV:v:$5聝bt~ Dq8q!U[mV:Wīנ6 `:$_2)M@Yٔ1ભ"*[X"\&s@2_eFV`~lxh+/6MS${sұ4);`gL{m+/Ŧ#Z$j ұD"\Md2,H7맭@7W{@@r0Is.JZS޻]W7/c+K}j޵Ȗzʉm^Wy@-,<^ Om F2_8 KLS$sұ]%ܼ>{{,GڤpCw&EOd6-~3?fk[y(6Y" 9\U yQ>o1IujS7V*+]Q GfZre*Y,nO[y(n'6D@rjJRdxEuC @}"ž#7Fbp,Vk羞[]ޫy[.c=+ӫ'N{+ߺ8.y(+V_vc|ԣujgv>x&ȏ⇅S/GW|& RRn2.?Umw<=/W6R߿pzM޳}sp6o>IV^ @@r0IХho/US<W5{RG2LԲ硁:`8->u{%w@ĻG7s"Uv@"@T9ŷ%ċ*uQgm]3]㜉⻖VzCL`_SO%;BMuCRq_SԾ=ɇGU;I5YS\LXU~xbT#{KkC !`k,!IH&I[CeDqZte1ƫV.pE3/HK/7):A?;\Dq~EutKj˩ٟb|Jm*ufU+rA0is Hs](nBk2/`ұ^>n7E{UB/kC T$9+-}bC>e %$U|Kz:MrF2_]Y,nO[y(n'6D@rjJDz)ְ(x7lW쿙 btD-]2|Q(Q7_jqC=~vPح#>mj<Ӣvە8[e"A\r:/ Kgrn Wm7ewQ\Wf]) _#+;XLj.yVD]Q/*?>wHR(R:$)䙆`V^ C`8[H).-kcvmuEqe@C63y0vq%UQZ>Q㐏J^I=upJeEb|e@l%DqYP%+ұRWmɶtJ w(Ѯ[ͫ)jqs۹G;ZQfmڝX[Qvţ&q Cr+o(¿f9IݼWoiGGa` Dq [$| JDz{p4-W;[Vkp׈-c[+[gym-'çdK~d8-ߒ|b;9m|ua_Q_pV3)X%_W56jOt9c␏3ṳdkO49-ux|q^=^-o;[8C"Rؒne쇿KhgDqI@rw]"`+/.eLD:IR5Ţº'ΙdF6.&Kb U[N XEoZ$ճ]FQtZ9-Ꭷұ Axwd3 z3|}n+/žfL`~KWm^#K2Hk/́F`@tV^ L]ڊ1],}pWKkױ0%Ri+/ƙz 9$mσvPd75 ĥHWmeX"臛_2_Փ=Y,nO[y(n'6D@rjJ1馘 %.ufDY?mY-C6+PpSKkQKx[XB7J@r0Ir~I1!9r".K|itd_pV-\4A@:u ,!#ct@SϋKH_ A.uʹ_eB3J;a7Y_SQSꞇrmխ}k/%Ȁr( . D$ssұ4!TL٪PDߙ+LWgiu:8x}$ oO ջؗ`g r6'Vv'F8e}sD~6Cۯ< Hx(nBk 9$my1'%?hW*F+*^[YO[H% ub5UBoZiIT}aJR1>T(.!p'Bs|&-c6,K#+Dx5jwmc]O:Bnkj9_ϻ^mQ>WbSjooժxqŻo>1ާߴe@+kڪrc(nxI P{Vտ~|U.>`8~.ym|k/%Uda5Ş&LhnKWm>#:}xd{C=~xaKl5ux/q:dG,2noHf#[UnlɖnTIK2:Al?%%$Cw/>أtKǙ'+dk[(Kk˅6`BV^ ˅(=ڊ2;-˶bNx*ZA|C9]39}niU3J?N8]`]AV9U[r$xuK/4ŔNt牅jq@NrgNHҳ[wSNXC0ƃq Dqpq$-EFPP:a?-C f~DqYP%+ұd^y .Gt 7 D@0ѝpVwJYJS9 vffqjC$ ڬt,M!"uHk;9ffqjH&I[sEIj2$չC葀(14UM@rj7' Kn|m>Zf~ʹ׶Ql:دE@rj. K+dHk,Sbt~ Dq8q!U[mV:&ܒufDY?mY-C6+K+dHkQKx[XB7J@r0Ir~IA;IA.$ɹIMhq1U[lX:E-uEPWst`G ׀D`KV^ ʼn 2.hұX&]W7'Wy:>ccg>HkXۺuȸQpՖ$XlI2Q<77EGSC:jaϚ:z9?o7g~ty٫;+jSZAx^SOl%lzͅUueb{ j u9_%,#`k,!H&I[C)R<wl/L⏨Oέ o/=bV*Hzx6KKꞇN'Ě{u٬TzCjҚ:)٧}{wvUQfPa,= /l%D)cU[qETұjq(Z)^ȉR̗ձ%0.V_8v5{ntzupznwͧ] n[Խc|A[1ᡭ@ۈ6mN" H2Q\2;.()˝rQH^M,#/TgVU|bBR\V.d6-~3?fk[y(6Y" 9\U Mt ]w嫳ؒT9F((#x9-'-v dݯ_,u!vTX"ݬQ,N\mpՖ!tAj򉩇zť++W_[V?}~(YuIͱ׋.uKkA`[c QLjG@r0I t܃v5E.'vjhzmP;q$X8M@Yٔ1ભ"*[XƸR\]+\!.}nw^}ݿu޾mj=]pb+ F@l%DqAjU[Ŀ9X")E1V|yimtd_pV-\DULEo>K=L0%i+/ՆHWmBYX&ׯm| z`:X"ݬQ,N\$itι(ɟb$չC葀(14$iއՊ$D1شЖװF2@3Y-C6+KӢq o| z`S>Kx[XB7Jڒ-X"ZG'-w=5y\<}ytďK}Wφjkwa]7 Dqig$8ѭג)NEG=+#1VKxʆ„ԧ}Y`}I7 xh/..,iFwC}s"Zc$ ذt,bzcԱon=]QRܖ:[=>s8}GCLh?u:saaY-??mֳѳݜ8yͫjIupE]裝coڞ}I-~y1 S;m$GL?ppɤ@׀D`KV^ ʼn 2.h:?fE5{udu(vN۩auG]]H|Q^= m@k^M]%G>Cݙw+]#ی}9^ɶZWԱN5U\lIř'dXV?}eMs}+GUNegde-r8Rhދ(=<pՖ'M3j۵Y(V>V8cܳ%ۚ9}s]ف_78y҇찍NM|IuL^M뭗VAx8N-է'Byt4uv:'Cb|WPF@2/\E0#e2eQە5q{쎖ZY}jV^RSpVkbQ<ܛZrbP 8 3).I&I[vňbbC"`QP-bD1ؽ,9_;5 }|E@r0Iڪ<A# DH(0B`:wr?xD()K$a^S?zjEpD|#`kA+x<`jk+/Amsߗ' .[ݜ$SS[.]RO<ڻwX#[۬hVq@ (DqPiDg4TC5 ޤqDqZ\+Sx NB ! 9+/$`kA*05Yk"Q `jp["=l?bQŶ}  @ }nqE3zI^0I(6Ul[!`j"Q 8j"L@NdߌQB3Ț5 #Kkk0ir cl0 ]:bJ(‹K=5 ]|!`k0/"z 8ꡫ4Q@V:bJ(j@l?!FW LxdUf"QG _:A 8ҲQKEO[)"t5ܠ J(Vl?V& L.374%8jJ,닥PkWzfkA!F` ƑApą J( NnؚŁ&Tݲ5bfN#8 /m{TV:A E[WQ\':\[+H8 9G&PU:A aQl2ضB`Y@G~xG=[v_*—(秭qDǬp#O&MKbcmJ'|yyGQ]pU<  o9y{[KE;5#hH@[W?3 sNdyCIQvo[b7:5:̭JI VCkuJ'(5$4f}QMQ[)4DuJ((1}u=Ȯ"0S[bӑ~l ;J$P AME1%#l#=J\G`WAMuJ((p3v&pܹ=^^0 6#$`}Qae[)t/|J((?uzZt%`+]#5ChH`V  az9ku[ QX"NwSwϱfPP:a76J$V!Ϋ({gk0E NG҉ܺC̯qc Q H\[:x J(( k2̯BlFl ^;Ic0D C=4a&uˇHDs^$o##j#oT6%p-`~m[g6w L3ix\& Wwzty[J>~;׼oVoJWiwiդA/)sHWVެnJzf37>?0𳷨7ݟGXQҎ(n4<_le]DL1Q+]E6uޜ 7&eoS ަ|lcoVouz ԝеI򜒌:x(t5W?SݹaIErߑ7E?},~0(n4<_le]DL1Q[y}#UxrVO b9x(֫?OkũpP.ǵjlQhx06- 3Dqˀql &w4QQ&+s5բ8B;|.-g>SB{3LDDmQ a_wJ$7DqF%[y(n0ns.<&NW&oV b-\e?FʹҌFqQ,ݳ1;l8֌ ߶SHZ@;Q\I2c׉DqUM7OTtO#̯5[y(50RfDkꖒ>={|n\aZDw*E/X[gX3.~L#kDq8BgQ jU'KvTQgl%zrGFN3N@;<_kk Qko[)`tͤ(N~6R-9(m?S:j|dj'F{gT&۽kڽoL'-u'G[!-ye~5I[y(&#`k0U)ΉLPN5M7>ޚpqKͣg>;}wq'oUoI‘6:裱(+͵@5\_"w; Qw{[)Ht@SQ<*p'S%ؒ(g~m[g6w L3ib]pz6S"(n4<_le]DL8ԛ>;bTNQ]Ax:J^ODq$`+-m5%g] +ҥKܹsJh}YoR[Q ~_ Nbck>;[y(;,8F`r $k^xa,ݫZr3%s[ԏ}MG[<<.SS,7ߥ"~G;v|Vw8-\MQ 9 D1F'NMqED~xm*QO1wO?W%LXOYyz80qsr FΏے=KxےQ|>uݔq{z-ɉtnQ%=yoxO"~o~㎷''y{NJ^i?Ӣ8Z,b~u)b+T=5\k|VQ֪Q+KjMu=EY?P*/|}~#&ѝ^>aPzTOD ~V}P{~ >я@A5NZKfEѢYZ:^ z1B$(1iCQW3xAؐ}ݮ} ChoP1/@#2QL W,CQN,#]h@d^ C@Nds,%2LD[҉l0@@t R#TP#YلM EdI@w!cPÌaŖ@2٤M _@qȗNPBw.{Dqэo J(" >](+(r["(fNPB!K@J'(;'B=8Fԯ J("J #PV:A 1HQl>M*B/V x S>[]?yěQZD#Ϭ J("K Mg9C;-@[O2Lzf X"08=rG\9ro!G7ՙA$]D &](Dc2D|{M&lhϙ;!8 &8#^#Cj$}j2aSBIRM@@@o(C!Ŗ@ 4)hϙ;!4&##Clj3aSBxR=@@@o(C!Ӵzr@_bwb'B@b@+)2DqэoLڑnC 0GL -§i3p* Wr d␣iߘ# <݆`~5,@[Of0iU@̯@!G7Ҿ1iGx 'j1 X$(`6_Ɂ Cn}cҎ4t0N8bHQl>M!m+V!0!@HƤi6 `q4`"|6CI WB`~%B&(9I;m@8Wi"DE4mX JLQrt#vq̯ӀEbi &m3\ @8F7&HO!_#ӴLfb+92DqэoLڑnC 0GL -§i3p* Wr d␣iߘ# <݆`~5,@[Of0iU@̯@!G7Ҿ>iooEΧ7Q{6ϩR v!"Wߪ˿juu?\6%TL%fdR~/}oD;EvW.KDo< QRt%0׿Z]ϩU_"Ķ^?%sr&:xBƋН]P= XS@QѤ5ԕڽX3pcl~ja:mBEOx?;fhh:NK?̩kKS5/'b(fs²o 'rgD\G5{X7Dq80fv:VMjU&_WOlrקH}F$+&(ЫտkQJ:G[˅(N6а͡%;u'&VbWTr|^o9v|R "ZJW/|DۇWUW׿%Бj5eS]K5gf?.Ǒ7K$ڢ#ɄNh6o!/?X"}rb*gܒ✨gշvґҹw7'\]c>Ԝso5^h[S7?Nk?_*/3ofz>B!kL٤=G߫vWԉ痢ןSJt&Vf>P'j^E㯪ީ9D_*K&Z[?~xV??<\= SK~w@|5y=j~G޸FU~?d6SV~)ڞ}Z~vBA:c{0֓k;}OU#cfXƉ @(#Z5?cth>کb,+ҫ8Uh>8OgDqŷPEM( +SŶḟי7fJ f>V{&^?8_ީ>3&Fxw Fn/뭴TtUkyQQd]ύ:x(t_uebRnpZza2\sbYsRA슋ln!)тvy(n0o"tS&D>m=9R['?tXRԟhR\?5[I՚ŞS@uJqkݼ}sw5o"2c+<#lN=c/d렺v}oV;Y/^WWU:׀{6qoעwDq3%=Lv|Be{wzGgBJ/(Qy(n0oR0='hi?%&]!p+8{0? /MvW`f?6C5YU/$z[wE}tʙBh\%FXe[w򙰓0(xxrynrOm&vIjq;ՙ7/s}аRz1fv5Y>٦{'ES -[ޫ~zL'՗CBF{SGCv6%UNԶ=e[=R&n7Zvp }ڳTؖl-4c՘/ fko5DeXrU^;{686ޝ9q|0H1%[h&S.=˶3oNnQ6ל7Y)e\ 4H˥<41_7tCtWno6|"]vx 7J#[$CvCz/@>li|jb}K1!IC+NCke-Qc7&xնw"F9|VK}Ρ[5'\OsV]5&mn7@k4(vÎ/`~Ǟ@gL =`8A`~&QvQe4vw=̯ӲybigL=9@ ̯ф:ʎ" {؝f;G{Z6OQl1-LIg4DC5PGQDqaLaǗA0cO 3 0i h0F(;(2awI;;@W{i<Dyƴ3&힁  hBeGQ=N3i_z#j=-'(6Ϙz&3p!M(8ʰi&K {_eB{Ns@4_ uEG;ͤv| `=lG/ro]Aӓ p0_4/`֜ư(D(Nycz1t:9O Q\NJxp t55:nI ʁa &{XA qcMXMP\(v bǃ{L؁$@ c G˱4bd+Fs1!fX?%ZAKP4hd.1!fX?%ZAKP4hd.@cO1@4cd+VwcdCOɱ~8K(h \LRLDO9603XDJ3Lfbbrs,y`9f}DK#LFb4G#b&@~NYDE6LbzH#b&@~NYDE6LbQLDO9603XDJ3Lfbu9F6L9뇳D+b m0 4+@cO1@4cdRGloE.oj={1X̧ۗ¢Z^RM6?ϺP0 83agB"$?jjqY]/A9堯mŢͲkenU_9>VgQYfsJ:c= HʲoYk%nڸV&3յ|8c}U]禎+{sYCL+i(vp/̱ʲU~VG.aX9.dd]Q<\PYJrAqr3-aŘ6weޚF;:g@ Q=d>/ּ ˼J=0W~!rW:5}m%Jy2"Fq1̷!S^2$mŎG͙(.NuZgxVmhK'C,:A9]Q\jF(.̣y %ڲQ\3B\VBQxZ2aO+u&I;M'48k<(v|$ 2֙+ŕesnmDq?[ʄ]KK y[Mi*۴RkCDqF$;,[h0Ge>Ѣ"Sr78 +js̚lQlmg+yɇ1OEHEq-^UOQg6-Јbl';s؁B-kcQ\sfΚ:mVGЈbDq?sέ[qež+w jlKmJJdSjʚ+9fAG;Fgӌ" G_ysj(ǰN`]^|"3\:Xez|&39fX@)Wg}XЗg\z<_JCoQ>1Wy&37*H-=(k!ZT-9ؐ1I[yDac8#"]hMok1I[5ݏ2Df8#"]hMok1I[5ݏ2Df8#"]hMok1I[5ݏ2Df8#"]hMok1m/.]{jv!ŎZz09]ܳ@&!@;`1Wm4 x,Y8rJ]$)敪'Y!~Wb {VN*İ+.kK5qI nX_N' D]bڻv$D{@x_g^' VboI昫gW 迫sڮ_V ISAQ$ϲ3;(\^i!=;jZ @x_5OOσu^=&]jKvha]_'cqD{1PwA 5_QÇ7t}Zl͞.xe(~ I]w\|*JqjIUp5޺G u-yش(׿Z}"Ko˕I昤 >D{Ņ $;PleMZ|= dQ=%[=QdΝrssUr_XI~'mĪw}.y3Fթ7)+8&ps)Q=0WCPڮ~Xyemb[MDtL$sU[ ے>Г˹fj3\}T}pdb-nZJwPD:|W|jJns$H )N"= ] =t ;u'`} s̅}{;fplVe# L`^cKhpxGԢ|tCvjjq;>Hpx?ǖ}]h1_+4]D!!Ȗou5\f6h wS#\9%dvo6vWsUQ,SXI;<:#PW7TVlAsփ1sx80N4 g!1Wm9RAwǭH'6y֮)AvvFaG6ܗJp*jKԡgE|I昤Qw3BCq+gּ#"h=[gumq{09N@}ZKw҃ u ½#6ձ[Aގ(v< {XA qcM昫~j2DrFIZ9X*'@1 c~?}1WmC|+b; 9:9 ǂ -AK:1Wmu͈bQpg9f <:Aw" A;!c޲sx!==W' Lp5\te0BΆ&$sLV(šD~@ 4I!+i+P"I? @*DUQ4N 3,_C@$,b7%sLҖE$M#Eqb b%Ȉ5~|\k@"# )d%mDq( `"*('̆Ql/!@ HmYb|@@D@INQHr @Ka K昤P#C$ @ hBVV(šD~@U h3fDYX Hh~ڎenoɡ(0lA X bb&r Q 8O|wC{t'` ?=O< #Oo v @ {G ,5AqYkup# @/H9(79 xCMp4 L@+uk @V X⏢qr QEI@=9(!O"'`<[N jb4rb9}@ <D1$A@0MC1C:Ђ%-WN7}E;uqY)W]msfJw @@7g @@P@ М93 @8@ ͙q @@`Ł@ 4'(nΌ; @#(,t @9Dqsf@ Dq`; @ 3@   (݁ @hNQܜw@ FQX@ @@s̸ @ 0Jw @, MIENDB`dlt-daemon-2.18.10/doc/images/dlt_overview.png000066400000000000000000000552311446635226000211560ustar00rootroot00000000000000PNG  IHDRI? IDATxy|SU?%UBΌtIgE6HH@ҦgHq>@+ 2B|T"X*e~ZaT|$tg>XZ/p$MMf{=}hrsι'!g眜˰,KWE8 R~a8aWB/ E8(?USS3p@wV0$ H0΅%ҩ s P4?ݝK0+s̙|I?z,*eYՖ SU:"V ]yN Q)Be5j(!O˲,/폳t׮]:ujvv\.'<tV/JeRerqA6SA-O)ȼRjj2/SY<&3Ƕ梶P_Ͳ,˖pq^ikbVr+(Ur薮˵ZeB*҉JQ/6St1:=EEŲl:ewS&YfQ 7nL:UPۓ聍^VC rLhXBK q)IV:ԩU D$t !$F-8՘˜N'Tf&Y$f3[3H]S~ڋ5D È 4=uaڒe2ի{F/J-nXΥj"RaJj]Z!J."mŸHE/&tNfYV΍W9l~z{_֬S~JH/ײݹs'%%ۺuYؚѓk%"aD%⼢ޗg'Pa $s yD%N/JSj ERJ0*%$ɶݞJ_I1(YΥhZ$Ԥ答RҹuQڎX=#S.Jg}2f. Ey\%}=l.ʢ<&Y¨s熆3 c ˲NOM`ҩLf,.]w# pw,HW楧&3 %yNOc3eW\w=z](~9=l˖-~SxwxX*?? ](W@/78p`ӦMO2d0***RSS9yM3z/=.K{Qw#^#ЋpzQ@/ E8(G^#Ћpaɱ<88vp?~pNbXeeY)999<6'~}Ћ; "a15τ8|Ex8y/EQ6nWRS?xL !:1STDVpOw~;,Q̡l%*ETS+5OϑT\ed5ݕTl<.kCt*bkRN> %iR&v* J-:=YJsHYȍGw+Dann\NuZOԥ%}91iٲ##N0EQo[bi>[M߇YE1+4ƊC䭴nЩr5yE ^R1Q{= 55"Ӑe0J"Hṛ2uDBb$%G;$*u|v:#"""l,5"[Be%۬;2Е\mgVn:ogyJK7n7 ԧ6= W zsꎫV8ޝ-/Lڴ_m/LP|ia?WIf i]mQ1`DD'V 8At5'bLAx =%?"#Nd *TPqa]X1eӧ3fG FHơ67{`h}Nyn8?@,xlD$wQG$ W7g HM]Vդv:s{3Ǝ@_a@I|x*E/?Y}ЛʉULʑd'6'pp]HgxTYCiӸD'Fo' u{-v_C4fǑ˟~zׁZÕ+gLs|>4\*H%u_@~ZAa,ʖUQ0qCe?/Oj^V J*.\~FY[U|Ν,/߼sg||7GJSi6O2`*:Gjgˆ HiD43eADZ9bYx`ܢB"M]2>+ '^54TϘ3Gv(:RtF߱xJ{k˅DFF]զߍf}D"jU&9ٻ|`ϫό^d7pW5*m˪0\fv*-*V/(sŲNHGqN5 UK£"G5QF$AWj43Q~Rn-mq*KK(>*|T4qz|rM߶m0G}E'x#^h/Z8O;++v:|s#U;Jd)ښF,]N%&-LZcvl\8PyIԄ͵֤\ANъQ%sbF2{ǺuސM=?{v<]hx9:W~Ƭ]F9w\];=YLDV]?O8J"bYsޅ>x+tİ,0 ۗF;㺡i?{[tyڿY$OW]K\‘#\0sN?yAD=l1@(YDp*cv :ZHO ;9@ta3/ș'c2GV"*hP0ݙX;zѾ_Po7p 8^{.kꎖ%?_0TYLJ@DR-w#suJ++Ѹ]:ݮqdقÛbiiL((,)eD0p1<Ge?`vͰo>+ť'Di1ŋ"C)^8:txb0e曵g[7 ŏsx+ y5Y?M=LQa׍S-0yA EKlu֮Y2I(N**Z>m dS!}'qSI9erlZ@hw@W\u7 ȴ5Ta4q7bF o>w#e w^em|E9Ƣ̓@}0 x/.8X7hv:g+ǝЋS07hE`y5ga@IoWÌ8 ]O%NŒ@ߠj%C{հ. 'aA{w^ 3z,t?apH8 3z}ΫapH; WuQAAA?޼yf'5ߺ€ ܼAhh蔧V_z9;?w4y5ò,0,˺+͋9QS8=2S|2[ &zȩ^b^M3f:tݹp\PPPPPiHHHHH^/ׯ_{3BDYWW\c<=g؋ p>3'/kGyeq 0x`txa<6>Ǣ|Ɨ M 8 m3zBD0w::hA= >N1¢(O<cQ3e w^ ;/ӁFa{~N@{. ON,,\ /.믿аlٲgϦ5661b۶mx oo|W\e˖UVuy7ذaCnn5kF;|LIΞhKM^XDžLEՉD7[f-[_qȐ!^PN҃>~+Ǵf0`[oe[NfQK6~0L"trdԨQDD>z} {; ^蹜HutNӁw9|Oo yI):PNe'܏XSH;j<.k݈f(_|*:'a۰tǗ;pVۆ'5==O#Q,2ө$ Z)PX疧NhOuQNS+eYe)Y&*DeYeS d旧'iDT#b|Nktd_+/IHQeR@),˲LQ6u\qԥ<-˲J1YeFRg~ 0,]&=Ÿ8Ji/ֈ\ IBH,eaD5DDHrc`HNT̘Bhj;-I0˜.+%"a2|l[קn'w:@/YhqAqpF]Z bL uiNN%I"PPbOQ+D5 ˲,[mtak,eYm,2`-Os44T/%8ÔR:uDd$*P&L.pE1]Ԓe|&Y6ȴpw6M%qa(SZW($*#jZH$WlH;{; ^;逈HFEz 6bxtmmmO!Ԋd*gYerJVIJ-kYe* "G:,jLk`a@I逈H$봽TC]&=85'MIkB""#_F  뢈.`!`\9Ca#ui8Z(ILOxo{= >\52_{#F6њLcJ_Nܳd*ϗPY$/႔R:8҃>t? ;t{tc<eq;Ց~g?' Y.̳3 ˦lʁ-7-5y+):Ww6>Ǣ|Fӥ__ݣq#E:?;1r=ص| .ww<.o˲s222v7lذF{Nb&|㗟 >|3gLIIqwvF{nc=|eEN 6r۠j?;8 v:虏  gOh{8 ?a|j9Omy5t|t; v:p;`uyt¢(O?c߆Zv:pw^ ;{;]`N=|A8X]-|,;( _t DDD׻1 tw.Yn/k+5Ϭʠ+<.p>3Ț_78 xZ"'[ͷn-:t(44B-O.(k;gױ;<3;ss^S37c*kxpk[۪߾ɓ^ev:pwl/L=8κfw:hkk#M |,fwūw~7>!9CYW5 iޢ;ܸq#48j\{} (_~qw^oPּ ʚGA{9[4x^cjvͭo,=x![ZZ_#s=C߀uֶ6# Ehnm]y󱯾౹e\l5kBD{[x~&soYú(XͭKxؗ_.k׆Z_46n7EA'm?p<+?{O{Mq޽Ϲ^Px5/Ƣv[mf^i[))^yYaB_}2@}㍣_~y-wey;w.VqqsMX̥EǝEƫӖ/sw_}ey;5{ $A5 ah\EN0fFKKP`02|Dxٍ=S0s=o'| Te`Uze,7qYzQDDTb皙'yӑUup>O`nbξ ~߼.GFqժ-߹Nwv:nMEOWzګ 7o3:C课:sx,hN}|dԤMΧY|zS 2?;vMI|>\4u acQDDWr׽ z_ODBa\(fU4ʐ" ::q}No8g`G%~@D٣ٕQ \4I&F0o^Fe(jIܵU6~}=oƟ͜6vlR?J2ceMSHDg ,UZ`p=DD'2NX#8AD kDF "X{_!J:i*kYDD2DS ;Š)w>1g`HȑƼf-S+r }T l_# 翱w XpYUH8n^ U5[-k_ռ7¹{'\ݼ>6`Ѣe(ny.m? /?/AD=+S/xHw3K;z^Π˝>nW֠v>s4.*~E1gԧt&'E%T_&(m$ψ4˒ߪtݻsG'P)껇TN$"}ęՆC[%kRVyWqÕ+gEO҇Ki.[#;(*;C&/$0a҆}^*Լ[UD&L\_YDkc[U}b<.OV%%<0=]DZ]Z3;[Qe?p:r$lj&n͉+\0L8>XG54N68Atbm&qPW .Jo~^No>̺Tp$󗧊4Sު;2NZ`F$Hymz"Zhϯtcdt8Oy_Dp/5T>C.,=`~LL8Qeie5$OI"F}eN⼘ W2/9z$t\Ӿ2wJSi6O2`*:"JYo&O"+GZ9bႤDz"ZYuD>1ZwO<з{-ѩ$ GgƱ$J"H:H.)ԦWjX6OP(Lɨ EtsˤNdξBۜ*P]j 2@2H'iD7/2pEub5W*P"D?XeY|$DԤMZ; ]SbgDԄ?W6/Vdl}*}j9>*=ID'K?xa ')e۶ݳmE|:ewg䓧?x-XT֖IaD߷&XTfMlH'3s #2jՇ~FʌD5qkաkP2Dq7dhlZADkR ).܇5'H$عe' uuQ#|YY5hm jtD)25lZ[hYVQei GujE=N*Sgh5ao?ذ<1t&*RU,BDd#5.P]De?õkUiDTzA!ş+vTN5 UK£"G #WRJl}|S9?̺>Z|bϷnvƝ|]IĄ[> *b-t:I c-|u>MzE_:L4̅ i(jU9 Ytw9o̿XOdk/w'N2gp EO8r< 3eM|ořv>q-sNNcDDڋ$ H.Sz"MIꈈB""akNbDD؈eH`N\t*H$ʬ+%"a2|LBeQL) cHn;5,Aq?w j [t$*McedȀ!CW3dq;>̉/^^@ s&l0d| r|EiWL[Qt)Pe1=‘#ezeoTT*⾣ܷ6J-xDRZ)4Q-ǥ7JJY\k2sɍV+ݤ_x)l/[=8rW]KLK}mz![S'|u{uQOkLswN8poE)O=]o}Ν6 8x2`N|ce-88^.(|·%-LSVǚ-*c= L,[Ngj2EToWH.: ia(SZ<ɅL(ZR8V43z*jG˗ ^zc؈c-~{׬fhN9DDD4e0LRRb^dYǞv]WfD|gDBe[$x,V+jOX$g;:xdeOuVe(h}'SZzIY9mlUUU]/+Mx.7B9Y>u--﷣hX_>zc4gvr6Ը)*TD". DZRvd?==vj}gYJJJqFQQѲu]^#S)3}d|ErYNyuZ_pUyaaWwrruWw(ke&T/ηǢz>nuQ'V 70ny"x? N#-󹿌NfDEY<%jx?Q$@tj zOޱ>૯z%^ɚ?t|`0"Ũ~ႈe;N0bwAԬ6o ]WM :_5`СCCgt/`8;(_D~Ƭ(AT@(c3b E#ؾ- M<>v9;`e5A#\zR1≈jsDG XܓQQ 3-=:1g*s11<:/qޣHQo2]xbsn5!cGܹcF#|ɉj8! BH}=QCWF(j "}_NĦC裉9z" ޸M~kw)t'jqJELÉUtY1P`(4q VNWTPD_*[EQ|=+gu<&_zP;"]6\8-]^2\d()(3}+.OAJЏ7s129])|ܮA3s.5|2mqX#C3%[.N [UUJDe ];jG/^:냇00lT.|2L^ؠ~-냥a^o;nw:5+::NmkD dg̝+H5 2Ҿ^CfN' "/ jx?+C.,;] : LMJDH厈H_1Q0Yt*X$ # byO=gw}*_"a= DdF I/$q0/-2XK'FDt@6QE3 Jk "&`gfM?ꏕOp0zÉ YL7ý"1ˎ\1\RR]k+KR^*#%#5Qm'MʅNLDQch/.]2\TK (L)q{hE5$e9kKQP n8o6Fsd ziᘵEi_(=L1_En% 2:ɖ6iP:e r~Q|~Q yeW/tf?a_ؠTb\3Hxt7hv:gyiΫapTp. oy5YX" $ ;YX"0w^ YPpv:w 1-Oiy֭\`Mg[q 8F7Arrr噚o\v͑x DmuyDkί7OxjϪ;|J.olmkc+W=Ƕlܸ({-^u{k\ƀ%L=#=]KUݧ׈Voښ}\;? rz:p"ۼzϭzFHIDATB91_xlK3zV n>qTS΁.o 8[!9sB^xt ^z/x6l~^7CCC& ȿUj|0~wq/=fno5qrhbit\.ͪWA4Poמy|n-- 7%$p{`Ӟ=IIIIIIIyyy999˪]&=E=kjuڋ5h+$Ĉʢ\aFYCDDڋ$7*DɌ)ܢs.KR^"bI-#οujY Y`CZ[[>bŊ_'w[\^%thXzrj+aaOIɈH~~6m$oӞ=1쑑կx-u7m=onYdI3ƿoK/lX274atw!@vvv)pRc_]Z bLUuihSIRx9@DD*)3~ QfMw,V+'F*YQI*.ܼys߾}ӧO 1cƎ;==uQ47H^H־ISe۟>W]=؇BN,p˲%rժi? K_ڰtfo6,Y`s^WWہj:ev [^JEr$tsݭ4I\n|&INHO'ID,Kr6b̩\evR$kX*P*Fjvn---.))9ur}v/|_/ᓩ_$m=xp_ۯ؇(~ƽyQWo&gGl~ ƹj!ZPtPŅU# լ:zsw}dV\cJ{w=N^aYa.nDRW^Cֱ ur,tE95(|bRjЇ xP`$2tͤWGB6lذz\^Vru_i ]wg͚5}tDzdAnLۗk TǕ;zP ˃Zot*q:!Ok8'qU{-zfAߞZgt^Z4rrrxcϱ(~ KJwA\\kKl/yWҤICEd7nkizQuPw58؏ǶΞ=,@N>ٳ}хpw^ ;'ANC{հ8 *NhuQ}ΫaF'x/*(0ܹx[--!AAx=4yTi'^hHȔɓ+x;w~~m4p^N(w>;u37p۽yիG CCCxK8|/"n?޼9edSJ`%z^;s*'K}mt<iyf{v. )/h}[3UkuK:|^;# <|0悦v<%/α#{5˗t0qsC?I|<&pРe\fwK\||]y._].0qݽ(p'wПEye=i{z~JW皽b08SA#KSϯ\t> <`.og݇*!ܢNsuw𤣠G&W>A75m qYqv:ptņW^qw롽j<.k|E`y5'ًe w(/~YΫaFAЋ2AW<͛9hikku+44>CY.(kX"^(po3q3zS~Z~}[Χ.uWA;/g(k^eӠ 1,2 ._477/3DMMhp=9uʓOfTDCp%,kׯ=_e {;;g2Iq 1zQ6^ =td~c%%%UVV;}iy a ~] /emذa΂P<;䖢X+/onoowwF'  N@{8X]~;8+QNBgv:pw^ ;85v:pE@j*pE@h_P9t "aQ'tB{wTUpw6pSK͊M_*'Wi.jS41aV?8SI@VbITب5vƗiv*)rQ\@PT9 x9<ṗ<9Ƥtpt#7޹Z3aÆEFF{+W5~a5tE{k~Efz#~_K/|J fZo>t}M ն7퐐9zGYU0ͪ1x%455HLh -@twK "rMFGWUU|cJ`P\x{HYs^7?;zx?+EqY˸FИ*:t`@H,s(CиЊTJCHXvd|kך->dXIDDe[,ߩGnP`,ƌwu7Hοj.Z?:+bj׈wƍKMM-**xW_6n׶0֕">ۢQ'-!",mҴ˷;˨K>p_23bΚ<;E#bD<9~`^@2M&Sr]y;3m-]ڵ+--mӦMGtO|x߶C -LTZsm nOgwS?6>uMb:lxog?;8"qyw=>i_qҲrq[pl^j:-~<\o+bz+Böu2E*}ԻFJOO/))ti?,M6k=y8[{l}+VMq8C "Α_WOKH+D/‰"ZcD<4"CyQPe)L[۠c`ʖ 6q%w'[3zh>co%hDs۱ǚOm>}t{)//Qz@tJ{DĤ(d (;;z0Pu1[i,`-3ӣڋyRg4:4!q3:aN]x<Żw~G}5kުtiTDiOK/W%H ɊK5B7?>/Y$edoș} \]t}yO/nȘ~XJWL&+AWf8`j%'$9K´<OQQQjjѣ7mڔVYYYRR2{찰ϫ] -g~\/;]⫫V}BH}/qGϱ_z.yz駭VkTTTGɓ'tғ Ǣ;cQA$io!ر(Lpc\#]<}''H̢0kĻS5?q7+Aq8PRRN o8, v9! h:Nf0(n@ 0P43`;0/ 4"1@+HqGfs]I{SFi=Ctӈt|=11omlVׂFԴxŪ5HFL@pwn{Nsn%Z{k~FvUW_䕫 \copyright Copyright © 2011-2015 BMW AG. \n License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. \par More information can be found at http://projects.covesa.org/diagnostic-log-trace/ \n \par About DLT DLT is a reusable open source software component for standardized logging and tracing in infotainment ECUs based on the AUTOSAR 4.0 standard. The goal of DLT is the consolidation of the existing variety of logging and tracing protocols on one format. \image html covesalogo.png */ dlt-daemon-2.18.10/doc/test/000077500000000000000000000000001446635226000154435ustar00rootroot00000000000000dlt-daemon-2.18.10/doc/test/dlt-test-qnx-slogger.1.md000066400000000000000000000020361446635226000221310ustar00rootroot00000000000000% DLT-TEST-QNX-SLOGGER(1) # NAME **dlt-test-qnx-slogger** - Console based test application for sending messages to QNX slogger # SYNOPSIS **dlt-test-qnx-slogger** \[**-h**\] \[**-n** count\] \[**-d** delay\] \[**-l** length\] # DESCRIPTION The binary writes specific amount of messages to slogger2. This can be used to test `dlt-qnx-system` ([dlt-qnx-system.md](dlt_qnx_system.md)). ## OPTIONS -h : Display a short help text. -n : Number of messages to be generated (Default: 10). -d : Milliseconds to wait between sending messages (Default: 500). -l : Messages length (Default: 100 bytes). # Examples Send 100 messages every 1 second: dlt-test-qnx-slogger -n 100 -d 1000 # EXIT STATUS Non zero value is returned in case of failure. # AUTHOR Saya Sugiura (ssugiura@jp.adit-jv.com) # COPYRIGHT Copyright (C) 2021 ADIT GmbH. License MPL-2.0: Mozilla Public License version 2.0 . # BUGS See Github issue: # SEE ALSO **dlt-qnx-system.md(1)** dlt-daemon-2.18.10/examples/000077500000000000000000000000001446635226000155355ustar00rootroot00000000000000dlt-daemon-2.18.10/examples/README.txt000066400000000000000000000010751446635226000172360ustar00rootroot00000000000000Copyright (C) 2015 BMW AG. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This folder contains several examples of applications using the DLT library. These examples will be extended in the future to show different Use Cases. Example1: Minimal DLT Example Example2: Non Verbose Mode Examples with different AppIdds and normal Strings Example3: Non Verbose Mode Examples with different AppIdds and constant strings Example4: Different RAW data dlt-daemon-2.18.10/examples/example1/000077500000000000000000000000001446635226000172515ustar00rootroot00000000000000dlt-daemon-2.18.10/examples/example1/CMakeLists.txt000066400000000000000000000017571446635226000220230ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # # DLT example implementation # cmake_minimum_required( VERSION 2.6 ) project( automotive-dlt-example1 ) # # find dependency packages # find_package(PkgConfig) pkg_check_modules(DLT REQUIRED automotive-dlt) # # include directories # include_directories( ${DLT_INCLUDE_DIRS} ) # # build project # set(dlt_example1_SRCS example1.c) add_executable(dlt-example1 ${dlt_example1_SRCS}) target_link_libraries(dlt-example1 ${DLT_LIBRARIES}) set_target_properties(dlt-example1 PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-example1 RUNTIME DESTINATION bin COMPONENT base) dlt-daemon-2.18.10/examples/example1/example1.c000066400000000000000000000052211446635226000211310ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file example1.c */ /******************************************************************************* ** ** ** SRC-MODULE: example1.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include DLT_DECLARE_CONTEXT(con_exa1); int main() { struct timespec ts; DLT_REGISTER_APP("EXA1", "First Example"); DLT_REGISTER_CONTEXT(con_exa1, "CON", "First context"); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("Hello world!")); ts.tv_sec = 0; ts.tv_nsec = 1000000; nanosleep(&ts, NULL); DLT_UNREGISTER_CONTEXT(con_exa1); DLT_UNREGISTER_APP(); } dlt-daemon-2.18.10/examples/example2/000077500000000000000000000000001446635226000172525ustar00rootroot00000000000000dlt-daemon-2.18.10/examples/example2/CMakeLists.txt000066400000000000000000000017571446635226000220240ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # # DLT example implementation # cmake_minimum_required( VERSION 2.6 ) project( automotive-dlt-example2 ) # # find dependency packages # find_package(PkgConfig) pkg_check_modules(DLT REQUIRED automotive-dlt) # # include directories # include_directories( ${DLT_INCLUDE_DIRS} ) # # build project # set(dlt_example2_SRCS example2.c) add_executable(dlt-example2 ${dlt_example2_SRCS}) target_link_libraries(dlt-example2 ${DLT_LIBRARIES}) set_target_properties(dlt-example2 PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-example2 RUNTIME DESTINATION bin COMPONENT base) dlt-daemon-2.18.10/examples/example2/dlt_id.h000066400000000000000000000011621446635226000206620ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /* generated file, do not edit */ #ifndef DLT_ID_H #define DLT_ID_H #define DLT_EXA2_CON_EXA2_ID1 1000 #define DLT_EXA2_CON_EXA2_ID2 1001 #define DLT_EXA2_CON_EXA2_ID3 1002 #endif /* DLT_ID_H */ dlt-daemon-2.18.10/examples/example2/example2.c000066400000000000000000000060461446635226000211410ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file example2.c */ /******************************************************************************* ** ** ** SRC-MODULE: example2.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include #include "dlt_id.h" DLT_DECLARE_CONTEXT(con_exa2); int main() { int num; struct timespec ts; DLT_REGISTER_APP("EXA2", "Third Example"); DLT_REGISTER_CONTEXT(con_exa2, "CON", "First context"); DLT_NONVERBOSE_MODE(); for (num = 0; num < 10; num++) { DLT_LOG_ID(con_exa2, DLT_LOG_INFO, DLT_EXA2_CON_EXA2_ID1, DLT_INT32(12345678), DLT_STRING("Hello world 1!")); DLT_LOG_ID(con_exa2, DLT_LOG_ERROR, DLT_EXA2_CON_EXA2_ID2, DLT_INT32(87654321), DLT_STRING("Hello world 2!")); DLT_LOG_ID(con_exa2, DLT_LOG_WARN, DLT_EXA2_CON_EXA2_ID3, DLT_INT32(11223344), DLT_STRING("Hello world 3!")); ts.tv_sec = 0; ts.tv_nsec = 1000000; nanosleep(&ts, NULL); } DLT_UNREGISTER_CONTEXT(con_exa2); DLT_UNREGISTER_APP(); } dlt-daemon-2.18.10/examples/example2/example2.xml000066400000000000000000000176471446635226000215300ustar00rootroot00000000000000 projectEntry Entry unknown EXA2 Third Example CON First context PDU_1000_0 4 OTHER 0 PDU_1000_1 0 OTHER 0 PDU_1001_0 4 OTHER 0 PDU_1001_1 0 OTHER 0 PDU_1002_0 4 OTHER 0 PDU_1002_1 0 OTHER 0 ID_1000 4 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_INFO EXA2 CON /home/alex/workspace/ascgit/dlt-daemon/examples/example2/example2.c 64 ID_1001 4 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_ERROR EXA2 CON /home/alex/workspace/ascgit/dlt-daemon/examples/example2/example2.c 65 ID_1002 4 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_WARN EXA2 CON /home/alex/workspace/ascgit/dlt-daemon/examples/example2/example2.c 66 dlt-daemon-2.18.10/examples/example3/000077500000000000000000000000001446635226000172535ustar00rootroot00000000000000dlt-daemon-2.18.10/examples/example3/CMakeLists.txt000066400000000000000000000017571446635226000220250ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # # DLT example implementation # cmake_minimum_required( VERSION 2.6 ) project( automotive-dlt-example3 ) # # find dependency packages # find_package(PkgConfig) pkg_check_modules(DLT REQUIRED automotive-dlt) # # include directories # include_directories( ${DLT_INCLUDE_DIRS} ) # # build project # set(dlt_example3_SRCS example3.c) add_executable(dlt-example3 ${dlt_example3_SRCS}) target_link_libraries(dlt-example3 ${DLT_LIBRARIES}) set_target_properties(dlt-example3 PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-example3 RUNTIME DESTINATION bin COMPONENT base) dlt-daemon-2.18.10/examples/example3/dlt_id.h000066400000000000000000000011621446635226000206630ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /* generated file, do not edit */ #ifndef DLT_ID_H #define DLT_ID_H #define DLT_EXA3_CON_EXA3_ID1 1000 #define DLT_EXA3_CON_EXA3_ID2 1001 #define DLT_EXA3_CON_EXA3_ID3 1002 #endif /* DLT_ID_H */ dlt-daemon-2.18.10/examples/example3/example3.c000066400000000000000000000060511446635226000211370ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file example3.c */ /******************************************************************************* ** ** ** SRC-MODULE: example3.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include #include "dlt_id.h" DLT_DECLARE_CONTEXT(con_exa3); int main() { int num; struct timespec ts; DLT_REGISTER_APP("EXA3", "Third Example"); DLT_REGISTER_CONTEXT(con_exa3, "CON", "First context"); DLT_NONVERBOSE_MODE(); for (num = 0; num < 10; num++) { DLT_LOG_ID(con_exa3, DLT_LOG_INFO, DLT_EXA3_CON_EXA3_ID1, DLT_INT32(12345678), DLT_CSTRING("Hello world 1!")); DLT_LOG_ID(con_exa3, DLT_LOG_ERROR, DLT_EXA3_CON_EXA3_ID2, DLT_INT32(87654321), DLT_CSTRING("Hello world 2!")); DLT_LOG_ID(con_exa3, DLT_LOG_WARN, DLT_EXA3_CON_EXA3_ID3, DLT_INT32(11223344), DLT_CSTRING("Hello world 3!")); ts.tv_sec = 0; ts.tv_nsec = 1000000; nanosleep(&ts, NULL); } DLT_UNREGISTER_CONTEXT(con_exa3); DLT_UNREGISTER_APP(); } dlt-daemon-2.18.10/examples/example3/example3.xml000066400000000000000000000162551446635226000215240ustar00rootroot00000000000000 projectEntry Entry unknown EXA3 Third Example CON First context PDU_1000_0 4 OTHER 0 PDU_1000_1 Hello world 1! 0 OTHER PDU_1001_0 4 OTHER 0 PDU_1001_1 Hello world 2! 0 OTHER PDU_1002_0 4 OTHER 0 PDU_1002_1 Hello world 3! 0 OTHER ID_1000 4 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_INFO EXA3 CON /home/alex/workspace/ascgit/dlt-daemon/examples/example3/example3.c 64 ID_1001 4 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_ERROR EXA3 CON /home/alex/workspace/ascgit/dlt-daemon/examples/example3/example3.c 65 ID_1002 4 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_WARN EXA3 CON /home/alex/workspace/ascgit/dlt-daemon/examples/example3/example3.c 66 dlt-daemon-2.18.10/examples/example4/000077500000000000000000000000001446635226000172545ustar00rootroot00000000000000dlt-daemon-2.18.10/examples/example4/CMakeLists.txt000066400000000000000000000020451446635226000220150ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### # # DLT example implementation # cmake_minimum_required( VERSION 2.6 ) project( automotive-dlt-example4 ) # # set prefix # set( CMAKE_INSTALL_PREFIX "/usr" ) # # find dependency packages # find_package(PkgConfig) pkg_check_modules(DLT REQUIRED automotive-dlt) # # include directories # include_directories( ${DLT_INCLUDE_DIRS} ) # # build project # set(dlt_example4_SRCS example4.c) add_executable(dlt-example4 ${dlt_example4_SRCS}) target_link_libraries(dlt-example4 ${DLT_LIBRARIES}) set_target_properties(dlt-example4 PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-example4 RUNTIME DESTINATION bin COMPONENT base) dlt-daemon-2.18.10/examples/example4/example4.c000066400000000000000000000077731446635226000211550ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file example4.c */ /******************************************************************************* ** ** ** SRC-MODULE: example4.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include DLT_DECLARE_CONTEXT(con_exa1); int main() { unsigned char buffer[256]; int num; struct timespec ts; DLT_REGISTER_APP("EXA4", "Fourth Example"); DLT_REGISTER_CONTEXT(con_exa1, "CON", "First context"); for (num = 0; num < 256; num++) buffer[num] = num; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_RAW")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_RAW(buffer, 256)); uint8_t uint8data = 0x2a; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_UINT8")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_UINT8(uint8data)); uint8_t hex8data = 0x1a; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_HEX8")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_HEX8(hex8data)); uint16_t hex16data = 0x1ad3; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_HEX16")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_HEX16(hex16data)); uint32_t hex32data = 0x1abcd3e4; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_HEX32")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_HEX32(hex32data)); uint64_t hex64data = 0x17b4ddcf34eabb2a; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_HEX64")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_HEX64(hex64data)); uint8_t bin8data = 0xe2; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_BIN8")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_BIN8(bin8data)); bin8data = 0x01; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_BIN8")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_BIN8(bin8data)); uint16_t bin16data = 0x1234; DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_STRING("DLT_BIN16")); DLT_LOG(con_exa1, DLT_LOG_INFO, DLT_BIN16(bin16data)); ts.tv_sec = 0; ts.tv_nsec = 1000000; nanosleep(&ts, NULL); DLT_UNREGISTER_CONTEXT(con_exa1); DLT_UNREGISTER_APP(); } dlt-daemon-2.18.10/googletest/000077500000000000000000000000001446635226000160735ustar00rootroot00000000000000dlt-daemon-2.18.10/include/000077500000000000000000000000001446635226000153425ustar00rootroot00000000000000dlt-daemon-2.18.10/include/CMakeLists.txt000066400000000000000000000007031446635226000201020ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### add_subdirectory( dlt ) dlt-daemon-2.18.10/include/dlt/000077500000000000000000000000001446635226000161255ustar00rootroot00000000000000dlt-daemon-2.18.10/include/dlt/CMakeLists.txt000066400000000000000000000021351446635226000206660ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if(WITH_DLT_DISABLE_MACRO) set(DLT_DISABLE_MACRO 1) endif() configure_file(dlt_user.h.in dlt_user.h) set(HEADER_LIST dlt.h dlt_user_macros.h dlt_client.h dlt_protocol.h dlt_common.h dlt_types.h dlt_shm.h dlt_offline_trace.h dlt_filetransfer.h dlt_common_api.h dlt_multiple_files.h ${CMAKE_CURRENT_BINARY_DIR}/dlt_version.h ${CMAKE_CURRENT_BINARY_DIR}/dlt_user.h) if(WITH_DLT_DISABLE_MACRO) list(REMOVE_ITEM HEADER_LIST dlt_user_macros.h) endif() if(WITH_DLT_CXX11_EXT) list(APPEND HEADER_LIST dlt_cpp_extension.hpp) endif() install(FILES ${HEADER_LIST} DESTINATION include/dlt COMPONENT devel) dlt-daemon-2.18.10/include/dlt/dlt-logd-converter.hpp000066400000000000000000000217731446635226000223630ustar00rootroot00000000000000/** * Copyright (C) 2019-2022 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * dlt-logd-converter : Retrieve log entries from logd and forward them to DLT. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \Author Luu Quang Minh ADIT 2022 * * \file: dlt-logd-converter.hpp * For further information see http://www.covesa.org/. **/ /******************************************************************************* ** ** ** SRC-MODULE: dlt-logd-converter.hpp ** ** ** ** TARGET : ANDROID ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Minh.LuuQuang@vn.bosch.com ** ** ** ** PURPOSE : Header for DLT logd converter ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #ifndef DLT_LOGD_CONVERTER_HPP #define DLT_LOGD_CONVERTER_HPP #pragma once #include #include #include #include #include #ifndef DLT_UNIT_TESTS # include # include # include #endif #include #include #include #include #include using namespace std; /* MACRO */ #define CONFIGURATION_FILE_DIR "/vendor/etc/dlt-logd-converter.conf" #define JSON_FILE_DIR "/vendor/etc/dlt-logdctxt.json" #define MAX_LINE 1024 #define DLT_FAIL_TO_GET_LOG_MSG 0 typedef struct { char *appID; char *ctxID; char *json_file_dir; char *default_ctxID; char *conf_file_dir; } dlt_logd_configuration; #ifdef DLT_UNIT_TESTS #define LOGGER_LOGD (1U << 31) #define READ_ONLY 0x0000 #define NS_PER_SEC 1000000000ULL #define LOGGER_ENTRY_MAX_LEN (5 * 1024) struct logger_list { int mode; unsigned int tail; pid_t pid; uint32_t log_mask; int signal; char dummy_data[96]; }; typedef enum { LOG_ID_MIN = 0, /** The main log buffer. This is the only log buffer available to apps. */ LOG_ID_MAIN = 0, /** The radio log buffer. */ LOG_ID_RADIO = 1, /** The event log buffer. */ LOG_ID_EVENTS = 2, /** The system log buffer. */ LOG_ID_SYSTEM = 3, /** The crash log buffer. */ LOG_ID_CRASH = 4, /** The statistics log buffer. */ LOG_ID_STATS = 5, /** The security log buffer. */ LOG_ID_SECURITY = 6, /** The kernel log buffer. */ LOG_ID_KERNEL = 7, LOG_ID_MAX, /** Let the logging function choose the best log target. */ LOG_ID_DEFAULT = 0x7FFFFFFF } log_id_t; typedef enum { /** For internal use only. */ ANDROID_LOG_UNKNOWN = 0, /** The default priority, for internal use only. */ ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ /** Verbose logging. Should typically be disabled for a release apk. */ ANDROID_LOG_VERBOSE, /** Debug logging. Should typically be disabled for a release apk. */ ANDROID_LOG_DEBUG, /** Informational logging. Should typically be disabled for a release apk. */ ANDROID_LOG_INFO, /** Warning logging. For use with recoverable failures. */ ANDROID_LOG_WARN, /** Error logging. For use with unrecoverable failures. */ ANDROID_LOG_ERROR, /** Fatal logging. For use when aborting. */ ANDROID_LOG_FATAL, /** For internal use only. */ ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ } android_LogPriority; struct logger_entry { uint16_t len; /* length of the payload */ uint16_t hdr_size; /* sizeof(struct logger_entry) */ int32_t pid; /* generating process's pid */ uint32_t tid; /* generating process's tid */ uint32_t sec; /* seconds since Epoch */ uint32_t nsec; /* nanoseconds */ uint32_t lid; /* log id of the payload, bottom 4 bits currently */ uint32_t uid; /* generating process's uid */ }; struct log_msg { union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; struct logger_entry entry; } __attribute__((aligned(4))); uint64_t nsec() const { return static_cast(entry.sec) * NS_PER_SEC + entry.nsec; } log_id_t id() { return static_cast(entry.lid); } char* msg() { unsigned short hdr_size = entry.hdr_size; if (hdr_size >= sizeof(struct log_msg) - sizeof(entry)) { return nullptr; } return reinterpret_cast(buf) + hdr_size; } unsigned int len() { return entry.hdr_size + entry.len; } }; struct dlt_log_container { DltContext *ctx; DltLogLevelType log_level; uint32_t ts; const char *tag; const char *message; }; /* Android API faked method for unit test */ string t_load_json_file(); struct logger *t_android_logger_open(logger_list *logger_list,log_id_t log_id); struct logger_list *t_android_logger_list_alloc(int mode, unsigned int tail, pid_t pid); int t_android_logger_list_read(logger_list *logger_list, log_msg *t_log_msg); #endif /** * Prints manual page for instruction * @param prog_name binary name from stdin * @return void */ DLT_STATIC void usage(char *prog_name); /** * Initializes configuration to default values * @return scenario statement */ DLT_STATIC int init_configuration(); /** * Reads command line options and set the values in provided structure * @return scenario statement */ DLT_STATIC int read_command_line(int argc, char *argv[]); /** * Reads options from the configuration file * @param file_name configuration file name/path * @return scenario statement */ DLT_STATIC int load_configuration_file(const char *file_name); /** * Frees the memory allocated for configuration values. * @return void */ DLT_STATIC void clean_mem(); /** * Parses data from a JSON file into an internal data * structure and do registration with the new ctxID. * @return void */ DLT_STATIC void json_parser(); /** * Doing tag matching for pairs in JSON unordered map. * @param tag tag of the application that needs new context ID * @return pointer to DLT context mapped with the corresponding tag */ DLT_STATIC DltContext* find_tag_in_json(const char *tag); /** * Doing initialization for logger. * @param logger_list pointer to a logger list struct * @param log_id identifies a specific log buffer * @return pointer to a logger object logging messages for applications */ DLT_STATIC struct logger *init_logger(struct logger_list *logger_list, log_id_t log_id); /** * Doing initialization for logger list. * @param skip_binary_buffers boolean value to use event buffers * @return pointer to a logger list struct */ DLT_STATIC struct logger_list *init_logger_list(bool skip_binary_buffers); /** * Getting a context from an android log message. * @param log_msg struct contains android log data including log messages * @return pointer to DLT context mapped with the corresponding tag */ DLT_STATIC DltContext *get_log_context_from_log_msg(struct log_msg *log_msg); /** * Getting timestamp from an android log message. * @param log_msg struct contains android log data including log messages * @return timestamp of messages from a logger entry */ DLT_STATIC uint32_t get_timestamp_from_log_msg(struct log_msg *log_msg); /** * Getting log level from an android log message. * @param log_msg struct contains android log data including log messages * @return DLT log level */ DLT_STATIC DltLogLevelType get_log_level_from_log_msg(struct log_msg *log_msg); /** * Handling received signal. * @param signal received signal to handle * @return void */ void signal_handler(int signal); /** * Continuously converting android logs to dlt logs. * @param logger_list pointer to a logger list struct * @return scenario statement */ DLT_STATIC int logd_parser_loop(struct logger_list *logger_list); #endif /* DLT_LOGD_CONVERTER_HPP */ dlt-daemon-2.18.10/include/dlt/dlt.h000066400000000000000000000067211446635226000170670ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #ifndef DLT_H #define DLT_H #include "dlt_common.h" #include "dlt_user.h" #endif /* DLT_H */ dlt-daemon-2.18.10/include/dlt/dlt_client.h000066400000000000000000000321421446635226000204210ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_client.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_client.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision$ * $LastChangedDate$ * $LastChangedBy$ */ #ifndef DLT_CLIENT_H # define DLT_CLIENT_H /** * \defgroup clientapi DLT Client API * \addtogroup clientapi \{ */ # include "dlt_types.h" # include "dlt_common.h" #include typedef enum { DLT_CLIENT_MODE_UNDEFINED = -1, DLT_CLIENT_MODE_TCP, DLT_CLIENT_MODE_SERIAL, DLT_CLIENT_MODE_UNIX, DLT_CLIENT_MODE_UDP_MULTICAST } DltClientMode; typedef struct { DltReceiver receiver; /**< receiver pointer to dlt receiver structure */ int sock; /**< sock Connection handle/socket */ char *servIP; /**< servIP IP adress/Hostname of interface */ char *hostip; /**< hostip IP address of UDP host receiver interface */ int port; /**< Port for TCP connections (optional) */ char *serialDevice; /**< serialDevice Devicename of serial device */ char *socketPath; /**< socketPath Unix socket path */ char ecuid[4]; /**< ECUiD */ speed_t baudrate; /**< baudrate Baudrate of serial interface, as speed_t */ DltClientMode mode; /**< mode DltClientMode */ int send_serial_header; /**< (Boolean) Send DLT messages with serial header */ int resync_serial_header; /**< (Boolean) Resync to serial header on all connection */ } DltClient; # ifdef __cplusplus extern "C" { # endif void dlt_client_register_message_callback(int (*registerd_callback)(DltMessage *message, void *data)); void dlt_client_register_fetch_next_message_callback(bool (*registerd_callback)(void *data)); /** * Initialising dlt client structure with a specific port * @param client pointer to dlt client structure * @param port The port for the tcp connection * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_client_init_port(DltClient *client, int port, int verbose); /** * Initialising dlt client structure * @param client pointer to dlt client structure * @param verbose if set to true verbose information is printed out. * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_init(DltClient *client, int verbose); /** * Connect to dlt daemon using the information from the dlt client structure * @param client pointer to dlt client structure * @param verbose if set to true verbose information is printed out. * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_connect(DltClient *client, int verbose); /** * Cleanup dlt client structure * @param client pointer to dlt client structure * @param verbose if set to true verbose information is printed out. * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_cleanup(DltClient *client, int verbose); /** * Main Loop of dlt client application * @param client pointer to dlt client structure * @param data pointer to data to be provided to the main loop * @param verbose if set to true verbose information is printed out. * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_main_loop(DltClient *client, void *data, int verbose); /** * Send a message to the daemon through the socket. * @param client pointer to dlt client structure. * @param msg The message to be send in DLT format. * @return Value from DltReturnValue enum. */ DltReturnValue dlt_client_send_message_to_socket(DltClient *client, DltMessage *msg); /** * Send ancontrol message to the dlt daemon * @param client pointer to dlt client structure * @param apid application id * @param ctid context id * @param payload Buffer filled with control message data * @param size Size of control message data * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_ctrl_msg(DltClient *client, char *apid, char *ctid, uint8_t *payload, uint32_t size); /** * Send an injection message to the dlt daemon * @param client pointer to dlt client structure * @param apid application id * @param ctid context id * @param serviceID service id * @param buffer Buffer filled with injection message data * @param size Size of injection data within buffer * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_inject_msg(DltClient *client, char *apid, char *ctid, uint32_t serviceID, uint8_t *buffer, uint32_t size); /** * Send an set log level message to the dlt daemon * @param client pointer to dlt client structure * @param apid application id * @param ctid context id * @param logLevel Log Level * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_log_level(DltClient *client, char *apid, char *ctid, uint8_t logLevel); /** * Send an request to get log info message to the dlt daemon * @param client pointer to dlt client structure * @return negative value if there was an error */ int dlt_client_get_log_info(DltClient *client); /** * Send an request to get default log level to the dlt daemon * @param client pointer to dlt client structure * @return negative value if there was an error */ DltReturnValue dlt_client_get_default_log_level(DltClient *client); /** * Send an request to get software version to the dlt daemon * @param client pointer to dlt client structure * @return negative value if there was an error */ int dlt_client_get_software_version(DltClient *client); /** * Initialise get log info structure * @return void */ void dlt_getloginfo_init(void); /** * To free the memory allocated for app description in get log info * @return void */ void dlt_getloginfo_free(void); /** * Send a set trace status message to the dlt daemon * @param client pointer to dlt client structure * @param apid application id * @param ctid context id * @param traceStatus Default Trace Status * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_trace_status(DltClient *client, char *apid, char *ctid, uint8_t traceStatus); /** * Send the default log level to the dlt daemon * @param client pointer to dlt client structure * @param defaultLogLevel Default Log Level * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_default_log_level(DltClient *client, uint8_t defaultLogLevel); /** * Send the log level to all contexts registered with dlt daemon * @param client pointer to dlt client structure * @param LogLevel Log Level to be set * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_all_log_level(DltClient *client, uint8_t LogLevel); /** * Send the default trace status to the dlt daemon * @param client pointer to dlt client structure * @param defaultTraceStatus Default Trace Status * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_default_trace_status(DltClient *client, uint8_t defaultTraceStatus); /** * Send the trace status to all contexts registered with dlt daemon * @param client pointer to dlt client structure * @param traceStatus trace status to be set * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_all_trace_status(DltClient *client, uint8_t traceStatus); /** * Send the timing pakets status to the dlt daemon * @param client pointer to dlt client structure * @param timingPakets Timing pakets enabled * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_timing_pakets(DltClient *client, uint8_t timingPakets); /** * Send the store config command to the dlt daemon * @param client pointer to dlt client structure * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_store_config(DltClient *client); /** * Send the reset to factory default command to the dlt daemon * @param client pointer to dlt client structure * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_send_reset_to_factory_default(DltClient *client); /** * Set baudrate within dlt client structure * @param client pointer to dlt client structure * @param baudrate Baudrate * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_setbaudrate(DltClient *client, int baudrate); /** * Set mode within dlt client structure * @param client pointer to dlt client structure * @param mode DltClientMode * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_set_mode(DltClient *client, DltClientMode mode); /** * Set server ip * @param client pointer to dlt client structure * @param ipaddr pointer to command line argument * @return negative value if there was an error */ int dlt_client_set_server_ip(DltClient *client, char *ipaddr); /** * Set server UDP host receiver interface address * @param client pointer to dlt client structure * @param hostip pointer to multicast group address * @return negative value if there was an error */ int dlt_client_set_host_if_address(DltClient *client, char *hostip); /** * Set serial device * @param client pointer to dlt client structure * @param serial_device pointer to command line argument * @return negative value if there was an error */ int dlt_client_set_serial_device(DltClient *client, char *serial_device); /** * Set socket path * @param client pointer to dlt client structure * @param socket_path pointer to socket path string * @return negative value if there was an error */ int dlt_client_set_socket_path(DltClient *client, char *socket_path); /** * Parse GET_LOG_INFO response text * @param resp GET_LOG_INFO response * @param resp_text response text represented by ASCII * @return Value from DltReturnValue enum */ DltReturnValue dlt_client_parse_get_log_info_resp_text(DltServiceGetLogInfoResponse *resp, char *resp_text); /** * Free memory allocated for get log info message * @param resp response * @return 0 on success, -1 otherwise */ int dlt_client_cleanup_get_log_info(DltServiceGetLogInfoResponse *resp); # ifdef __cplusplus } # endif /** \} */ #endif /* DLT_CLIENT_H */ dlt-daemon-2.18.10/include/dlt/dlt_common.h000066400000000000000000001773671446635226000204560ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_common.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_common.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #ifndef DLT_COMMON_H # define DLT_COMMON_H /** * \defgroup commonapi DLT Common API * \addtogroup commonapi \{ */ # include # include # include # ifdef __linux__ # include # include # else # include # endif # if !defined(_MSC_VER) # include # include # endif # if defined(__GNUC__) # define PURE_FUNCTION __attribute__((pure)) # define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, a, b))) # else # define PURE_FUNCTION /* nothing */ # define PRINTF_FORMAT(a,b) /* nothing */ # endif # if !defined (__WIN32__) && !defined(_MSC_VER) # include # endif # include "dlt_types.h" # include "dlt_protocol.h" # define DLT_PACKED __attribute__((aligned(1), packed)) # if defined (__MSDOS__) || defined (_MSC_VER) /* set instead /Zp8 flag in Visual C++ configuration */ # undef DLT_PACKED # define DLT_PACKED # endif /* * Macros to swap the byte order. */ # define DLT_SWAP_64(value) ((((uint64_t)DLT_SWAP_32((value) & 0xffffffffull)) << 32) | (DLT_SWAP_32((value) >> 32))) # define DLT_SWAP_16(value) ((((value) >> 8) & 0xff) | (((value) << 8) & 0xff00)) # define DLT_SWAP_32(value) ((((value) >> 24) & 0xff) | (((value) << 8) & 0xff0000) | (((value) >> 8) & 0xff00) | \ (((value) << 24) & 0xff000000)) /* Set Big Endian and Little Endian to a initial value, if not defined */ # if !defined __USE_BSD # ifndef LITTLE_ENDIAN # define LITTLE_ENDIAN 1234 # endif # ifndef BIG_ENDIAN # define BIG_ENDIAN 4321 # endif # endif /* __USE_BSD */ /* If byte order is not defined, default to little endian */ # if !defined __USE_BSD # ifndef BYTE_ORDER # define BYTE_ORDER LITTLE_ENDIAN # endif # endif /* __USE_BSD */ /* Check for byte-order */ # if (BYTE_ORDER == BIG_ENDIAN) /* #warning "Big Endian Architecture!" */ # define DLT_HTOBE_16(x) ((x)) # define DLT_HTOLE_16(x) DLT_SWAP_16((x)) # define DLT_BETOH_16(x) ((x)) # define DLT_LETOH_16(x) DLT_SWAP_16((x)) # define DLT_HTOBE_32(x) ((x)) # define DLT_HTOLE_32(x) DLT_SWAP_32((x)) # define DLT_BETOH_32(x) ((x)) # define DLT_LETOH_32(x) DLT_SWAP_32((x)) # define DLT_HTOBE_64(x) ((x)) # define DLT_HTOLE_64(x) DLT_SWAP_64((x)) # define DLT_BETOH_64(x) ((x)) # define DLT_LETOH_64(x) DLT_SWAP_64((x)) # else /* #warning "Litte Endian Architecture!" */ # define DLT_HTOBE_16(x) DLT_SWAP_16((x)) # define DLT_HTOLE_16(x) ((x)) # define DLT_BETOH_16(x) DLT_SWAP_16((x)) # define DLT_LETOH_16(x) ((x)) # define DLT_HTOBE_32(x) DLT_SWAP_32((x)) # define DLT_HTOLE_32(x) ((x)) # define DLT_BETOH_32(x) DLT_SWAP_32((x)) # define DLT_LETOH_32(x) ((x)) # define DLT_HTOBE_64(x) DLT_SWAP_64((x)) # define DLT_HTOLE_64(x) ((x)) # define DLT_BETOH_64(x) DLT_SWAP_64((x)) # define DLT_LETOH_64(x) ((x)) # endif # define DLT_ENDIAN_GET_16(htyp, x) ((((htyp) & DLT_HTYP_MSBF) > 0) ? DLT_BETOH_16(x) : DLT_LETOH_16(x)) # define DLT_ENDIAN_GET_32(htyp, x) ((((htyp) & DLT_HTYP_MSBF) > 0) ? DLT_BETOH_32(x) : DLT_LETOH_32(x)) # define DLT_ENDIAN_GET_64(htyp, x) ((((htyp) & DLT_HTYP_MSBF) > 0) ? DLT_BETOH_64(x) : DLT_LETOH_64(x)) # if defined (__WIN32__) || defined (_MSC_VER) # define LOG_EMERG 0 # define LOG_ALERT 1 # define LOG_CRIT 2 # define LOG_ERR 3 # define LOG_WARNING 4 # define LOG_NOTICE 5 # define LOG_INFO 6 # define LOG_DEBUG 7 # define LOG_PID 0x01 # define LOG_DAEMON (3 << 3) # endif typedef enum { DLT_LOG_TO_CONSOLE = 0, DLT_LOG_TO_SYSLOG = 1, DLT_LOG_TO_FILE = 2, DLT_LOG_TO_STDERR = 3, DLT_LOG_DROPPED = 4 } DltLoggingMode; /** * The standard TCP Port used for DLT daemon, can be overwritten via -p \ when starting dlt-daemon */ # define DLT_DAEMON_TCP_PORT 3490 /* Initial value for file descriptor */ # define DLT_FD_INIT -1 /* Minimum value for a file descriptor except the POSIX Standards: stdin=0, stdout=1, stderr=2 */ # define DLT_FD_MINIMUM 3 /** * The size of a DLT ID */ # define DLT_ID_SIZE 4 # define DLT_SIZE_WEID DLT_ID_SIZE # define DLT_SIZE_WSID (sizeof(uint32_t)) # define DLT_SIZE_WTMS (sizeof(uint32_t)) /* Size of buffer for text output */ #define DLT_CONVERT_TEXTBUFSIZE 10024 /** * Definitions for GET_LOG_INFO */ # define DLT_GET_LOG_INFO_HEADER 18 /*Get log info header size in response text */ # define GET_LOG_INFO_LENGTH 13 # define SERVICE_OPT_LENGTH 3 /** * Get the size of extra header parameters, depends on htyp. */ # define DLT_STANDARD_HEADER_EXTRA_SIZE(htyp) ((DLT_IS_HTYP_WEID(htyp) ? DLT_SIZE_WEID : 0) + \ (DLT_IS_HTYP_WSID(htyp) ? DLT_SIZE_WSID : 0) + \ (DLT_IS_HTYP_WTMS(htyp) ? DLT_SIZE_WTMS : 0)) # if defined (__MSDOS__) || defined (_MSC_VER) # define __func__ __FUNCTION__ # endif # define PRINT_FUNCTION_VERBOSE(_verbose) \ if (_verbose) \ dlt_vlog(LOG_INFO, "%s()\n", __func__) # ifndef NULL # define NULL (char *)0 # endif # define DLT_MSG_IS_CONTROL(MSG) ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (DLT_GET_MSIN_MSTP((MSG)->extendedheader->msin) == DLT_TYPE_CONTROL)) # define DLT_MSG_IS_CONTROL_REQUEST(MSG) ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (DLT_GET_MSIN_MSTP((MSG)->extendedheader->msin) == DLT_TYPE_CONTROL) && \ (DLT_GET_MSIN_MTIN((MSG)->extendedheader->msin) == DLT_CONTROL_REQUEST)) # define DLT_MSG_IS_CONTROL_RESPONSE(MSG) ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (DLT_GET_MSIN_MSTP((MSG)->extendedheader->msin) == DLT_TYPE_CONTROL) && \ (DLT_GET_MSIN_MTIN((MSG)->extendedheader->msin) == DLT_CONTROL_RESPONSE)) # define DLT_MSG_IS_CONTROL_TIME(MSG) ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (DLT_GET_MSIN_MSTP((MSG)->extendedheader->msin) == DLT_TYPE_CONTROL) && \ (DLT_GET_MSIN_MTIN((MSG)->extendedheader->msin) == DLT_CONTROL_TIME)) # define DLT_MSG_IS_NW_TRACE(MSG) ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (DLT_GET_MSIN_MSTP((MSG)->extendedheader->msin) == DLT_TYPE_NW_TRACE)) # define DLT_MSG_IS_TRACE_MOST(MSG) ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (DLT_GET_MSIN_MSTP((MSG)->extendedheader->msin) == DLT_TYPE_NW_TRACE) && \ (DLT_GET_MSIN_MTIN((MSG)->extendedheader->msin) == DLT_NW_TRACE_MOST)) # define DLT_MSG_IS_NONVERBOSE(MSG) (!(DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) || \ ((DLT_IS_HTYP_UEH((MSG)->standardheader->htyp)) && \ (!(DLT_IS_MSIN_VERB((MSG)->extendedheader->msin))))) /* * * Definitions of DLT message buffer overflow */ # define DLT_MESSAGE_BUFFER_NO_OVERFLOW 0x00/**< Buffer overflow has not occured */ # define DLT_MESSAGE_BUFFER_OVERFLOW 0x01/**< Buffer overflow has occured */ /* * Definition of DLT output variants */ # define DLT_OUTPUT_HEX 1 # define DLT_OUTPUT_ASCII 2 # define DLT_OUTPUT_MIXED_FOR_PLAIN 3 # define DLT_OUTPUT_MIXED_FOR_HTML 4 # define DLT_OUTPUT_ASCII_LIMITED 5 # define DLT_FILTER_MAX 30 /**< Maximum number of filters */ # define DLT_MSG_READ_VALUE(dst, src, length, type) \ do { \ if ((length < 0) || ((length) < ((int32_t)sizeof(type)))) \ { length = -1; } \ else \ { dst = *((type *)src); src += sizeof(type); length -= sizeof(type); } \ } while(false) # define DLT_MSG_READ_ID(dst, src, length) \ do { \ if ((length < 0) || ((length) < DLT_ID_SIZE)) \ { length = -1; } \ else \ { memcpy(dst, src, DLT_ID_SIZE); src += DLT_ID_SIZE; length -= DLT_ID_SIZE; } \ } while(false) # define DLT_MSG_READ_STRING(dst, src, maxlength, dstlength, length) \ do { \ if ((maxlength < 0) || (length <= 0) || (dstlength < length) || (maxlength < length)) \ { \ maxlength = -1; \ } \ else \ { \ memcpy(dst, src, length); \ dlt_clean_string(dst, length); \ dst[length] = 0; \ src += length; \ maxlength -= length; \ } \ } while(false) # define DLT_MSG_READ_NULL(src, maxlength, length) \ do { \ if (((maxlength) < 0) || ((length) < 0) || ((maxlength) < (length))) \ { length = -1; } \ else \ { src += length; maxlength -= length; } \ } while(false) # define DLT_HEADER_SHOW_NONE 0x0000 # define DLT_HEADER_SHOW_TIME 0x0001 # define DLT_HEADER_SHOW_TMSTP 0x0002 # define DLT_HEADER_SHOW_MSGCNT 0x0004 # define DLT_HEADER_SHOW_ECUID 0x0008 # define DLT_HEADER_SHOW_APID 0x0010 # define DLT_HEADER_SHOW_CTID 0x0020 # define DLT_HEADER_SHOW_MSGTYPE 0x0040 # define DLT_HEADER_SHOW_MSGSUBTYPE 0x0080 # define DLT_HEADER_SHOW_VNVSTATUS 0x0100 # define DLT_HEADER_SHOW_NOARG 0x0200 # define DLT_HEADER_SHOW_ALL 0xFFFF /* dlt_receiver_check_and_get flags */ # define DLT_RCV_NONE 0 # define DLT_RCV_SKIP_HEADER (1 << 0) # define DLT_RCV_REMOVE (1 << 1) /** * Maximal length of path in DLT * DLT limits the path length and does not do anything else to determine * the actual value, because the least that is supported on any system * that DLT runs on is 1024 bytes. */ # define DLT_PATH_MAX 1024 /** * Maximal length of mounted path */ # define DLT_MOUNT_PATH_MAX 1024 /** * Maximal length of an entry */ # define DLT_ENTRY_MAX 100 /** * Maximal IPC path len */ # define DLT_IPC_PATH_MAX 100 /** * Maximal receiver buffer size for application messages */ # define DLT_RECEIVE_BUFSIZE 65535 /** * Maximal line length */ # define DLT_LINE_LEN 1024 /** * Macros for network trace */ #define DLT_TRACE_NW_TRUNCATED "NWTR" #define DLT_TRACE_NW_START "NWST" #define DLT_TRACE_NW_SEGMENT "NWCH" #define DLT_TRACE_NW_END "NWEN" /** * Provision to test static function */ # ifndef DLT_UNIT_TESTS # define DLT_STATIC static # else # define DLT_STATIC # endif /** * Type to specify whether received data is from socket or file/fifo */ typedef enum { DLT_RECEIVE_SOCKET, DLT_RECEIVE_UDP_SOCKET, DLT_RECEIVE_FD } DltReceiverType; /** * The definition of the serial header containing the characters "DLS" + 0x01. */ extern const char dltSerialHeader[DLT_ID_SIZE]; /** * The definition of the serial header containing the characters "DLS" + 0x01 as char. */ extern char dltSerialHeaderChar[DLT_ID_SIZE]; #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC /** * The common base-path of the dlt-daemon-fifo and application-generated fifos */ extern char dltFifoBaseDir[DLT_PATH_MAX]; #endif #ifdef DLT_SHM_ENABLE /** * The common name of the dlt-daemon and application share memory */ extern char dltShmName[NAME_MAX + 1]; #endif /** * The type of a DLT ID (context id, application id, etc.) */ typedef char ID4[DLT_ID_SIZE]; /** * The structure of the DLT file storage header. This header is used before each stored DLT message. */ typedef struct { char pattern[DLT_ID_SIZE]; /**< This pattern should be DLT0x01 */ uint32_t seconds; /**< seconds since 1.1.1970 */ int32_t microseconds; /**< Microseconds */ char ecu[DLT_ID_SIZE]; /**< The ECU id is added, if it is not already in the DLT message itself */ } DLT_PACKED DltStorageHeader; /** * The structure of the DLT standard header. This header is used in each DLT message. */ typedef struct { uint8_t htyp; /**< This parameter contains several informations, see definitions below */ uint8_t mcnt; /**< The message counter is increased with each sent DLT message */ uint16_t len; /**< Length of the complete message, without storage header */ } DLT_PACKED DltStandardHeader; /** * The structure of the DLT extra header parameters. Each parameter is sent only if enabled in htyp. */ typedef struct { char ecu[DLT_ID_SIZE]; /**< ECU id */ uint32_t seid; /**< Session number */ uint32_t tmsp; /**< Timestamp since system start in 0.1 milliseconds */ } DLT_PACKED DltStandardHeaderExtra; /** * The structure of the DLT extended header. This header is only sent if enabled in htyp parameter. */ typedef struct { uint8_t msin; /**< messsage info */ uint8_t noar; /**< number of arguments */ char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ } DLT_PACKED DltExtendedHeader; /** * The structure to organise the DLT messages. * This structure is used by the corresponding functions. */ typedef struct sDltMessage { /* flags */ int8_t found_serialheader; /* offsets */ int32_t resync_offset; /* size parameters */ int32_t headersize; /**< size of complete header including storage header */ int32_t datasize; /**< size of complete payload */ /* buffer for current loaded message */ uint8_t headerbuffer[sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra) + sizeof(DltExtendedHeader)]; /**< buffer for loading complete header */ uint8_t *databuffer; /**< buffer for loading payload */ int32_t databuffersize; /* header values of current loaded message */ DltStorageHeader *storageheader; /**< pointer to storage header of current loaded header */ DltStandardHeader *standardheader; /**< pointer to standard header of current loaded header */ DltStandardHeaderExtra headerextra; /**< extra parameters of current loaded header */ DltExtendedHeader *extendedheader; /**< pointer to extended of current loaded header */ } DltMessage; /** * The structure of the DLT Service Get Log Info. */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t options; /**< type of request */ char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ char com[DLT_ID_SIZE]; /**< communication interface */ } DLT_PACKED DltServiceGetLogInfoRequest; typedef struct { uint32_t service_id; /**< service ID */ } DLT_PACKED DltServiceGetDefaultLogLevelRequest; /** * The structure of the DLT Service Get Log Info response. */ typedef struct { char context_id[DLT_ID_SIZE]; int16_t log_level; int16_t trace_status; uint16_t len_context_description; char *context_description; } ContextIDsInfoType; typedef struct { char app_id[DLT_ID_SIZE]; uint16_t count_context_ids; ContextIDsInfoType *context_id_info; /**< holds info about a specific con id */ uint16_t len_app_description; char *app_description; } AppIDsType; typedef struct { uint16_t count_app_ids; AppIDsType *app_ids; /**< holds info about a specific app id */ } LogInfoType; typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< type of request */ LogInfoType log_info_type; /**< log info type */ char com[DLT_ID_SIZE]; /**< communication interface */ } DltServiceGetLogInfoResponse; /** * The structure of the DLT Service Set Log Level. */ typedef struct { uint32_t service_id; /**< service ID */ char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ uint8_t log_level; /**< log level to be set */ char com[DLT_ID_SIZE]; /**< communication interface */ } DLT_PACKED DltServiceSetLogLevel; /** * The structure of the DLT Service Set Default Log Level. */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t log_level; /**< default log level to be set */ char com[DLT_ID_SIZE]; /**< communication interface */ } DLT_PACKED DltServiceSetDefaultLogLevel; /** * The structure of the DLT Service Set Verbose Mode */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t new_status; /**< new status to be set */ } DLT_PACKED DltServiceSetVerboseMode; /** * The structure of the DLT Service Set Communication Interface Status */ typedef struct { uint32_t service_id; /**< service ID */ char com[DLT_ID_SIZE]; /**< communication interface */ uint8_t new_status; /**< new status to be set */ } DLT_PACKED DltServiceSetCommunicationInterfaceStatus; /** * The structure of the DLT Service Set Communication Maximum Bandwidth */ typedef struct { uint32_t service_id; /**< service ID */ char com[DLT_ID_SIZE]; /**< communication interface */ uint32_t max_bandwidth; /**< maximum bandwith */ } DLT_PACKED DltServiceSetCommunicationMaximumBandwidth; typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ } DLT_PACKED DltServiceResponse; typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ uint8_t log_level; /**< log level */ } DLT_PACKED DltServiceGetDefaultLogLevelResponse; typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ uint8_t overflow; /**< overflow status */ uint32_t overflow_counter; /**< overflow counter */ } DLT_PACKED DltServiceMessageBufferOverflowResponse; typedef struct { uint32_t service_id; /**< service ID */ } DLT_PACKED DltServiceGetSoftwareVersion; typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ uint32_t length; /**< length of following payload */ char *payload; /**< payload */ } DLT_PACKED DltServiceGetSoftwareVersionResponse; /** * The structure of the DLT Service Unregister Context. */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ char comid[DLT_ID_SIZE]; /**< communication interface */ } DLT_PACKED DltServiceUnregisterContext; /** * The structure of the DLT Service Connection Info */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ uint8_t state; /**< new state */ char comid[DLT_ID_SIZE]; /**< communication interface */ } DLT_PACKED DltServiceConnectionInfo; /** * The structure of the DLT Service Timezone */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ int32_t timezone; /**< Timezone in seconds */ uint8_t isdst; /**< Is daylight saving time */ } DLT_PACKED DltServiceTimezone; /** * The structure of the DLT Service Marker */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< reponse status */ } DLT_PACKED DltServiceMarker; /*** * The structure of the DLT Service Offline Logstorage */ typedef struct { uint32_t service_id; /**< service ID */ char mount_point[DLT_MOUNT_PATH_MAX]; /**< storage device mount point */ uint8_t connection_type; /**< connection status of the connected device connected/disconnected */ char comid[DLT_ID_SIZE]; /**< communication interface */ } DLT_PACKED DltServiceOfflineLogstorage; typedef struct { uint32_t service_id; /**< service ID */ uint32_t connection_status; /**< connect/disconnect */ char node_id[DLT_ID_SIZE]; /**< passive node ID */ } DLT_PACKED DltServicePassiveNodeConnect; /** * The structure of DLT Service Passive Node Connection Status */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< response status */ uint32_t num_connections; /**< number of connections */ uint8_t connection_status[DLT_ENTRY_MAX]; /**< list of connection status */ char node_id[DLT_ENTRY_MAX]; /**< list of passive node IDs */ } DLT_PACKED DltServicePassiveNodeConnectionInfo; /** * Structure to store filter parameters. * ID are maximal four characters. Unused values are filled with zeros. * If every value as filter is valid, the id should be empty by having only zero values. */ typedef struct { char apid[DLT_FILTER_MAX][DLT_ID_SIZE]; /**< application id */ char ctid[DLT_FILTER_MAX][DLT_ID_SIZE]; /**< context id */ int log_level[DLT_FILTER_MAX]; /**< log level */ int32_t payload_max[DLT_FILTER_MAX]; /**< upper border for payload */ int32_t payload_min[DLT_FILTER_MAX]; /**< lower border for payload */ int counter; /**< number of filters */ } DltFilter; /** * The structure to organise the access to DLT files. * This structure is used by the corresponding functions. */ typedef struct sDltFile { /* file handle and index for fast access */ FILE *handle; /**< file handle of opened DLT file */ long *index; /**< file positions of all DLT messages for fast access to file, only filtered messages */ /* size parameters */ int32_t counter; /**< number of messages in DLT file with filter */ int32_t counter_total; /**< number of messages in DLT file without filter */ int32_t position; /**< current index to message parsed in DLT file starting at 0 */ uint64_t file_length; /**< length of the file */ uint64_t file_position; /**< current position in the file */ /* error counters */ int32_t error_messages; /**< number of incomplete DLT messages found during file parsing */ /* filter parameters */ DltFilter *filter; /**< pointer to filter list. Zero if no filter is set. */ int32_t filter_counter; /**< number of filter set */ /* current loaded message */ DltMessage msg; /**< pointer to message */ } DltFile; /** * The structure is used to organise the receiving of data * including buffer handling. * This structure is used by the corresponding functions. */ typedef struct { int32_t lastBytesRcvd; /**< bytes received in last receive call */ int32_t bytesRcvd; /**< received bytes */ int32_t totalBytesRcvd; /**< total number of received bytes */ char *buffer; /**< pointer to receiver buffer */ char *buf; /**< pointer to position within receiver buffer */ char *backup_buf; /** pointer to the buffer with partial messages if any **/ int fd; /**< connection handle */ DltReceiverType type; /**< type of connection handle */ int32_t buffersize; /**< size of receiver buffer */ struct sockaddr_in addr; /**< socket address information */ } DltReceiver; typedef struct { unsigned char *shm; /* pointer to beginning of shared memory */ unsigned int size; /* size of data area in shared memory */ unsigned char *mem; /* pointer to data area in shared memory */ uint32_t min_size; /**< Minimum size of buffer */ uint32_t max_size; /**< Maximum size of buffer */ uint32_t step_size; /**< Step size of buffer */ } DltBuffer; typedef struct { int write; int read; int count; } DltBufferHead; # define DLT_BUFFER_HEAD "SHM" typedef struct { char head[4]; unsigned char status; int size; } DltBufferBlockHead; # ifdef DLT_USE_IPv6 # define DLT_IP_SIZE (INET6_ADDRSTRLEN) # else # define DLT_IP_SIZE (INET_ADDRSTRLEN) # endif typedef struct DltBindAddress { char ip[DLT_IP_SIZE]; struct DltBindAddress *next; } DltBindAddress_t; # define DLT_MESSAGE_ERROR_OK 0 # define DLT_MESSAGE_ERROR_UNKNOWN -1 # define DLT_MESSAGE_ERROR_SIZE -2 # define DLT_MESSAGE_ERROR_CONTENT -3 # ifdef __cplusplus extern "C" { # endif /** * Helper function to print a byte array in hex. * @param ptr pointer to the byte array. * @param size number of bytes to be printed. */ void dlt_print_hex(uint8_t *ptr, int size); /** * Helper function to print a byte array in hex into a string. * @param text pointer to a ASCII string, in which the text is written * @param textlength maximal size of text buffer * @param ptr pointer to the byte array. * @param size number of bytes to be printed. * @return negative value if there was an error */ DltReturnValue dlt_print_hex_string(char *text, int textlength, uint8_t *ptr, int size); /** * Helper function to print a byte array in hex and ascii into a string. * @param text pointer to a ASCII string, in which the text is written * @param textlength maximal size of text buffer * @param ptr pointer to the byte array. * @param size number of bytes to be printed. * @param html output is html? 0 - false, 1 - true * @return negative value if there was an error */ DltReturnValue dlt_print_mixed_string(char *text, int textlength, uint8_t *ptr, int size, int html); /** * Helper function to print a byte array in ascii into a string. * @param text pointer to a ASCII string, in which the text is written * @param textlength maximal size of text buffer * @param ptr pointer to the byte array. * @param size number of bytes to be printed. * @return negative value if there was an error */ DltReturnValue dlt_print_char_string(char **text, int textlength, uint8_t *ptr, int size); /** * Helper function to determine a bounded length of a string. * This function returns zero if @a str is a null pointer, * and it returns @a maxsize if the null character was not found in the first @a maxsize bytes of @a str. * This is a re-implementation of C11's strnlen_s, which we cannot yet assume to be available. * @param str pointer to string whose length is to be determined * @param maxsize maximal considered length of @a str * @return the bounded length of the string */ PURE_FUNCTION size_t dlt_strnlen_s(const char* str, size_t maxsize); /** * Helper function to print an id. * @param text pointer to ASCII string where to write the id * @param id four byte char array as used in DLT mesages as IDs. */ void dlt_print_id(char *text, const char *id); /** * Helper function to set an ID parameter. * @param id four byte char array as used in DLT mesages as IDs. * @param text string to be copied into char array. */ void dlt_set_id(char *id, const char *text); /** * Helper function to remove not nice to print characters, e.g. NULL or carage return. * @param text pointer to string to be cleaned. * @param length length of string excluding terminating zero. */ void dlt_clean_string(char *text, int length); /** * Initialise the filter list. * This function must be called before using further dlt filter. * @param filter pointer to structure of organising DLT filter * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_filter_init(DltFilter *filter, int verbose); /** * Free the used memory by the organising structure of filter. * @param filter pointer to structure of organising DLT filter * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_filter_free(DltFilter *filter, int verbose); /** * Load filter list from file. * @param filter pointer to structure of organising DLT filter * @param filename filename to load filters from * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_filter_load(DltFilter *filter, const char *filename, int verbose); /** * Save filter in space separated list to text file. * @param filter pointer to structure of organising DLT filter * @param filename filename to safe filters into * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_filter_save(DltFilter *filter, const char *filename, int verbose); /** * Find index of filter in filter list * @param filter pointer to structure of organising DLT filter * @param apid application id to be found in filter list * @param ctid context id to be found in filter list * @param log_level log level to be found in filter list * @param payload_min minimum payload lenght to be found in filter list * @param payload_max maximum payload lenght to be found in filter list * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error (or not found), else return index of filter */ int dlt_filter_find(DltFilter *filter, const char *apid, const char *ctid, const int log_level, const int32_t payload_min, const int32_t payload_max, int verbose); /** * Add new filter to filter list. * @param filter pointer to structure of organising DLT filter * @param apid application id to be added to filter list (must always be set). * @param ctid context id to be added to filter list. empty equals don't care. * @param log_level log level to be added to filter list. 0 equals don't care. * @param payload_min min lenght of payload to be added to filter list. 0 equals don't care. * @param payload_max max lenght of payload to be added to filter list. INT32_MAX equals don't care. * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_filter_add(DltFilter *filter, const char *apid, const char *ctid, const int log_level, const int32_t payload_min, const int32_t payload_max, int verbose); /** * Delete filter from filter list * @param filter pointer to structure of organising DLT filter * @param apid application id to be deleted from filter list * @param ctid context id to be deleted from filter list * @param log_level log level to be deleted from filter list * @param payload_min minimum payload lenght to be deleted from filter list * @param payload_max maximum payload lenght to be deleted from filter list * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_filter_delete(DltFilter *filter, const char *apid, const char *ctid, const int log_level, const int32_t payload_min, const int32_t payload_max, int verbose); /** * Initialise the structure used to access a DLT message. * This function must be called before using further dlt_message functions. * @param msg pointer to structure of organising access to DLT messages * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_init(DltMessage *msg, int verbose); /** * Free the used memory by the organising structure of file. * @param msg pointer to structure of organising access to DLT messages * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_free(DltMessage *msg, int verbose); /** * Print Header into an ASCII string. * This function calls dlt_message_header_flags() with flags=DLT_HEADER_SHOW_ALL * @param msg pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the header is written * @param textlength maximal size of text buffer * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_header(DltMessage *msg, char *text, size_t textlength, int verbose); /** * Print Header into an ASCII string, selective. * @param msg pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the header is written * @param textlength maximal size of text buffer * @param flags select, bit-field to select, what should be printed (DLT_HEADER_SHOW_...) * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_header_flags(DltMessage *msg, char *text, size_t textlength, int flags, int verbose); /** * Print Payload into an ASCII string. * @param msg pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the header is written * @param textlength maximal size of text buffer * @param type 1 = payload as hex, 2 = payload as ASCII. * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_payload(DltMessage *msg, char *text, size_t textlength, int type, int verbose); /** * Check if message is filtered or not. All filters are applied (logical OR). * @param msg pointer to structure of organising access to DLT messages * @param filter pointer to filter * @param verbose if set to true verbose information is printed out. * @return 1 = filter matches, 0 = filter does not match, negative value if there was an error */ DltReturnValue dlt_message_filter_check(DltMessage *msg, DltFilter *filter, int verbose); /** * Read message from memory buffer. * Message in buffer has no storage header. * @param msg pointer to structure of organising access to DLT messages * @param buffer pointer to memory buffer * @param length length of message in buffer * @param resync if set to true resync to serial header is enforced * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_message_read(DltMessage *msg, uint8_t *buffer, unsigned int length, int resync, int verbose); /** * Get standard header extra parameters * @param msg pointer to structure of organising access to DLT messages * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_get_extraparameters(DltMessage *msg, int verbose); /** * Set standard header extra parameters * @param msg pointer to structure of organising access to DLT messages * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_set_extraparameters(DltMessage *msg, int verbose); /** * Initialise the structure used to access a DLT file. * This function must be called before using further dlt_file functions. * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_init(DltFile *file, int verbose); /** * Set a list to filters. * This function should be called before loading a DLT file, if filters should be used. * A filter list is an array of filters. Several filters are combined logically by or operation. * The filter list is not copied, so take care to keep list in memory. * @param file pointer to structure of organising access to DLT file * @param filter pointer to filter list array * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_set_filter(DltFile *file, DltFilter *filter, int verbose); /** * Initialising loading a DLT file. * @param file pointer to structure of organising access to DLT file * @param filename filename of DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_open(DltFile *file, const char *filename, int verbose); /** * This function reads DLT file and parse DLT message one by one. * Each message will be written into new file. * If a filter is set, the filter list is used. * @param file pointer to structure of organizing access to DLT file * @param filename file to contain parsed DLT messages. * @param type 1 = payload as hex, 2 = payload as ASCII. * @param verbose if set to true verbose information is printed out. * @return 0 = message does not match filter, 1 = message was read, negative value if there was an error */ DltReturnValue dlt_file_quick_parsing(DltFile *file, const char *filename, int type, int verbose); /** * Find next message in the DLT file and parse them. * This function finds the next message in the DLT file. * If a filter is set, the filter list is used. * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return 0 = message does not match filter, 1 = message was read, negative value if there was an error */ DltReturnValue dlt_file_read(DltFile *file, int verbose); /** * Find next message in the DLT file in RAW format (without storage header) and parse them. * This function finds the next message in the DLT file. * If a filter is set, the filter list is used. * @param file pointer to structure of organising access to DLT file * @param resync Resync to serial header when set to true * @param verbose if set to true verbose information is printed out. * @return 0 = message does not match filter, 1 = message was read, negative value if there was an error */ DltReturnValue dlt_file_read_raw(DltFile *file, int resync, int verbose); /** * Closing loading a DLT file. * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_close(DltFile *file, int verbose); /** * Load standard header of a message from file * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_read_header(DltFile *file, int verbose); /** * Load standard header of a message from file in RAW format (without storage header) * @param file pointer to structure of organising access to DLT file * @param resync Resync to serial header when set to true * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_read_header_raw(DltFile *file, int resync, int verbose); /** * Load, if available in message, extra standard header fields and * extended header of a message from file * (dlt_file_read_header() must have been called before this call!) * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_read_header_extended(DltFile *file, int verbose); /** * Load payload of a message from file * (dlt_file_read_header() must have been called before this call!) * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_read_data(DltFile *file, int verbose); /** * Load headers and payload of a message selected by the index. * If filters are set, index is based on the filtered list. * @param file pointer to structure of organising access to DLT file * @param index position of message in the files beginning from zero * @param verbose if set to true verbose information is printed out. * @return number of messages loaded, negative value if there was an error */ DltReturnValue dlt_file_message(DltFile *file, int index, int verbose); /** * Free the used memory by the organising structure of file. * @param file pointer to structure of organising access to DLT file * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_file_free(DltFile *file, int verbose); /** * Set internal logging filename if mode 2 * @param filename the filename */ void dlt_log_set_filename(const char *filename); #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC /** * Set FIFO base direction * @param pipe_dir the pipe direction */ void dlt_log_set_fifo_basedir(const char *pipe_dir); #endif /** * Set internal logging level * @param level the level */ void dlt_log_set_level(int level); /** * Set whether to print "name" and "unit" attributes in console output * @param state true = with attributes, false = without attributes */ void dlt_print_with_attributes(bool state); /** * Initialize (external) logging facility * @param mode positive, 0 = log to stdout, 1 = log to syslog, 2 = log to file, 3 = log to stderr */ DltReturnValue dlt_log_init(int mode); /** * Print with variable arguments to specified file descriptor by DLT_LOG_MODE environment variable (like fprintf) * @param format format string for message * @return negative value if there was an error or the total number of characters written is returned on success */ int dlt_user_printf(const char *format, ...) PRINTF_FORMAT(1, 2); /** * Log ASCII string with null-termination to (external) logging facility * @param prio priority (see syslog() call) * @param s Pointer to ASCII string with null-termination * @return negative value if there was an error */ DltReturnValue dlt_log(int prio, char *s); /** * Log with variable arguments to (external) logging facility (like printf) * @param prio priority (see syslog() call) * @param format format string for log message * @return negative value if there was an error */ DltReturnValue dlt_vlog(int prio, const char *format, ...) PRINTF_FORMAT(2, 3); /** * Log size bytes with variable arguments to (external) logging facility (similar to snprintf) * @param prio priority (see syslog() call) * @param size number of bytes to log * @param format format string for log message * @return negative value if there was an error */ DltReturnValue dlt_vnlog(int prio, size_t size, const char *format, ...) PRINTF_FORMAT(3, 4); /** * De-Initialize (external) logging facility */ void dlt_log_free(void); /** * Initialising a dlt receiver structure * @param receiver pointer to dlt receiver structure * @param _fd handle to file/socket/fifo, fram which the data should be received * @param type specify whether received data is from socket or file/fifo * @param _buffersize size of data buffer for storing the received data * @return negative value if there was an error */ DltReturnValue dlt_receiver_init(DltReceiver *receiver, int _fd, DltReceiverType type, int _buffersize); /** * De-Initialize a dlt receiver structure * @param receiver pointer to dlt receiver structure * @return negative value if there was an error */ DltReturnValue dlt_receiver_free(DltReceiver *receiver); /** * Initialising a dlt receiver structure * @param receiver pointer to dlt receiver structure * @param fd handle to file/socket/fifo, fram which the data should be received * @param type specify whether received data is from socket or file/fifo * @param buffer data buffer for storing the received data * @return negative value if there was an error and zero if success */ DltReturnValue dlt_receiver_init_global_buffer(DltReceiver *receiver, int fd, DltReceiverType type, char **buffer); /** * De-Initialize a dlt receiver structure * @param receiver pointer to dlt receiver structure * @return negative value if there was an error and zero if success */ DltReturnValue dlt_receiver_free_global_buffer(DltReceiver *receiver); /** * Receive data from socket or file/fifo using the dlt receiver structure * @param receiver pointer to dlt receiver structure * @return number of received bytes or negative value if there was an error */ int dlt_receiver_receive(DltReceiver *receiver); /** * Remove a specific size of bytes from the received data * @param receiver pointer to dlt receiver structure * @param size amount of bytes to be removed * @return negative value if there was an error */ DltReturnValue dlt_receiver_remove(DltReceiver *receiver, int size); /** * Move data from last receive call to front of receive buffer * @param receiver pointer to dlt receiver structure * @return negative value if there was an error */ DltReturnValue dlt_receiver_move_to_begin(DltReceiver *receiver); /** * Check whether to_get amount of data is available in receiver and * copy it to dest. Skip the DltUserHeader if skip_header is set to 1. * @param receiver pointer to dlt receiver structure * @param dest pointer to the destination buffer * @param to_get size of the data to copy in dest * @param skip_header whether if the DltUserHeader must be skipped. */ int dlt_receiver_check_and_get(DltReceiver *receiver, void *dest, unsigned int to_get, unsigned int skip_header); /** * Fill out storage header of a dlt message * @param storageheader pointer to storage header of a dlt message * @param ecu name of ecu to be set in storage header * @return negative value if there was an error */ DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char *ecu); /** * Check if a storage header contains its marker * @param storageheader pointer to storage header of a dlt message * @return 0 no, 1 yes, negative value if there was an error */ DltReturnValue dlt_check_storageheader(DltStorageHeader *storageheader); /** * Checks if received size is big enough for expected data * @param received size * @param required size * @return negative value if required size is not sufficient * */ DltReturnValue dlt_check_rcv_data_size(int received, int required); /** * Initialise static ringbuffer with a size of size. * Initialise as server. Init counters. * Memory is already allocated. * @param buf Pointer to ringbuffer structure * @param ptr Ptr to ringbuffer memory * @param size Maximum size of buffer in bytes * @return negative value if there was an error */ DltReturnValue dlt_buffer_init_static_server(DltBuffer *buf, const unsigned char *ptr, uint32_t size); /** * Initialize static ringbuffer with a size of size. * Initialise as a client. Do not change counters. * Memory is already allocated. * @param buf Pointer to ringbuffer structure * @param ptr Ptr to ringbuffer memory * @param size Maximum size of buffer in bytes * @return negative value if there was an error */ DltReturnValue dlt_buffer_init_static_client(DltBuffer *buf, const unsigned char *ptr, uint32_t size); /** * Initialize dynamic ringbuffer with a size of size. * Initialise as a client. Do not change counters. * Memory will be allocated starting with min_size. * If more memory is needed size is increased wit step_size. * The maximum size is max_size. * @param buf Pointer to ringbuffer structure * @param min_size Minimum size of buffer in bytes * @param max_size Maximum size of buffer in bytes * @param step_size size of which ringbuffer is increased * @return negative value if there was an error */ DltReturnValue dlt_buffer_init_dynamic(DltBuffer *buf, uint32_t min_size, uint32_t max_size, uint32_t step_size); /** * Deinitilaise usage of static ringbuffer * @param buf Pointer to ringbuffer structure * @return negative value if there was an error */ DltReturnValue dlt_buffer_free_static(DltBuffer *buf); /** * Release and free memory used by dynamic ringbuffer * @param buf Pointer to ringbuffer structure * @return negative value if there was an error */ DltReturnValue dlt_buffer_free_dynamic(DltBuffer *buf); /** * Check if message fits into buffer. * @param buf Pointer to buffer structure * @param needed Needed size * @return DLT_RETURN_OK if enough space, DLT_RETURN_ERROR otherwise */ DltReturnValue dlt_buffer_check_size(DltBuffer *buf, int needed); /** * Write one entry to ringbuffer * @param buf Pointer to ringbuffer structure * @param data Pointer to data to be written to ringbuffer * @param size Size of data in bytes to be written to ringbuffer * @return negative value if there was an error */ DltReturnValue dlt_buffer_push(DltBuffer *buf, const unsigned char *data, unsigned int size); /** * Write up to three entries to ringbuffer. * Entries are joined to one block. * @param buf Pointer to ringbuffer structure * @param data1 Pointer to data to be written to ringbuffer * @param size1 Size of data in bytes to be written to ringbuffer * @param data2 Pointer to data to be written to ringbuffer * @param size2 Size of data in bytes to be written to ringbuffer * @param data3 Pointer to data to be written to ringbuffer * @param size3 Size of data in bytes to be written to ringbuffer * @return negative value if there was an error */ DltReturnValue dlt_buffer_push3(DltBuffer *buf, const unsigned char *data1, unsigned int size1, const unsigned char *data2, unsigned int size2, const unsigned char *data3, unsigned int size3); /** * Read one entry from ringbuffer. * Remove it from ringbuffer. * @param buf Pointer to ringbuffer structure * @param data Pointer to data read from ringbuffer * @param max_size Max size of read data in bytes from ringbuffer * @return size of read data, zero if no data available, negative value if there was an error */ int dlt_buffer_pull(DltBuffer *buf, unsigned char *data, int max_size); /** * Read one entry from ringbuffer. * Do not remove it from ringbuffer. * @param buf Pointer to ringbuffer structure * @param data Pointer to data read from ringbuffer * @param max_size Max size of read data in bytes from ringbuffer * @return size of read data, zero if no data available, negative value if there was an error */ int dlt_buffer_copy(DltBuffer *buf, unsigned char *data, int max_size); /** * Remove entry from ringbuffer. * @param buf Pointer to ringbuffer structure * @return size of read data, zero if no data available, negative value if there was an error */ int dlt_buffer_remove(DltBuffer *buf); /** * Print information about buffer and log to internal DLT log. * @param buf Pointer to ringbuffer structure */ void dlt_buffer_info(DltBuffer *buf); /** * Print status of buffer and log to internal DLT log. * @param buf Pointer to ringbuffer structure */ void dlt_buffer_status(DltBuffer *buf); /** * Get total size in bytes of ringbuffer. * If buffer is dynamic, max size is returned. * @param buf Pointer to ringbuffer structure * @return total size of buffer */ uint32_t dlt_buffer_get_total_size(DltBuffer *buf); /** * Get used size in bytes of ringbuffer. * @param buf Pointer to ringbuffer structure * @return used size of buffer */ int dlt_buffer_get_used_size(DltBuffer *buf); /** * Get number of entries in ringbuffer. * @param buf Pointer to ringbuffer structure * @return number of entries */ int dlt_buffer_get_message_count(DltBuffer *buf); # if !defined (__WIN32__) /** * Helper function: Setup serial connection * @param fd File descriptor of serial tty device * @param speed Serial line speed, as defined in termios.h * @return negative value if there was an error */ DltReturnValue dlt_setup_serial(int fd, speed_t speed); /** * Helper function: Convert serial line baudrate (as number) to line speed (as defined in termios.h) * @param baudrate Serial line baudrate (as number) * @return Serial line speed, as defined in termios.h */ speed_t dlt_convert_serial_speed(int baudrate); /** * Print dlt version and dlt svn version to buffer * @param buf Pointer to buffer * @param size size of buffer */ void dlt_get_version(char *buf, size_t size); /** * Print dlt major version to buffer * @param buf Pointer to buffer * @param size size of buffer */ void dlt_get_major_version(char *buf, size_t size); /** * Print dlt minor version to buffer * @param buf Pointer to buffer * @param size size of buffer */ void dlt_get_minor_version(char *buf, size_t size); # endif /* Function prototypes which should be used only internally */ /* */ /** * Common part of initialisation. Evaluates the following environment variables * and stores them in dlt_user struct: * - DLT_DISABLE_EXTENDED_HEADER_FOR_NONVERBOSE * - DLT_LOCAL_PRINT_MODE (AUTOMATIC: 0, FORCE_ON: 2, FORCE_OFF: 3) * - DLT_INITIAL_LOG_LEVEL (e.g. APPx:CTXa:6;APPx:CTXb:5) * - DLT_FORCE_BLOCKING * - DLT_USER_BUFFER_MIN * - DLT_USER_BUFFER_MAX * - DLT_USER_BUFFER_STEP * - DLT_LOG_MSG_BUF_LEN * - DLT_DISABLE_INJECTION_MSG_AT_USER * @return negative value if there was an error */ DltReturnValue dlt_init_common(void); /** * Return the uptime of the system in 0.1 ms resolution * @return 0 if there was an error */ uint32_t dlt_uptime(void); /** * Print header of a DLT message * @param message pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the header is written * @param size maximal size of text buffer * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_print_header(DltMessage *message, char *text, uint32_t size, int verbose); /** * Print payload of a DLT message as Hex-Output * @param message pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the output is written * @param size maximal size of text buffer * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_print_hex(DltMessage *message, char *text, uint32_t size, int verbose); /** * Print payload of a DLT message as ASCII-Output * @param message pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the output is written * @param size maximal size of text buffer * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_print_ascii(DltMessage *message, char *text, uint32_t size, int verbose); /** * Print payload of a DLT message as Mixed-Ouput (Hex and ASCII), for plain text output * @param message pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the output is written * @param size maximal size of text buffer * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_print_mixed_plain(DltMessage *message, char *text, uint32_t size, int verbose); /** * Print payload of a DLT message as Mixed-Ouput (Hex and ASCII), for HTML text output * @param message pointer to structure of organising access to DLT messages * @param text pointer to a ASCII string, in which the output is written * @param size maximal size of text buffer * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_print_mixed_html(DltMessage *message, char *text, uint32_t size, int verbose); /** * Decode and print a argument of a DLT message * @param msg pointer to structure of organising access to DLT messages * @param type_info Type of argument * @param ptr pointer to pointer to data (pointer to data is changed within this function) * @param datalength pointer to datalength (datalength is changed within this function) * @param text pointer to a ASCII string, in which the output is written * @param textlength maximal size of text buffer * @param byteLength If argument is a string, and this value is 0 or greater, this value will be taken as string length * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_message_argument_print(DltMessage *msg, uint32_t type_info, uint8_t **ptr, int32_t *datalength, char *text, size_t textlength, int byteLength, int verbose); /** * Check environment variables. */ void dlt_check_envvar(void); /** * Parse the response text and identifying service id and its options. * * @param resp_text char * * @param service_id int * * @param service_opt int * * @return pointer to resp_text */ int dlt_set_loginfo_parse_service_id(char *resp_text, uint32_t *service_id, uint8_t *service_opt); /** * Convert get log info from ASCII to uint16 * * @param rp char * @param rp_count int * @return length */ int16_t dlt_getloginfo_conv_ascii_to_uint16_t(char *rp, int *rp_count); /** * Convert get log info from ASCII to int16 * * @param rp char * @param rp_count int * @return length */ int16_t dlt_getloginfo_conv_ascii_to_int16_t(char *rp, int *rp_count); /** * Convert get log info from ASCII to string (with '\0' termination) * * @param rp char * @param rp_count int * @param wp char Array needs to be 1 byte larger than len to store '\0' * @param len int */ void dlt_getloginfo_conv_ascii_to_string(char *rp, int *rp_count, char *wp, int len); /** * Convert get log info from ASCII to ID (without '\0' termination) * * @param rp char * @param rp_count int * @param wp char * @param len int * @return position of last read character in wp */ int dlt_getloginfo_conv_ascii_to_id(char *rp, int *rp_count, char *wp, int len); /** * Convert from hex ASCII to binary * @param ptr const char * @param binary uint8_t * @param size int */ void dlt_hex_ascii_to_binary(const char *ptr, uint8_t *binary, int *size); /** * Helper function to execute the execvp function in a new child process. * @param filename file path to store the stdout of command (NULL if not required) * @param command execution command followed by arguments with NULL-termination * @return negative value if there was an error */ int dlt_execute_command(char *filename, char *command, ...); /** * Return the extension of given file name. * @param filename Only file names without prepended path allowed. * @return pointer to extension */ char *get_filename_ext(const char *filename); /** * Extract the base name of given file name (without the extension). * @param abs_file_name Absolute path to file name. * @param base_name Base name it is extracted to. * @param base_name_length Base name length. * @return indicating success */ bool dlt_extract_base_name_without_ext(const char* const abs_file_name, char* base_name, long base_name_len); /** * Initialize (external) logging facility * @param mode DltLoggingMode, 0 = log to stdout, 1 = log to syslog, 2 = log to file, 3 = log to stderr * @param enable_multiple_logfiles, true if multiple logfiles (incl. size limits) should be use * @param logging_file_size, maximum size in bytes of one logging file * @param logging_files_max_size, maximum size in bytes of all logging files */ DltReturnValue dlt_log_init_multiple_logfiles_support(DltLoggingMode mode, bool enable_multiple_logfiles, int logging_file_size, int logging_files_max_size); /** * Initialize (external) logging facility for single logfile. */ DltReturnValue dlt_log_init_single_logfile(); /** * Initialize (external) logging facility for multiple files logging. */ DltReturnValue dlt_log_init_multiple_logfiles(int logging_file_size, int logging_files_max_size); /** * Logs into log files represented by the multiple files buffer. * @param format First element in a specific format that will be logged. * @param ... Further elements in a specific format that will be logged. */ void dlt_log_multiple_files_write(const char* format, ...); void dlt_log_free_single_logfile(); void dlt_log_free_multiple_logfiles(); /** * Checks whether (internal) logging in multiple files is active. */ bool dlt_is_log_in_multiple_files_active(); # ifdef __cplusplus } # endif /** \} */ #endif /* DLT_COMMON_H */ dlt-daemon-2.18.10/include/dlt/dlt_common_api.h000066400000000000000000000461741446635226000212760ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_common_api.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_commpn_api.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #ifndef DLT_COMMON_API_H #define DLT_COMMON_API_H #include "dlt.h" /** * Create an object for a new context. * Common API with DLT Embedded * This macro has to be called first for every. * @param CONTEXT object containing information about one special logging context */ /* #define DLT_DECLARE_CONTEXT(CONTEXT) */ /* UNCHANGED */ /** * Use an object of a new context created in another module. * Common API with DLT Embedded * This macro has to be called first for every. * @param CONTEXT object containing information about one special logging context */ /* #define DLT_IMPORT_CONTEXT(CONTEXT) */ /* UNCHANGED */ /** * Register application. * Common API with DLT Embedded * @param APPID application id with maximal four characters * @param DESCRIPTION ASCII string containing description */ /* #define DLT_REGISTER_APP(APPID,DESCRIPTION) */ /* UNCHANGED */ /** * Register context including application (with default log level and default trace status) * Common API with DLT Embedded * @param CONTEXT object containing information about one special logging context * @param CONTEXTID context id with maximal four characters * @param APPID context id with maximal four characters * @param DESCRIPTION ASCII string containing description */ #define DLT_REGISTER_CONTEXT_APP(CONTEXT, CONTEXTID, APPID, DESCRIPTION) \ DLT_REGISTER_CONTEXT(CONTEXT, CONTEXTID, DESCRIPTION) /** * Send log message with variable list of messages (intended for verbose mode) * Common API with DLT Embedded * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param ARGS variable list of arguments */ /*****************************************/ #define DLT_LOG0(CONTEXT, LOGLEVEL) \ DLT_LOG(CONTEXT, LOGLEVEL) /*****************************************/ #define DLT_LOG1(CONTEXT, LOGLEVEL, ARGS1) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1) /*****************************************/ #define DLT_LOG2(CONTEXT, LOGLEVEL, ARGS1, ARGS2) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2) /*****************************************/ #define DLT_LOG3(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3) /*****************************************/ #define DLT_LOG4(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4) /*****************************************/ #define DLT_LOG5(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5) /*****************************************/ #define DLT_LOG6(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6) /*****************************************/ #define DLT_LOG7(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7) /*****************************************/ #define DLT_LOG8(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8) /*****************************************/ #define DLT_LOG9(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9) /*****************************************/ #define DLT_LOG10(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10) /*****************************************/ #define DLT_LOG11(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10, ARGS11) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10, ARGS11) /*****************************************/ #define DLT_LOG12(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12) \ DLT_LOG(CONTEXT, LOGLEVEL, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10, ARGS11, ARGS12) /*****************************************/ #define DLT_LOG13(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13) \ DLT_LOG(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13) /*****************************************/ #define DLT_LOG14(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14) \ DLT_LOG(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14) /*****************************************/ #define DLT_LOG15(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15) \ DLT_LOG(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15) /*****************************************/ #define DLT_LOG16(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15, \ ARGS16) \ DLT_LOG(CONTEXT, \ LOGLEVEL, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15, \ ARGS16) /** * Send log message with variable list of messages (intended for non-verbose mode) * Common API with DLT Embedded * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param MSGID the message id of log message * @param ARGS variable list of arguments: * calls to DLT_STRING(), DLT_BOOL(), DLT_FLOAT32(), DLT_FLOAT64(), * DLT_INT(), DLT_UINT(), DLT_RAW() */ /*****************************************/ #define DLT_LOG_ID0(CONTEXT, LOGLEVEL, MSGID) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID) /*****************************************/ #define DLT_LOG_ID1(CONTEXT, LOGLEVEL, MSGID, ARGS1) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1) /*****************************************/ #define DLT_LOG_ID2(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2) /*****************************************/ #define DLT_LOG_ID3(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3) /*****************************************/ #define DLT_LOG_ID4(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4) /*****************************************/ #define DLT_LOG_ID5(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5) /*****************************************/ #define DLT_LOG_ID6(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6) /*****************************************/ #define DLT_LOG_ID7(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7) /*****************************************/ #define DLT_LOG_ID8(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8) /*****************************************/ #define DLT_LOG_ID9(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9) /*****************************************/ #define DLT_LOG_ID10(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10) /*****************************************/ #define DLT_LOG_ID11(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11) \ DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ARGS1, ARGS2, ARGS3, ARGS4, ARGS5, ARGS6, ARGS7, ARGS8, ARGS9, ARGS10, ARGS11) /*****************************************/ #define DLT_LOG_ID12(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12) \ DLT_LOG_ID(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12) /*****************************************/ #define DLT_LOG_ID13(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13) \ DLT_LOG_ID(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13) /*****************************************/ #define DLT_LOG_ID14(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14) \ DLT_LOG_ID(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14) /*****************************************/ #define DLT_LOG_ID15(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15) \ DLT_LOG_ID(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15) /*****************************************/ #define DLT_LOG_ID16(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15, \ ARGS16) \ DLT_LOG_ID(CONTEXT, \ LOGLEVEL, \ MSGID, \ ARGS1, \ ARGS2, \ ARGS3, \ ARGS4, \ ARGS5, \ ARGS6, \ ARGS7, \ ARGS8, \ ARGS9, \ ARGS10, \ ARGS11, \ ARGS12, \ ARGS13, \ ARGS14, \ ARGS15, \ ARGS16) /** * Unregister context. * Common API with DLT Embedded * @param CONTEXT object containing information about one special logging context */ /* #define DLT_UNREGISTER_CONTEXT(CONTEXT) */ /* UNCHANGED */ /** * Unregister application. * Common API with DLT Embedded */ /* #define DLT_UNREGISTER_APP() */ /* UNCHANGED */ /** * Add string parameter to the log messsage. * Common API with DLT Embedded * In the future in none verbose mode the string will not be sent via DLT message. * @param TEXT ASCII string */ /* #define DLT_CSTRING(TEXT) */ /* UNCHANGED */ #endif /* DLT_COMMON_API_H */ dlt-daemon-2.18.10/include/dlt/dlt_cpp_extension.hpp000066400000000000000000000134621446635226000223650ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Intel Corporation * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Stefan Vacek Intel Corporation * * \copyright Copyright © 2015 Intel Corporation. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cpp_extension.hpp */ #ifndef DLT_CPP_EXTENSION_HPP #define DLT_CPP_EXTENSION_HPP #include #include #include #include #include "dlt.h" template int32_t logToDlt(DltContextData &log, T const &value) = delete; template<> inline int32_t logToDlt(DltContextData &log, int8_t const &value) { return dlt_user_log_write_int8(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, int16_t const &value) { return dlt_user_log_write_int16(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, int32_t const &value) { return dlt_user_log_write_int32(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, int64_t const &value) { return dlt_user_log_write_int64(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, uint8_t const &value) { return dlt_user_log_write_uint8(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, uint16_t const &value) { return dlt_user_log_write_uint16(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, uint32_t const &value) { return dlt_user_log_write_uint32(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, uint64_t const &value) { return dlt_user_log_write_uint64(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, float32_t const &value) { return dlt_user_log_write_float32(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, double const &value) { return dlt_user_log_write_float64(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, bool const &value) { return dlt_user_log_write_bool(&log, value); } static inline int32_t logToDlt(DltContextData &log, char const * const value) { return dlt_user_log_write_utf8_string(&log, value); } static inline int32_t logToDlt(DltContextData &log, char * const value) { return dlt_user_log_write_utf8_string(&log, value); } template<> inline int32_t logToDlt(DltContextData &log, std::string const &value) { return dlt_user_log_write_utf8_string(&log, value.c_str()); } /* stl types */ template<> int32_t logToDlt(DltContextData &log, std::string const &value); template> static inline int32_t logToDlt(DltContextData &log, std::vector<_Tp, _Alloc> const & value) { int result = 0; for (auto elem : value) result += logToDlt(log, elem); if (result != 0) result = -1; return result; } template> static inline int32_t logToDlt(DltContextData &log, std::list<_Tp, _Alloc> const & value) { int result = 0; for (auto elem : value) result += logToDlt(log, elem); if (result != 0) result = -1; return result; } template, typename _Alloc = std::allocator>> static inline int32_t logToDlt(DltContextData &log, std::map<_Key, _Tp, _Compare, _Alloc> const & value) { int result = 0; for (auto elem : value) { result += logToDlt(log, elem.first); result += logToDlt(log, elem.second); } if (result != 0) result = -1; return result; } //variadic functions using C11 standard template static inline int32_t logToDltVariadic(DltContextData &log, First const &valueA) { return logToDlt(log, valueA); } template static inline int32_t logToDltVariadic(DltContextData &log, First const &valueA, const Rest&... valueB) { int result = logToDlt(log, valueA) + logToDltVariadic(log, valueB...); if (result != 0) result = -1; return result; } /** * @brief macro to write a log message with variable number of arguments and without the need to specify the type of log data * * The macro can be used with any type that provides a logToDlt function. * * Example: * DLT_LOG_CXX(dltContext, DLT_LV_X, "text", valueA, valueB, ...) */ #define DLT_LOG_CXX(CONTEXT, LOGLEVEL, ...)\ do\ {\ DltContextData log;\ if (dlt_user_log_write_start(&CONTEXT,&log,LOGLEVEL)>0)\ {\ logToDltVariadic(log, ##__VA_ARGS__);\ dlt_user_log_write_finish(&log);\ }\ }\ while(false) /** * @brief macro to write a log message with variable number of arguments and without the need to specify the type of log data. * * The macro can be used with any type that provides a logToDlt function. * This includes all the types that are code generated. * * This macro is similar to \c DLT_LOG_CXX. However, it adds the current function name as the first log argument. * * Example: * DLT_LOG_FCN_CXX(dltContext, DLT_LV_X, "text", valueA, valueB, ...) */ #define DLT_LOG_FCN_CXX(CONTEXT, LOGLEVEL, ...) \ do\ {\ DltContextData log;\ if (dlt_user_log_write_start(&CONTEXT, &log, LOGLEVEL) > 0)\ {\ dlt_user_log_write_string(&log, __PRETTY_FUNCTION__);\ logToDltVariadic(log, ##__VA_ARGS__);\ dlt_user_log_write_finish(&log);\ }\ }\ while(false) #endif /* DLT_CPP_EXTENSION_HPP */ dlt-daemon-2.18.10/include/dlt/dlt_filetransfer.h000066400000000000000000000160121446635226000216250ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_filetransfer.h */ #ifndef DLT_FILETRANSFER_H #define DLT_FILETRANSFER_H #include /* Needed for LONG_MAX */ #include /* Needed for struct stat st*/ #include "dlt.h" /* Needed for DLT Logs */ #include /* Signal handling */ #include "errno.h" /* ! Error code for dlt_user_log_file_complete */ #define DLT_FILETRANSFER_ERROR_FILE_COMPLETE -300 /* ! Error code for dlt_user_log_file_complete */ #define DLT_FILETRANSFER_ERROR_FILE_COMPLETE1 -301 /* ! Error code for dlt_user_log_file_complete */ #define DLT_FILETRANSFER_ERROR_FILE_COMPLETE2 -302 /* ! Error code for dlt_user_log_file_complete */ #define DLT_FILETRANSFER_ERROR_FILE_COMPLETE3 -303 /* ! Error code for dlt_user_log_file_head */ #define DLT_FILETRANSFER_ERROR_FILE_HEAD -400 /* ! Error code for dlt_user_log_file_data */ #define DLT_FILETRANSFER_ERROR_FILE_DATA -500 /* ! Error code for dlt_user_log_file_data */ #define DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED -501 /* ! Error code for dlt_user_log_file_end */ #define DLT_FILETRANSFER_ERROR_FILE_END -600 /* ! Error code for dlt_user_log_file_infoAbout */ #define DLT_FILETRANSFER_ERROR_INFO_ABOUT -700 /* ! Error code for dlt_user_log_file_packagesCount */ #define DLT_FILETRANSFER_ERROR_PACKAGE_COUNT -800 /* ! Error code for failed get serial number */ #define DLT_FILETRANSFER_FILE_SERIAL_NUMBER -900 /* !Transfer the complete file as several dlt logs. */ /**This method transfer the complete file as several dlt logs. At first it will be checked that the file exist. * In the next step some generic informations about the file will be logged to dlt. * Now the header will be logged to dlt. See the method dlt_user_log_file_header for more informations. * Then the method dlt_user_log_data will be called with the parameter to log all packages in a loop with some timeout. * At last dlt_user_log_end is called to signal that the complete file transfer was okey. This is important for the plugin of the dlt viewer. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param deleteFlag Flag if the file will be deleted after transfer. 1->delete, 0->notDelete * @param timeout Timeout in ms to wait between some logs. Important that the FIFO of dlt will not be flooded with to many messages in a short period of time. * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_complete(DltContext *fileContext, const char *filename, int deleteFlag, int timeout); /* !This method gives information about the number of packages the file have */ /**Every file will be divided into several packages. Every package will be logged as a single dlt log. * The number of packages depends on the BUFFER_SIZE. * At first it will be checked if the file exist. Then the file will be divided into * several packages depending on the buffer size. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_packagesCount(DltContext *fileContext, const char *filename); /* !Logs specific file inforamtions to dlt */ /**The filename, file size, file serial number and the number of packages will be logged to dlt. * @param fileContext Specific context * @param filename Absolute file path * @return Returns 0 if everything was okey.If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_infoAbout(DltContext *fileContext, const char *filename); /* !Transfer the head of the file as a dlt logs. */ /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number, * the file name, the file size, package number the file have and the buffer size. * All these informations are needed from the plugin of the dlt viewer. * See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param alias Alias for the file. An alternative name to show in the receiving end * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_header_alias(DltContext *fileContext, const char *filename, const char *alias); /* !Transfer the head of the file as a dlt logs. */ /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number, * the file name, the file size, package number the file have and the buffer size. * All these informations are needed from the plugin of the dlt viewer. * See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_header(DltContext *fileContext, const char *filename); /* !Transfer the content data of a file. */ /**See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param packageToTransfer Package number to transfer. If this param is LONG_MAX, the whole file will be transferred with a specific timeout * @param timeout Timeout to wait between dlt logs. Important because the dlt FIFO should not be flooded. Default is defined by MIN_TIMEOUT. The given timeout in ms can not be smaller than MIN_TIMEOUT. * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_data(DltContext *fileContext, const char *filename, int packageToTransfer, int timeout); /* !Transfer the end of the file as a dlt logs. */ /**The end of the file must be logged to dlt because the end contains inforamtion about the file serial number. * This informations is needed from the plugin of the dlt viewer. * See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param deleteFlag Flag to delete the file after the whole file is transferred (logged to dlt).1->delete,0->NotDelete * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned. */ extern int dlt_user_log_file_end(DltContext *fileContext, const char *filename, int deleteFlag); #endif /* DLT_FILETRANSFER_H */ dlt-daemon-2.18.10/include/dlt/dlt_multiple_files.h000066400000000000000000000151611446635226000221620ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Oleg Tropmann * Daniel Weber * * \copyright Copyright © 2022 Mercedes-Benz AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_multiple_files.h */ #ifndef DLT_MULTIPLE_FILES_H #define DLT_MULTIPLE_FILES_H #include #include "dlt_common.h" #include "dlt_types.h" #define MULTIPLE_FILES_FILENAME_INDEX_DELIM "." #define MULTIPLE_FILES_FILENAME_TIMESTAMP_DELIM "_" /** * Represents a ring buffer of multiple files of identical file size. * File names differ in timestamp or index (depending on chosen mode). * This buffer is used, e.g. for dlt offline traces and the internal dlt logging (dlt.log) */ typedef struct { char directory[NAME_MAX + 1];/**< (String) Store DLT messages to local directory */ char filename[NAME_MAX + 1]; /**< (String) Filename of currently used log file */ int fileSize; /**< (int) Maximum size in bytes of one file, e.g. for offline trace 1000000 as default */ int maxSize; /**< (int) Maximum size of all files, e.g. for offline trace 4000000 as default */ bool filenameTimestampBased; /**< (bool) is filename timestamp based? false = index based (Default: true) */ char filenameBase[NAME_MAX + 1];/**< (String) Prefix of file name */ char filenameExt[NAME_MAX + 1];/**< (String) Extension of file name */ int ohandle; /**< (int) file handle to current output file */ } MultipleFilesRingBuffer; /** * Initialise the multiple files buffer. * This function call opens the currently used log file. * A check of the complete size of the files is done during startup. * Old files are deleted, if there is not enough space left to create new file. * This function must be called before using further multiple files functions. * @param files_buffer pointer to MultipleFilesRingBuffer struct. * @param directory directory where to store multiple files. * @param file_size maximum size of one files. * @param max_size maximum size of complete multiple files in bytes. * @param filename_timestamp_based filename to be created on timestamp-based or index-based. * @param append Indicates whether the current log files is used or a new file should be be created * @param filename_base Base name. * @param filename_ext File extension. * @return negative value if there was an error. */ extern DltReturnValue multiple_files_buffer_init(MultipleFilesRingBuffer *files_buffer, const char *directory, int file_size, int max_size, bool filename_timestamp_based, bool append, const char *filename_base, const char *filename_ext); /** * Uninitialise the multiple files buffer. * This function call closes currently used log file. * This function must be called after usage of multiple files. * @param files_buffer pointer to MultipleFilesRingBuffer struct. * @return negative value if there was an error. */ extern DltReturnValue multiple_files_buffer_free(const MultipleFilesRingBuffer *files_buffer); /** * Write data into multiple files. * If the current used log file exceeds the max file size, new log file is created. * A check of the complete size of the multiple files is done before new file is created. * Old files are deleted, if there is not enough space left to create new file. * @param files_buffer pointer to MultipleFilesRingBuffer struct. * @param data pointer to first data block to be written, null if not used. * @param size size in bytes of first data block to be written, 0 if not used. * @return negative value if there was an error. */ extern DltReturnValue multiple_files_buffer_write(MultipleFilesRingBuffer *files_buffer, const unsigned char *data, int size); /** * First the limits are verified. Then the oldest file is deleted and a new file is created on demand. * @param files_buffer pointer to MultipleFilesRingBuffer struct. * @param size size in bytes of data that will be written. */ void multiple_files_buffer_rotate_file(MultipleFilesRingBuffer *files_buffer, int size); /** * Writes the given data to current file specified by corresponding file handle. * @param files_buffer pointer to MultipleFilesRingBuffer struct. * @param data pointer to data block to be written, null if not used. * @param size size in bytes of given data block to be written, 0 if not used. */ DltReturnValue multiple_files_buffer_write_chunk(const MultipleFilesRingBuffer *files_buffer, const unsigned char *data, int size); /** * Get size of currently used multiple files buffer. * @return size in bytes. */ extern ssize_t multiple_files_buffer_get_total_size(const MultipleFilesRingBuffer *files_buffer); /** * Provides info about the multiple files storage directory. * @param path path of the storage directory * @param file_name filename to search for * @param newest pointer to store newest filename * @param oldest pointer to store oldest filename * @return num of files in the directory. */ unsigned int multiple_files_buffer_storage_dir_info(const char *path, const char *file_name, char *newest, char *oldest); /** * Creates filename with index. * @param files_buffer pointer to MultipleFilesRingBuffer struct. * @param length the maximum length of the log_file_name. * @param idx index to be used for file name creation. */ void multiple_files_buffer_file_name(MultipleFilesRingBuffer *files_buffer, size_t length, unsigned int idx); /** * Generates index for log file name. * @param file filename supplied to create index. * @return the index to be used for log file name. */ unsigned int multiple_files_buffer_get_idx_of_log_file(char *file); #endif // DLT_MULTIPLE_FILES_H dlt-daemon-2.18.10/include/dlt/dlt_offline_trace.h000066400000000000000000000105721446635226000217460ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_offline_trace.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_offline_trace.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #ifndef DLT_OFFLINE_TRACE_H #define DLT_OFFLINE_TRACE_H #include #include "dlt_multiple_files.h" #include "dlt_types.h" #define DLT_OFFLINETRACE_FILENAME_BASE "dlt_offlinetrace" #define DLT_OFFLINETRACE_FILENAME_EXT ".dlt" /** * Write data into offline traces. * If the current used log file exceeds the max file size, new log file is created. * A check of the complete size of the offline traces is done before new file is created. * Old files are deleted, if there is not enough space left to create new file. * @param trace pointer to MultipleFilesRingBuffer struct. * @param data1 pointer to first data block to be written, null if not used. * @param size1 size in bytes of first data block to be written, 0 if not used. * @param data2 pointer to second data block to be written, null if not used. * @param size2 size in bytes of second data block to be written, 0 if not used. * @param data3 pointer to third data block to be written, null if not used. * @param size3 size in bytes of third data block to be written, 0 if not used. * @return negative value if there was an error. */ extern DltReturnValue dlt_offline_trace_write(MultipleFilesRingBuffer *trace, const unsigned char *data1, int size1, const unsigned char *data2, int size2, const unsigned char *data3, int size3); #endif /* DLT_OFFLINE_TRACE_H */ dlt-daemon-2.18.10/include/dlt/dlt_protocol.h000066400000000000000000000250451446635226000210100ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_protocol.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_protocol.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision$ * $LastChangedDate$ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #ifndef DLT_PROTOCOL_H #define DLT_PROTOCOL_H /** * \defgroup protocolapi DLT Protocol API * \addtogroup protocolapi \{ */ /* * Definitions of the htyp parameter in standard header. */ #define DLT_HTYP_UEH 0x01 /**< use extended header */ #define DLT_HTYP_MSBF 0x02 /**< MSB first */ #define DLT_HTYP_WEID 0x04 /**< with ECU ID */ #define DLT_HTYP_WSID 0x08 /**< with session ID */ #define DLT_HTYP_WTMS 0x10 /**< with timestamp */ #define DLT_HTYP_VERS 0xe0 /**< version number, 0x1 */ #define DLT_IS_HTYP_UEH(htyp) ((htyp) & DLT_HTYP_UEH) #define DLT_IS_HTYP_MSBF(htyp) ((htyp) & DLT_HTYP_MSBF) #define DLT_IS_HTYP_WEID(htyp) ((htyp) & DLT_HTYP_WEID) #define DLT_IS_HTYP_WSID(htyp) ((htyp) & DLT_HTYP_WSID) #define DLT_IS_HTYP_WTMS(htyp) ((htyp) & DLT_HTYP_WTMS) #define DLT_HTYP_PROTOCOL_VERSION1 (1 << 5) /* * Definitions of msin parameter in extended header. */ #define DLT_MSIN_VERB 0x01 /**< verbose */ #define DLT_MSIN_MSTP 0x0e /**< message type */ #define DLT_MSIN_MTIN 0xf0 /**< message type info */ #define DLT_MSIN_MSTP_SHIFT 1 /**< shift right offset to get mstp value */ #define DLT_MSIN_MTIN_SHIFT 4 /**< shift right offset to get mtin value */ #define DLT_IS_MSIN_VERB(msin) ((msin) & DLT_MSIN_VERB) #define DLT_GET_MSIN_MSTP(msin) (((msin) & DLT_MSIN_MSTP) >> DLT_MSIN_MSTP_SHIFT) #define DLT_GET_MSIN_MTIN(msin) (((msin) & DLT_MSIN_MTIN) >> DLT_MSIN_MTIN_SHIFT) /* * Definitions of mstp parameter in extended header. */ #define DLT_TYPE_LOG 0x00 /**< Log message type */ #define DLT_TYPE_APP_TRACE 0x01 /**< Application trace message type */ #define DLT_TYPE_NW_TRACE 0x02 /**< Network trace message type */ #define DLT_TYPE_CONTROL 0x03 /**< Control message type */ /* * Definitions of msti parameter in extended header. */ #define DLT_TRACE_VARIABLE 0x01 /**< tracing of a variable */ #define DLT_TRACE_FUNCTION_IN 0x02 /**< tracing of function calls */ #define DLT_TRACE_FUNCTION_OUT 0x03 /**< tracing of function return values */ #define DLT_TRACE_STATE 0x04 /**< tracing of states of a state machine */ #define DLT_TRACE_VFB 0x05 /**< tracing of virtual function bus */ /* * Definitions of msbi parameter in extended header. */ /* see file dlt_user.h */ /* * Definitions of msci parameter in extended header. */ #define DLT_CONTROL_REQUEST 0x01 /**< Request message */ #define DLT_CONTROL_RESPONSE 0x02 /**< Response to request message */ #define DLT_CONTROL_TIME 0x03 /**< keep-alive message */ #define DLT_MSIN_CONTROL_REQUEST ((DLT_TYPE_CONTROL << DLT_MSIN_MSTP_SHIFT) | \ (DLT_CONTROL_REQUEST << DLT_MSIN_MTIN_SHIFT)) #define DLT_MSIN_CONTROL_RESPONSE ((DLT_TYPE_CONTROL << DLT_MSIN_MSTP_SHIFT) | \ (DLT_CONTROL_RESPONSE << DLT_MSIN_MTIN_SHIFT)) #define DLT_MSIN_CONTROL_TIME ((DLT_TYPE_CONTROL << DLT_MSIN_MSTP_SHIFT) | \ (DLT_CONTROL_TIME << DLT_MSIN_MTIN_SHIFT)) /* * Definitions of types of arguments in payload. */ #define DLT_TYPE_INFO_TYLE 0x0000000f /**< Length of standard data: 1 = 8bit, 2 = 16bit, 3 = 32 bit, 4 = 64 bit, 5 = 128 bit */ #define DLT_TYPE_INFO_BOOL 0x00000010 /**< Boolean data */ #define DLT_TYPE_INFO_SINT 0x00000020 /**< Signed integer data */ #define DLT_TYPE_INFO_UINT 0x00000040 /**< Unsigned integer data */ #define DLT_TYPE_INFO_FLOA 0x00000080 /**< Float data */ #define DLT_TYPE_INFO_ARAY 0x00000100 /**< Array of standard types */ #define DLT_TYPE_INFO_STRG 0x00000200 /**< String */ #define DLT_TYPE_INFO_RAWD 0x00000400 /**< Raw data */ #define DLT_TYPE_INFO_VARI 0x00000800 /**< Set, if additional information to a variable is available */ #define DLT_TYPE_INFO_FIXP 0x00001000 /**< Set, if quantization and offset are added */ #define DLT_TYPE_INFO_TRAI 0x00002000 /**< Set, if additional trace information is added */ #define DLT_TYPE_INFO_STRU 0x00004000 /**< Struct */ #define DLT_TYPE_INFO_SCOD 0x00038000 /**< coding of the type string: 0 = ASCII, 1 = UTF-8 */ #define DLT_TYLE_8BIT 0x00000001 #define DLT_TYLE_16BIT 0x00000002 #define DLT_TYLE_32BIT 0x00000003 #define DLT_TYLE_64BIT 0x00000004 #define DLT_TYLE_128BIT 0x00000005 #define DLT_SCOD_ASCII 0x00000000 #define DLT_SCOD_UTF8 0x00008000 #define DLT_SCOD_HEX 0x00010000 #define DLT_SCOD_BIN 0x00018000 /* * Definitions of DLT services. */ #define DLT_SERVICE_ID_CALLSW_CINJECTION 0xFFF enum dlt_services { DLT_SERVICE_ID = 0x00, DLT_SERVICE_ID_SET_LOG_LEVEL = 0x01, DLT_SERVICE_ID_SET_TRACE_STATUS = 0x02, DLT_SERVICE_ID_GET_LOG_INFO = 0x03, DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL = 0x04, DLT_SERVICE_ID_STORE_CONFIG = 0x05, DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT = 0x06, DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS = 0x07, DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH = 0x08, DLT_SERVICE_ID_SET_VERBOSE_MODE = 0x09, DLT_SERVICE_ID_SET_MESSAGE_FILTERING = 0x0A, DLT_SERVICE_ID_SET_TIMING_PACKETS = 0x0B, DLT_SERVICE_ID_GET_LOCAL_TIME = 0x0C, DLT_SERVICE_ID_USE_ECU_ID = 0x0D, DLT_SERVICE_ID_USE_SESSION_ID = 0x0E, DLT_SERVICE_ID_USE_TIMESTAMP = 0x0F, DLT_SERVICE_ID_USE_EXTENDED_HEADER = 0x10, DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL = 0x11, DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS = 0x12, DLT_SERVICE_ID_GET_SOFTWARE_VERSION = 0x13, DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW = 0x14, DLT_SERVICE_ID_LAST_ENTRY }; enum dlt_user_services { DLT_USER_SERVICE_ID = 0xF00, DLT_SERVICE_ID_UNREGISTER_CONTEXT = 0xF01, DLT_SERVICE_ID_CONNECTION_INFO = 0xF02, DLT_SERVICE_ID_TIMEZONE = 0xF03, DLT_SERVICE_ID_MARKER = 0xF04, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE = 0xF05, DLT_SERVICE_ID_PASSIVE_NODE_CONNECT = 0xF06, DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS = 0xF07, DLT_SERVICE_ID_SET_ALL_LOG_LEVEL = 0xF08, DLT_SERVICE_ID_SET_ALL_TRACE_STATUS = 0xF09, DLT_SERVICE_ID_RESERVED_B = 0xF0B, DLT_SERVICE_ID_RESERVED_C = 0xF0C, DLT_SERVICE_ID_RESERVED_D = 0xF0D, DLT_SERVICE_ID_RESERVED_E = 0xF0E, DLT_USER_SERVICE_ID_LAST_ENTRY }; /* Need to be adapted if another service is added */ extern const char *const dlt_service_names[]; extern const char *const dlt_user_service_names[]; extern const char *dlt_get_service_name(unsigned int id); /* * Definitions of DLT service response status */ #define DLT_SERVICE_RESPONSE_OK 0x00 /**< Control message response: OK */ #define DLT_SERVICE_RESPONSE_NOT_SUPPORTED 0x01 /**< Control message response: Not supported */ #define DLT_SERVICE_RESPONSE_ERROR 0x02 /**< Control message response: Error */ #define DLT_SERVICE_RESPONSE_PERM_DENIED 0x03 /**< Control message response: Permission denied */ #define DLT_SERVICE_RESPONSE_WARNING 0x04 /**< Control message response: warning */ #define DLT_SERVICE_RESPONSE_LAST 0x05 /**< Used as max value */ /* * Definitions of DLT service connection state */ #define DLT_CONNECTION_STATUS_DISCONNECTED 0x01 /**< Client is disconnected */ #define DLT_CONNECTION_STATUS_CONNECTED 0x02 /**< Client is connected */ /* * Definitions of DLT GET_LOG_INFO status */ #define GET_LOG_INFO_STATUS_MIN 3 #define GET_LOG_INFO_STATUS_MAX 7 #define GET_LOG_INFO_STATUS_NO_MATCHING_CTX 8 #define GET_LOG_INFO_STATUS_RESP_DATA_OVERFLOW 9 /** \} */ #endif /* DLT_PROTOCOL_H */ dlt-daemon-2.18.10/include/dlt/dlt_shm.h000066400000000000000000000172441446635226000177400ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_shm.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_shm.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #ifndef DLT_SHM_H #define DLT_SHM_H #include #include "dlt_common.h" /** * Default size of shared memory. * size is extended during creation to fit segment size. * client retrieves real size from file descriptor of shared memory. */ #define DLT_SHM_SIZE 100000 typedef struct { int shmfd; /* file descriptor of shared memory */ sem_t *sem; /* pointer to semaphore */ DltBuffer buffer; } DltShm; typedef struct { char head[4]; unsigned char status; int size; } DltShmBlockHead; #define DLT_SHM_SEM_GET(id) sem_wait(id) #define DLT_SHM_SEM_FREE(id) sem_post(id) /** * Initialise the shared memory on the client side. * This function must be called before using further shm functions. * @param buf pointer to shm structure * @param name the name of the shm, must be the same for server and client * @return negative value if there was an error */ extern DltReturnValue dlt_shm_init_client(DltShm *buf, const char *name); /** * Initialise the shared memory on the server side. * This function must be called before using further shm functions. * @param buf pointer to shm structure * @param name the name of the shm, must be the same for server and client * @param size the requested size of the shm * @return negative value if there was an error */ extern DltReturnValue dlt_shm_init_server(DltShm *buf, const char *name, int size); /** * Push data from client onto the shm. * @param buf pointer to shm structure * @param data1 pointer to first data block to be written, null if not used * @param size1 size in bytes of first data block to be written, 0 if not used * @param data2 pointer to second data block to be written, null if not used * @param size2 size in bytes of second data block to be written, 0 if not used * @param data3 pointer to third data block to be written, null if not used * @param size3 size in bytes of third data block to be written, 0 if not used * @return negative value if there was an error */ extern int dlt_shm_push(DltShm *buf, const unsigned char *data1, unsigned int size1, const unsigned char *data2, unsigned int size2, const unsigned char *data3, unsigned int size3); /** * Pull data from shm. * This function should be called from client. * Data is deleted from shm after this call. * @param buf pointer to shm structure * @param data pointer to buffer where data is to be written * @param size maximum size to be written into buffer * @return negative value if there was an error */ extern int dlt_shm_pull(DltShm *buf, unsigned char *data, int size); /** * Copy message from shm. * This function should be called from server. * Data is not deleted from shm after this call. * @param buf pointer to shm structure * @param data pointer to buffer where data is to be written * @param size maximum size to be written into buffer * @return negative value if there was an error */ extern int dlt_shm_copy(DltShm *buf, unsigned char *data, int size); /** * Delete message from shm. * This function should be called from server. * This function should be called after each succesful copy. * @param buf pointer to shm structure * @return negative value if there was an error */ extern int dlt_shm_remove(DltShm *buf); /** * Print information about shm. * @param buf pointer to shm structure */ extern void dlt_shm_info(DltShm *buf); /** * Print status about shm. * @param buf pointer to shm structure */ extern void dlt_shm_status(DltShm *buf); /** * Deinitialise the shared memory on the client side. * @param buf pointer to shm structure * @return negative value if there was an error */ extern DltReturnValue dlt_shm_free_client(DltShm *buf); /** * Returns the total size of the shm. * @param buf pointer to shm structure * @return size of the shared memory. */ extern int dlt_shm_get_total_size(DltShm *buf); /** * Returns the used size in the shm. * @param buf pointer to shm structure * @return size of the shared memory. */ extern int dlt_shm_get_used_size(DltShm *buf); /** * Returns the number of messages in the shm. * @param buf pointer to shm structure * @return size of the shared memory. */ extern int dlt_shm_get_message_count(DltShm *buf); /** * Reset pointers and counters when shm corrupted. * @param buf pointer to shm structure * @return size of the shared memory. */ extern int dlt_shm_reset(DltShm *buf); /** * Recover to find next valid message. * @param buf pointer to shm structure * @return size of the shared memory. */ extern int dlt_shm_recover(DltShm *buf); /** * Deinitialise the shared memory on the server side. * @param buf pointer to shm structure * @param name name of the shared memory * @return negative value if there was an error */ extern DltReturnValue dlt_shm_free_server(DltShm *buf, const char *name); #endif /* DLT_SHM_H */ dlt-daemon-2.18.10/include/dlt/dlt_types.h000066400000000000000000000164311446635226000203120ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_types.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_types.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_TYPES_H #define DLT_TYPES_H #ifdef _MSC_VER typedef __int64 int64_t; typedef __int32 int32_t; typedef __int16 int16_t; typedef __int8 int8_t; typedef unsigned __int64 uint64_t; typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t; typedef unsigned __int8 uint8_t; typedef int pid_t; typedef unsigned int speed_t; # define UINT16_MAX 0xFFFF # include #else # include #endif /** * Definitions of DLT return values */ typedef enum { DLT_RETURN_FILESZERR = -8, DLT_RETURN_LOGGING_DISABLED = -7, DLT_RETURN_USER_BUFFER_FULL = -6, DLT_RETURN_WRONG_PARAMETER = -5, DLT_RETURN_BUFFER_FULL = -4, DLT_RETURN_PIPE_FULL = -3, DLT_RETURN_PIPE_ERROR = -2, DLT_RETURN_ERROR = -1, DLT_RETURN_OK = 0, DLT_RETURN_TRUE = 1 } DltReturnValue; /** * Definitions of DLT log level */ typedef enum { DLT_LOG_DEFAULT = -1, /**< Default log level */ DLT_LOG_OFF = 0x00, /**< Log level off */ DLT_LOG_FATAL = 0x01, /**< fatal system error */ DLT_LOG_ERROR = 0x02, /**< error with impact to correct functionality */ DLT_LOG_WARN = 0x03, /**< warning, correct behaviour could not be ensured */ DLT_LOG_INFO = 0x04, /**< informational */ DLT_LOG_DEBUG = 0x05, /**< debug */ DLT_LOG_VERBOSE = 0x06, /**< highest grade of information */ DLT_LOG_MAX /**< maximum value, used for range check */ } DltLogLevelType; /** * Definitions of DLT Format */ typedef enum { DLT_FORMAT_DEFAULT = 0x00, /**< no sepecial format */ DLT_FORMAT_HEX8 = 0x01, /**< Hex 8 */ DLT_FORMAT_HEX16 = 0x02, /**< Hex 16 */ DLT_FORMAT_HEX32 = 0x03, /**< Hex 32 */ DLT_FORMAT_HEX64 = 0x04, /**< Hex 64 */ DLT_FORMAT_BIN8 = 0x05, /**< Binary 8 */ DLT_FORMAT_BIN16 = 0x06, /**< Binary 16 */ DLT_FORMAT_MAX /**< maximum value, used for range check */ } DltFormatType; /** * Definitions of DLT trace status */ typedef enum { DLT_TRACE_STATUS_DEFAULT = -1, /**< Default trace status */ DLT_TRACE_STATUS_OFF = 0x00, /**< Trace status: Off */ DLT_TRACE_STATUS_ON = 0x01, /**< Trace status: On */ DLT_TRACE_STATUS_MAX /**< maximum value, used for range check */ } DltTraceStatusType; /** * Definitions for dlt_user_trace_network/DLT_TRACE_NETWORK() * as defined in the DLT protocol */ typedef enum { DLT_NW_TRACE_IPC = 0x01, /**< Interprocess communication */ DLT_NW_TRACE_CAN = 0x02, /**< Controller Area Network Bus */ DLT_NW_TRACE_FLEXRAY = 0x03, /**< Flexray Bus */ DLT_NW_TRACE_MOST = 0x04, /**< Media Oriented System Transport Bus */ DLT_NW_TRACE_RESERVED0 = 0x05, DLT_NW_TRACE_RESERVED1 = 0x06, DLT_NW_TRACE_RESERVED2 = 0x07, DLT_NW_TRACE_USER_DEFINED0 = 0x08, DLT_NW_TRACE_USER_DEFINED1 = 0x09, DLT_NW_TRACE_USER_DEFINED2 = 0x0A, DLT_NW_TRACE_USER_DEFINED3 = 0x0B, DLT_NW_TRACE_USER_DEFINED4 = 0x0C, DLT_NW_TRACE_USER_DEFINED5 = 0x0D, DLT_NW_TRACE_USER_DEFINED6 = 0x0E, DLT_NW_TRACE_RESEND = 0x0F, /**< Mark a resend */ DLT_NW_TRACE_MAX /**< maximum value, used for range check */ } DltNetworkTraceType; /** * This are the log modes. */ typedef enum { DLT_USER_MODE_UNDEFINED = -1, DLT_USER_MODE_OFF = 0, DLT_USER_MODE_EXTERNAL, DLT_USER_MODE_INTERNAL, DLT_USER_MODE_BOTH, DLT_USER_MODE_MAX /**< maximum value, used for range check */ } DltUserLogMode; /** * Definition of Maintain Logstorage Loglevel modes */ #define DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_UNDEF -1 #define DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_OFF 0 #define DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_ON 1 typedef float float32_t; typedef double float64_t; #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC /** * Definition Library connection state */ typedef enum { DLT_USER_NOT_CONNECTED = 0, DLT_USER_CONNECTED, DLT_USER_RETRY_CONNECT } DltUserConnectionState; #endif /** * Definition of timestamp types */ typedef enum { DLT_AUTO_TIMESTAMP = 0, DLT_USER_TIMESTAMP } DltTimestampType; #endif /* DLT_TYPES_H */ dlt-daemon-2.18.10/include/dlt/dlt_user.h.in000066400000000000000000001676061446635226000205440ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_user.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #ifndef DLT_USER_H # define DLT_USER_H /** * \defgroup userapi DLT User API * \addtogroup userapi \{ */ #include #ifndef DLT_NETWORK_TRACE_ENABLE #cmakedefine DLT_NETWORK_TRACE_ENABLE #endif #cmakedefine01 DLT_DISABLE_MACRO #ifdef DLT_NETWORK_TRACE_ENABLE # include #else # include # include #endif # include # if !defined (__WIN32__) # include # endif # include "dlt_types.h" # include "dlt_shm.h" #if !DLT_DISABLE_MACRO # include "dlt_user_macros.h" #endif # ifdef __cplusplus extern "C" { # endif # define DLT_USER_BUF_MAX_SIZE 1390 /**< maximum size of each user buffer, also used for injection buffer */ # define DLT_USER_RESENDBUF_MAX_SIZE (DLT_USER_BUF_MAX_SIZE + 100) /**< Size of resend buffer; Max DLT message size is 1390 bytes plus some extra header space */ /* Use a semaphore or mutex from your OS to prevent concurrent access to the DLT buffer. */ #define DLT_SEM_LOCK() do{\ while ((sem_wait(&dlt_mutex) == -1) && (errno == EINTR)) \ continue; /* Restart if interrupted */ \ } while(false) #define DLT_SEM_FREE() { sem_post(&dlt_mutex); } /** * This structure is used for every context used in an application. */ typedef struct { char contextID[DLT_ID_SIZE]; /**< context id */ int32_t log_level_pos; /**< offset in user-application context field */ int8_t *log_level_ptr; /**< pointer to the log level */ int8_t *trace_status_ptr; /**< pointer to the trace status */ uint8_t mcnt; /**< message counter */ } DltContext; /** * This structure is used for context data used in an application. */ typedef struct { DltContext *handle; /**< pointer to DltContext */ unsigned char *buffer; /**< buffer for building log message*/ int32_t size; /**< payload size */ int32_t log_level; /**< log level */ int32_t trace_status; /**< trace status */ int32_t args_num; /**< number of arguments for extended header*/ char *context_description; /**< description of context */ DltTimestampType use_timestamp; /**< whether to use user-supplied timestamps */ uint32_t user_timestamp; /**< user-supplied timestamp to use */ int8_t verbose_mode; /**< verbose mode: 1 enabled, 0 disabled */ } DltContextData; typedef struct { uint32_t service_id; int (*injection_callback)(uint32_t service_id, void *data, uint32_t length); int (*injection_callback_with_id)(uint32_t service_id, void *data, uint32_t length, void *priv_data); void *data; } DltUserInjectionCallback; typedef struct { char contextID[DLT_ID_SIZE]; /**< Context ID */ int8_t log_level; /**< Log level */ int8_t trace_status; /**< Trace status */ void (*log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status); } DltUserLogLevelChangedCallback; /** * This structure is used in a table managing all contexts and the corresponding log levels in an application. */ typedef struct { char contextID[DLT_ID_SIZE]; /**< Context ID */ int8_t log_level; /**< Log level */ int8_t *log_level_ptr; /**< Ptr to the log level */ int8_t trace_status; /**< Trace status */ int8_t *trace_status_ptr; /**< Ptr to the trace status */ char *context_description; /**< description of context */ DltUserInjectionCallback *injection_table; /**< Table with pointer to injection functions and service ids */ uint32_t nrcallbacks; /* Log Level changed callback */ void (*log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status); } dlt_ll_ts_type; /** * @brief holds initial log-level for given appId:ctxId pair */ typedef struct { char appId[DLT_ID_SIZE]; char ctxId[DLT_ID_SIZE]; int8_t ll; } dlt_env_ll_item; /** * @brief holds all initial log-levels given via environment variable DLT_INITIAL_LOG_LEVEL */ typedef struct { dlt_env_ll_item *item; size_t array_size; size_t num_elem; } dlt_env_ll_set; /** * This structure is used once for one application. */ typedef struct { char ecuID[DLT_ID_SIZE]; /**< ECU ID */ char appID[DLT_ID_SIZE]; /**< Application ID */ int dlt_log_handle; /**< Handle to fifo of dlt daemon */ int dlt_user_handle; /**< Handle to own fifo */ #ifdef DLT_NETWORK_TRACE_ENABLE mqd_t dlt_segmented_queue_read_handle; /**< Handle message queue */ mqd_t dlt_segmented_queue_write_handle; /**< Handle message queue */ pthread_t dlt_segmented_nwt_handle; /**< thread handle of segmented sending */ #endif int8_t dlt_is_file; /**< Target of logging: 1 to file, 0 to daemon */ unsigned int filesize_max; /**< Maximum size of existing file in case dlt_is_file=1 */ dlt_ll_ts_type *dlt_ll_ts; /** [MAX_DLT_LL_TS_ENTRIES]; < Internal management struct for all * contexts */ uint32_t dlt_ll_ts_max_num_entries; /**< Maximum number of contexts */ uint32_t dlt_ll_ts_num_entries; /**< Number of used contexts */ int8_t overflow; /**< Overflow marker, set to 1 on overflow, 0 otherwise */ uint32_t overflow_counter; /**< Counts the number of lost messages */ char *application_description; /**< description of application */ DltReceiver receiver; /**< Receiver for internal user-defined messages from daemon */ int8_t verbose_mode; /**< Verbose mode enabled: 1 enabled, 0 disabled */ int8_t use_extended_header_for_non_verbose; /**< Use extended header for non verbose: 1 enabled, 0 disabled */ int8_t with_session_id; /**< Send always session id: 1 enabled, 0 disabled */ int8_t with_timestamp; /**< Send always timestamp: 1 enabled, 0 disabled */ int8_t with_ecu_id; /**< Send always ecu id: 1 enabled, 0 disabled */ int8_t enable_local_print; /**< Local printing of log messages: 1 enabled, 0 disabled */ int8_t local_print_mode; /**< Local print mode, controlled by environment variable */ int8_t disable_injection_msg; /**< Injection msg availability: 1 disabled, 0 enabled (default) */ int8_t log_state; /**< Log state of external connection: * 1 client connected, * 0 not connected, * -1 unknown */ DltBuffer startup_buffer; /**< Ring-buffer for buffering messages during startup and missing connection */ /* Buffer used for resending, locked by DLT semaphore */ uint8_t *resend_buffer; uint32_t timeout_at_exit_handler; /**< timeout used in dlt_user_atexit_blow_out_user_buffer, in 0.1 milliseconds */ dlt_env_ll_set initial_ll_set; # ifdef DLT_SHM_ENABLE DltShm dlt_shm; # endif # ifdef DLT_TEST_ENABLE int corrupt_user_header; int corrupt_message_size; int16_t corrupt_message_size_size; # endif # if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC DltUserConnectionState connection_state; # endif uint16_t log_buf_len; /**< length of message buffer, by default: DLT_USER_BUF_MAX_SIZE */ } DltUser; typedef int (*dlt_injection_callback_id)(uint32_t, void *, uint32_t, void *); typedef int (*dlt_injection_callback)(uint32_t, void *, uint32_t); /************************************************************************************************** * The following API functions define a low level function interface for DLT **************************************************************************************************/ /** * Initialize the generation of a DLT log message (intended for usage in verbose mode) * This function has to be called first, when an application wants to send a new log messages. * Following functions like dlt_user_log_write_string and dlt_user_log_write_finish must only be called, * when return value is bigger than zero. * @param handle pointer to an object containing information about one special logging context * @param log pointer to an object containing information about logging context data * @param loglevel this is the current log level of the log message to be sent * @return Value from DltReturnValue enum, DLT_RETURN_TRUE if log level is matching */ DltReturnValue dlt_user_log_write_start(DltContext *handle, DltContextData *log, DltLogLevelType loglevel); /** * Initialize the generation of a DLT log message (intended for usage in non-verbose mode) * This function has to be called first, when an application wants to send a new log messages. * Following functions like dlt_user_log_write_string and dlt_user_log_write_finish must only be called, * when return value is bigger than zero. * @param handle pointer to an object containing information about one special logging context * @param log pointer to an object containing information about logging context data * @param loglevel this is the current log level of the log message to be sent * @param messageid message id of message * @return Value from DltReturnValue enum, DLT_RETURN_TRUE if log level is matching */ DltReturnValue dlt_user_log_write_start_id(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, uint32_t messageid); /** * Initialize the generation of a DLT log message with given buffer from DLT application. * This can be considered as replacement of dlt_user_log_write_start/dlt_user_log_write_start_id * and other data functions like dlt_user_log_write_string. The fourth, fifth, and sixth arguments * shall be prepared by DLT application; this function is only responsible for checking log * level and setting the given values to context data. This function has to be called first, * when an application is ready to send a new log message with given buffer. This function only * works with combination of dlt_user_log_write_finish_w_given_buffer and the function must only be * called, when return value is bigger than zero. The function only supports verbose mode as of now. * @param handle pointer to an object containing information about one special logging context * @param log pointer to an object containing information about logging context data * @param loglevel this is the current log level of the log message to be sent * @param buffer data with log message * @param size buffer size * @param args_num number of arguments in buffer * @return Value from DltReturnValue enum, DLT_RETURN_TRUE if log level is matching */ DltReturnValue dlt_user_log_write_start_w_given_buffer(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, char *buffer, size_t size, int32_t args_num); /** * Finishing the generation of a DLT log message and sending it to the DLT daemon. * This function has to be called after writing all the log attributes of a log message. * @param log pointer to an object containing information about logging context data * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_finish(DltContextData *log); /** * Finishing the generation of a DLT log message and sending it to the DLT daemon without * freeing log buffer. This function only works with combination of * dlt_user_log_write_start_w_given_buffer. This function has to be called after writing all * the log attributes of a log message. * @param log pointer to an object containing information about logging context data * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_finish_w_given_buffer(DltContextData *log); /** * Write a boolean parameter into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data boolean parameter written into log message (mapped to uint8) * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_bool(DltContextData *log, uint8_t data); /** * Write a boolean parameter with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param data boolean parameter written into log message (mapped to uint8) * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_bool_attr(DltContextData *log, uint8_t data, const char *name); /** * Write a float parameter into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data float32_t parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_float32(DltContextData *log, float32_t data); /** * Write a double parameter into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data float64_t parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_float64(DltContextData *log, double data); /** * Write a float parameter with attributes into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name or @a unit is NULL, this function will add a corresponding attribute field with length 0 * and no content to the message for that attribute. * * @param log pointer to an object containing information about logging context data * @param data float32_t parameter written into log message * @param name the "name" attribute (or NULL) * @param unit the "unit" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_float32_attr(DltContextData *log, float32_t data, const char *name, const char *unit); /** * Write a double parameter with attributes into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name or @a unit is NULL, this function will add a corresponding attribute field with length 0 * and no content to the message for that attribute. * * @param log pointer to an object containing information about logging context data * @param data float64_t parameter written into log message * @param name the "name" attribute (or NULL) * @param unit the "unit" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_float64_attr(DltContextData *log, float64_t data, const char *name, const char *unit); /** * Write a uint parameter into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data unsigned int parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_uint(DltContextData *log, unsigned int data); DltReturnValue dlt_user_log_write_uint8(DltContextData *log, uint8_t data); DltReturnValue dlt_user_log_write_uint16(DltContextData *log, uint16_t data); DltReturnValue dlt_user_log_write_uint32(DltContextData *log, uint32_t data); DltReturnValue dlt_user_log_write_uint64(DltContextData *log, uint64_t data); /** * Write a uint parameter with attributes into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name or @a unit is NULL, this function will add a corresponding attribute field with length 0 * and no content to the message for that attribute. * * @param log pointer to an object containing information about logging context data * @param data unsigned int parameter written into log message * @param name the "name" attribute (or NULL) * @param unit the "unit" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_uint_attr(DltContextData *log, unsigned int data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_uint8_attr(DltContextData *log, uint8_t data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_uint16_attr(DltContextData *log, uint16_t data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_uint32_attr(DltContextData *log, uint32_t data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_uint64_attr(DltContextData *log, uint64_t data, const char *name, const char *unit); /** * Write a uint parameter into a DLT log message. The output will be formatted as given by the parameter type. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data unsigned int parameter written into log message. * @param type The formatting type of the string output. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_uint8_formatted(DltContextData *log, uint8_t data, DltFormatType type); DltReturnValue dlt_user_log_write_uint16_formatted(DltContextData *log, uint16_t data, DltFormatType type); DltReturnValue dlt_user_log_write_uint32_formatted(DltContextData *log, uint32_t data, DltFormatType type); DltReturnValue dlt_user_log_write_uint64_formatted(DltContextData *log, uint64_t data, DltFormatType type); /** * Write a pointer value architecture independent. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data void* parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_ptr(DltContextData *log, void *data); /** * Write a int parameter into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data int parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_int(DltContextData *log, int data); DltReturnValue dlt_user_log_write_int8(DltContextData *log, int8_t data); DltReturnValue dlt_user_log_write_int16(DltContextData *log, int16_t data); DltReturnValue dlt_user_log_write_int32(DltContextData *log, int32_t data); DltReturnValue dlt_user_log_write_int64(DltContextData *log, int64_t data); /** * Write an int parameter with attributes into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name or @a unit is NULL, this function will add a corresponding attribute field with length 0 * and no content to the message for that attribute. * * @param log pointer to an object containing information about logging context data * @param data int parameter written into log message * @param name the "name" attribute (or NULL) * @param unit the "unit" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_int_attr(DltContextData *log, int data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_int8_attr(DltContextData *log, int8_t data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_int16_attr(DltContextData *log, int16_t data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_int32_attr(DltContextData *log, int32_t data, const char *name, const char *unit); DltReturnValue dlt_user_log_write_int64_attr(DltContextData *log, int64_t data, const char *name, const char *unit); /** * Write a null terminated ASCII string into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_string(DltContextData *log, const char *text); /** * Write a potentially non-null-terminated ASCII string into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_string(DltContextData *log, const char *text, uint16_t length); /** * Write a constant null terminated ASCII string into a DLT log message. * In non verbose mode DLT parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_constant_string(DltContextData *log, const char *text); /** * Write a constant, potentially non-null-terminated ASCII string into a DLT log message. * In non verbose mode DLT parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_constant_string(DltContextData *log, const char *text, uint16_t length); /** * Write a null terminated UTF8 string into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_utf8_string(DltContextData *log, const char *text); /** * Write a potentially non-null-terminated UTF8 string into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_utf8_string(DltContextData *log, const char *text, uint16_t length); /** * Write a constant null terminated UTF8 string into a DLT log message. * In non verbose mode DLT parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_constant_utf8_string(DltContextData *log, const char *text); /** * Write a constant, potentially non-null-terminated UTF8 string into a DLT log message. * In non verbose mode DLT parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_constant_utf8_string(DltContextData *log, const char *text, uint16_t length); /** * Write a null-terminated ASCII string with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_string_attr(DltContextData *log, const char *text, const char *name); /** * Write a potentially non-null-terminated ASCII string with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); /** * Write a constant, null-terminated ASCII string with "name" attribute into a DLT log message. * In non-verbose mode, this parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_constant_string_attr(DltContextData *log, const char *text, const char *name); /** * Write a constant, potentially non-null-terminated ASCII string with "name" attribute into a DLT log message. * In non-verbose mode, this parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_constant_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); /** * Write a null-terminated UTF-8 string with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_utf8_string_attr(DltContextData *log, const char *text, const char *name); /** * Write a potentially non-null-terminated UTF-8 string with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); /** * Write a constant, null-terminated UTF8 string with "name" attribute into a DLT log message. * In non-verbose mode, this parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message containing null termination * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_constant_utf8_string_attr(DltContextData *log, const char *text, const char *name); /** * Write a constant, potentially non-null-terminated UTF8 string with "name" attribute into a DLT log message. * In non-verbose mode, this parameter will not be sent at all. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param text pointer to the parameter written into log message * @param length length in bytes of @a text (without any termination character) * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_sized_constant_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); /** * Write a binary memory block into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data pointer to the parameter written into log message. * @param length length in bytes of the parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_raw(DltContextData *log, void *data, uint16_t length); /** * Write a binary memory block into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. * @param log pointer to an object containing information about logging context data * @param data pointer to the parameter written into log message. * @param length length in bytes of the parameter written into log message. * @param type the format information. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_raw_formatted(DltContextData *log, void *data, uint16_t length, DltFormatType type); /** * Write a binary memory block with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param data pointer to the parameter written into log message. * @param length length in bytes of the parameter written into log message * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_raw_attr(DltContextData *log, const void *data, uint16_t length, const char *name); /** * Write a binary memory block with "name" attribute into a DLT log message. * dlt_user_log_write_start has to be called before adding any parameters to the log message. * Finish building a log message by calling dlt_user_log_write_finish. * * If @a name is NULL, this function will add an attribute field with length 0 * and no content to the message. * * @param log pointer to an object containing information about logging context data * @param data pointer to the parameter written into log message. * @param length length in bytes of the parameter written into log message * @param type the format information * @param name the "name" attribute (or NULL) * @return value from DltReturnValue enum */ DltReturnValue dlt_user_log_write_raw_formatted_attr(DltContextData *log, const void *data, uint16_t length, DltFormatType type, const char *name); /** * Trace network message * @param handle pointer to an object containing information about one special logging context * @param nw_trace_type type of network trace (DLT_NW_TRACE_IPC, DLT_NW_TRACE_CAN, DLT_NW_TRACE_FLEXRAY, or DLT_NW_TRACE_MOST) * @param header_len length of network message header * @param header pointer to network message header * @param payload_len length of network message payload * @param payload pointer to network message payload * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload); /** * Trace network message, truncated if necessary. * @param handle pointer to an object containing information about logging context * @param nw_trace_type type of network trace (DLT_NW_TRACE_IPC, DLT_NW_TRACE_CAN, DLT_NW_TRACE_FLEXRAY, or DLT_NW_TRACE_MOST) * @param header_len length of network message header * @param header pointer to network message header * @param payload_len length of network message payload * @param payload pointer to network message payload * @param allow_truncate Set to > 0 to allow truncating of the message if it is too large. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate); /** * Trace network message in segmented asynchronous mode. * The sending of the data is done in a separate thread. * Please note that handle must exist for the lifetime of the application, because * data chunks are sent asynchronously in undetermined future time. * @param handle pointer to an object containing information about logging context * @param nw_trace_type type of network trace (DLT_NW_TRACE_IPC, DLT_NW_TRACE_CAN, DLT_NW_TRACE_FLEXRAY, or DLT_NW_TRACE_MOST) * @param header_len length of network message header * @param header pointer to network message header * @param payload_len length of network message payload * @param payload pointer to network message payload * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload); /************************************************************************************************** * The following API functions define a high level function interface for DLT **************************************************************************************************/ /** * Initialize the user lib communication with daemon. * This function has to be called first, before using any DLT user lib functions. * @return Value from DltReturnValue enum */ DltReturnValue dlt_init(); /** * Initialize the user lib writing only to file. * This function has to be called first, before using any DLT user lib functions. * @param name name of an optional log file * @return Value from DltReturnValue enum */ DltReturnValue dlt_init_file(const char *name); /** * Set maximum file size if lib is configured to write only to file. * This function has to be called after dlt_init_file(). * @param filesize maximum file size * @return Value from DltReturnValue enum */ DltReturnValue dlt_set_filesize_max(unsigned int filesize); /** * Terminate the user lib. * This function has to be called when finishing using the DLT user lib. * @return Value from DltReturnValue enum */ DltReturnValue dlt_free(); /** * Check the library version of DLT library. * @param user_major_version the major version to be compared * @param user_minor_version the minor version to be compared * @return Value from DltReturnValue enum, DLT_RETURN_ERROR if there is a mismatch */ DltReturnValue dlt_check_library_version(const char *user_major_version, const char *user_minor_version); /** * Register an application in the daemon. * @param apid four byte long character array with the application id * @param description long name of the application * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_app(const char *apid, const char *description); /** * Unregister an application in the daemon. * This function has to be called when finishing using an application. * @return Value from DltReturnValue enum */ DltReturnValue dlt_unregister_app(void); /** * Unregister an application in the daemon and also flushes the buffered logs. * This function has to be called when finishing using an application. * @return Value from DltReturnValue enum */ DltReturnValue dlt_unregister_app_flush_buffered_logs(void); /** * Get the application id * @param four byte long character array to store the application id * @return Value from DltReturnValue enum */ DltReturnValue dlt_get_appid(char *appid); /** * Register a context in the daemon. * This function has to be called before first usage of the context. * @param handle pointer to an object containing information about one special logging context * @param contextid four byte long character array with the context id * @param description long name of the context * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_context(DltContext *handle, const char *contextid, const char *description); /** * Register a context in the daemon with pre-defined log level and pre-defined trace status. * This function has to be called before first usage of the context. * @param handle pointer to an object containing information about one special logging context * @param contextid four byte long character array with the context id * @param description long name of the context * @param loglevel This is the log level to be pre-set for this context * (DLT_LOG_DEFAULT is not allowed here) * @param tracestatus This is the trace status to be pre-set for this context * (DLT_TRACE_STATUS_DEFAULT is not allowed here) * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char *description, int loglevel, int tracestatus); /** * Register a context in the daemon with log level changed callback fn. * This function is introduced to avoid missing of LL change callback during registration * @param handle pointer to an object containing information about one special logging context * @param contextid four byte long character array with the context id * @param description long name of the context * @param *dlt_log_level_changed_callback This is the fn which will be called when log level is changed * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_context_llccb(DltContext *handle, const char *contextid, const char *description, void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status)); /** * Unregister a context in the DLT daemon. * This function has to be called when finishing using a context. * @param handle pointer to an object containing information about one special logging context * @return Value from DltReturnValue enum */ DltReturnValue dlt_unregister_context(DltContext *handle); /** * Set maximum timeout for re-sending at exit * @param timeout_in_milliseconds maximum time to wait until giving up re-sending, default 10000 (equals to 10 seconds) */ int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds); /** * Set the logging mode used by the daemon. * The logging mode is stored persistantly by the daemon. * @see DltUserLogMode * @param mode the new logging mode used by the daemon: off, extern, internal, both. * @return Value from DltReturnValue enum */ DltReturnValue dlt_set_log_mode(DltUserLogMode mode); /** * Get the state of the connected client to the daemon. * The user application gets a message, when client is connected or disconnected. * This value contains the last state. * It needs some time until the application gets state from the daemon. * Until then the state is "unknown state". * @return -1 = unknown state, 0 = client not connected, 1 = client connected */ int dlt_get_log_state(); /** * Register callback function called when injection message was received * @param handle pointer to an object containing information about one special logging context * @param service_id the service id to be waited for * @param (*dlt_injection_callback) function pointer to callback function * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_injection_callback(DltContext *handle, uint32_t service_id, int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length)); /** * Register callback function with private data called when injection message was received * @param handle pointer to an object containing information about one special logging context * @param service_id the service id to be waited for * @param (*dlt_injection_callback) function pointer to callback function * @param priv private data * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_injection_callback_with_id(DltContext *handle, uint32_t service_id, int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length, void *priv_data), void *priv); /** * Register callback function called when log level of context was changed * @param handle pointer to an object containing information about one special logging context * @param (*dlt_log_level_changed_callback) function pointer to callback function * @return Value from DltReturnValue enum */ DltReturnValue dlt_register_log_level_changed_callback(DltContext *handle, void (*dlt_log_level_changed_callback)( char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status)); /** * Switch to verbose mode * @return Value from DltReturnValue enum */ DltReturnValue dlt_verbose_mode(void); /** * Check the version of dlt library with library version used of the application. * @param user_major_version version number of application - see dlt_version.h * @param user_minor_version version number of application - see dlt_version.h * @return Value from DltReturnValue enum, DLT_RETURN_ERROR if there is a mismatch */ DltReturnValue dlt_user_check_library_version(const char *user_major_version, const char *user_minor_version); /** * Switch to non-verbose mode * * This does not force all messages to be sent as Non-Verbose ones, as that does not make much sense. * Instead, it +allows+ the sending of both Verbose and Non-Verbose messages, depending on which APIs * are being called. */ DltReturnValue dlt_nonverbose_mode(void); /** * Use extended header in non verbose mode. * Enabled by default. * @param use_extended_header_for_non_verbose Use extended header for non verbose mode if true * @return Value from DltReturnValue enum */ DltReturnValue dlt_use_extended_header_for_non_verbose(int8_t use_extended_header_for_non_verbose); /** * Send session id configuration. * Enabled by default. * @param with_session_id Send session id in each message if enabled * @return Value from DltReturnValue enum */ DltReturnValue dlt_with_session_id(int8_t with_session_id); /** * Send timestamp configuration. * Enabled by default. * @param with_timestamp Send timestamp id in each message if enabled * @return Value from DltReturnValue enum */ DltReturnValue dlt_with_timestamp(int8_t with_timestamp); /** * Send ecu id configuration. * Enabled by default. * @param with_ecu_id Send ecu id in each message if enabled * @return Value from DltReturnValue enum */ DltReturnValue dlt_with_ecu_id(int8_t with_ecu_id); /** * Set maximum logged log level and trace status of application * * @param loglevel This is the log level to be set for the whole application * @param tracestatus This is the trace status to be set for the whole application * @return Value from DltReturnValue enum */ DltReturnValue dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus); /** * @brief adjust log-level based on values given through environment * * Iterate over the set of items, and find the best match. * For any item that matches, the one with the highest priority is selected and that * log-level is returned. * * Priorities are determined as follows: * - no apid, no ctid only ll given in item: use ll with prio 1 * - no apid, ctid matches: use ll with prio 2 * - no ctid, apid matches: use ll with prio 3 * - apid, ctid matches: use ll with prio 4 * * @param ll_set * @param apid * @param ctid * @param ll * If no item matches or in case of error, the original log-level (\param ll) is returned */ int dlt_env_adjust_ll_from_env(dlt_env_ll_set const *const ll_set, char const *const apid, char const *const ctid, int const ll); /** * @brief extract log-level settings from given string * * Scan \param env for setttings like apid:ctid:log-level and store them * in given \param ll_set * * @param env reference to a string to be parsed, after parsing env will point after the last parse character * @param ll_set set of log-level extracted from given string * * @return 0 on success * @return -1 on failure */ int dlt_env_extract_ll_set(char **const env, dlt_env_ll_set *const ll_set); void dlt_env_free_ll_set(dlt_env_ll_set *const ll_set); /** * Enable local printing of messages * @return Value from DltReturnValue enum */ DltReturnValue dlt_enable_local_print(void); /** * Disable local printing of messages * @return Value from DltReturnValue enum */ DltReturnValue dlt_disable_local_print(void); /** * Write a null terminated ASCII string into a DLT log message. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @param text pointer to the ASCII string written into log message containing null termination. * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_string(DltContext *handle, DltLogLevelType loglevel, const char *text); /** * Write a null terminated ASCII string and an integer value into a DLT log message. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @param text pointer to the ASCII string written into log message containing null termination. * @param data integer value written into the log message * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_string_int(DltContext *handle, DltLogLevelType loglevel, const char *text, int data); /** * Write a null terminated ASCII string and an unsigned integer value into a DLT log message. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @param text pointer to the ASCII string written into log message containing null termination. * @param data unsigned integer value written into the log message * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_string_uint(DltContext *handle, DltLogLevelType loglevel, const char *text, unsigned int data); /** * Write an integer value into a DLT log message. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @param data integer value written into the log message * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_int(DltContext *handle, DltLogLevelType loglevel, int data); /** * Write an unsigned integer value into a DLT log message. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @param data unsigned integer value written into the log message * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_uint(DltContext *handle, DltLogLevelType loglevel, unsigned int data); /** * Write an unsigned integer value into a DLT log message. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @param data pointer to the parameter written into log message. * @param length length in bytes of the parameter written into log message. * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_raw(DltContext *handle, DltLogLevelType loglevel, void *data, uint16_t length); /** * Write marker message to DLT. * @return Value from DltReturnValue enum */ DltReturnValue dlt_log_marker(); /** * Get the total size and available size of the shared memory buffer between daemon and applications. * This information is useful to control the flow control between applications and daemon. * For example only 50% of the buffer should be used for file transfer. * @param total_size total size of buffer in bytes * @param used_size used size of buffer in bytes * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_check_buffer(int *total_size, int *used_size); /** * Try to resend log message in the user buffer. Stops if the dlt_uptime is bigger than * dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT. A pause between the resending * attempts can be defined with DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP * @return number of messages in the user buffer */ int dlt_user_atexit_blow_out_user_buffer(void); /** * Try to resend log message in the user buffer. * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_resend_buffer(void); /** * Checks the log level passed by the log function if enabled for that context or not. * This function can be called by applications before generating their logs. * Also called before writing new log messages. * @param handle pointer to an object containing information about one special logging context * @param loglevel this is the current log level of the log message to be sent * @return Value from DltReturnValue enum, DLT_RETURN_TRUE if log level is enabled */ static inline DltReturnValue dlt_user_is_logLevel_enabled(DltContext *handle, DltLogLevelType loglevel) { if ((loglevel < DLT_LOG_DEFAULT) || (loglevel >= DLT_LOG_MAX)) return DLT_RETURN_WRONG_PARAMETER; if ((handle == NULL) || (handle->log_level_ptr == NULL)) return DLT_RETURN_WRONG_PARAMETER; if ((loglevel <= (DltLogLevelType)(*(handle->log_level_ptr))) && (loglevel != DLT_LOG_OFF)) return DLT_RETURN_TRUE; return DLT_RETURN_LOGGING_DISABLED; } # ifdef DLT_TEST_ENABLE void dlt_user_test_corrupt_user_header(int enable); void dlt_user_test_corrupt_message_size(int enable, int16_t size); # endif /* DLT_TEST_ENABLE */ # ifdef __cplusplus } # endif /** \} */ #endif /* DLT_USER_H */ dlt-daemon-2.18.10/include/dlt/dlt_user_macros.h000066400000000000000000000755121446635226000214750ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user_macros.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_user_macros.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1515 $ * $LastChangedDate: 2010-12-13 09:18:54 +0100 (Mon, 13 Dec 2010) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #ifndef DLT_USER_MACROS_H #define DLT_USER_MACROS_H #include "dlt_version.h" #include "dlt_types.h" #include /** * \defgroup userapi DLT User API * \addtogroup userapi \{ */ /************************************************************************************************** * The folowing macros define a macro interface for DLT **************************************************************************************************/ /** * Create an object for a new context. * This macro has to be called first for every. * @param CONTEXT object containing information about one special logging context * @note To avoid the MISRA warning "Null statement is located close to other code or comments" * remove the semicolon when using the macro. * Example: DLT_DECLARE_CONTEXT(hContext) */ #define DLT_DECLARE_CONTEXT(CONTEXT) \ DltContext CONTEXT; /** * Use an object of a new context created in another module. * This macro has to be called first for every. * @param CONTEXT object containing information about one special logging context * @note To avoid the MISRA warning "Null statement is located close to other code or comments" * remove the semicolon when using the macro. * Example: DLT_IMPORT_CONTEXT(hContext) */ #define DLT_IMPORT_CONTEXT(CONTEXT) \ extern DltContext CONTEXT; /** * Register application. * @param APPID application id with maximal four characters * @param DESCRIPTION ASCII string containing description */ #define DLT_REGISTER_APP(APPID, DESCRIPTION) do { \ (void)dlt_check_library_version(_DLT_PACKAGE_MAJOR_VERSION, _DLT_PACKAGE_MINOR_VERSION); \ (void)dlt_register_app(APPID, DESCRIPTION); } while(false) /** * Unregister application. */ #define DLT_UNREGISTER_APP() do { \ (void)dlt_unregister_app(); } while(false) /** * Unregister application and flush the logs buffered in startup buffer if any. */ #define DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS() do { \ (void)dlt_unregister_app_flush_buffered_logs(); } while(false) /** * To Get application ID. * @Param APPID character pointer of minimum 4 bytes */ #define DLT_GET_APPID(APPID) do{\ dlt_get_appid(APPID);} while(false) /** * Register context (with default log level and default trace status) * @param CONTEXT object containing information about one special logging context * @param CONTEXTID context id with maximal four characters * @param DESCRIPTION ASCII string containing description */ #define DLT_REGISTER_CONTEXT(CONTEXT, CONTEXTID, DESCRIPTION) do { \ (void)dlt_register_context(&(CONTEXT), CONTEXTID, DESCRIPTION); } while (false) /** * Register context with pre-defined log level and pre-defined trace status. * @param CONTEXT object containing information about one special logging context * @param CONTEXTID context id with maximal four characters * @param DESCRIPTION ASCII string containing description * @param LOGLEVEL log level to be pre-set for this context * (DLT_LOG_DEFAULT is not allowed here) * @param TRACESTATUS trace status to be pre-set for this context * (DLT_TRACE_STATUS_DEFAULT is not allowed here) */ #define DLT_REGISTER_CONTEXT_LL_TS(CONTEXT, CONTEXTID, DESCRIPTION, LOGLEVEL, TRACESTATUS) do { \ (void)dlt_register_context_ll_ts(&(CONTEXT), CONTEXTID, DESCRIPTION, LOGLEVEL, TRACESTATUS); } while (false) /** * Register context (with default log level and default trace status and log level change callback) * @param CONTEXT object containing information about one special logging context * @param CONTEXTID context id with maximal four characters * @param DESCRIPTION ASCII string containing description * @param CBK log level change callback to be registered */ #define DLT_REGISTER_CONTEXT_LLCCB(CONTEXT, CONTEXTID, DESCRIPTION, CBK) do { \ (void)dlt_register_context_llccb(&(CONTEXT), CONTEXTID, DESCRIPTION, CBK); } while(false) /** * Unregister context. * @param CONTEXT object containing information about one special logging context */ #define DLT_UNREGISTER_CONTEXT(CONTEXT) do { \ (void)dlt_unregister_context(&(CONTEXT)); } while(false) /** * Register callback function called when injection message was received * @param CONTEXT object containing information about one special logging context * @param SERVICEID service id of the injection message * @param CALLBACK function pointer to callback function */ #define DLT_REGISTER_INJECTION_CALLBACK(CONTEXT, SERVICEID, CALLBACK) do { \ (void)dlt_register_injection_callback(&(CONTEXT), SERVICEID, CALLBACK); } while(false) /** * Register callback function called when injection message was received * @param CONTEXT object containing information about one special logging context * @param SERVICEID service id of the injection message * @param CALLBACK function pointer to callback function * @param PRIV_DATA data specific to context */ #define DLT_REGISTER_INJECTION_CALLBACK_WITH_ID(CONTEXT, SERVICEID, CALLBACK, PRIV_DATA) do { \ (void)dlt_register_injection_callback_with_id(&(CONTEXT), SERVICEID, CALLBACK, PRIV_DATA); } while(false) /** * Register callback function called when log level of context was changed * @param CONTEXT object containing information about one special logging context * @param CALLBACK function pointer to callback function */ #define DLT_REGISTER_LOG_LEVEL_CHANGED_CALLBACK(CONTEXT, CALLBACK) do { \ (void)dlt_register_log_level_changed_callback(&(CONTEXT), CALLBACK); } while(false) /** * Send log message with variable list of messages (intended for verbose mode) * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param ... variable list of arguments * @note To avoid the MISRA warning "The comma operator has been used outside a for statement" * use a semicolon instead of a comma to separate the __VA_ARGS__. * Example: DLT_LOG(hContext, DLT_LOG_INFO, DLT_STRING("Hello world"); DLT_INT(123)); */ #ifdef _MSC_VER /* DLT_LOG is not supported by MS Visual C++ */ /* use function interface instead */ #else # define DLT_LOG(CONTEXT, LOGLEVEL, ...) \ do { \ DltContextData log_local; \ int dlt_local; \ dlt_local = dlt_user_log_write_start(&CONTEXT, &log_local, LOGLEVEL); \ if (dlt_local == DLT_RETURN_TRUE) \ { \ __VA_ARGS__; \ (void)dlt_user_log_write_finish(&log_local); \ } \ } while (false) #endif /** * Send log message with variable list of messages (intended for verbose mode) * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param TS timestamp to be used for log message * @param ... variable list of arguments * @note To avoid the MISRA warning "The comma operator has been used outside a for statement" * use a semicolon instead of a comma to separate the __VA_ARGS__. * Example: DLT_LOG_TS(hContext, DLT_LOG_INFO, timestamp, DLT_STRING("Hello world"); DLT_INT(123)); */ #ifdef _MSC_VER /* DLT_LOG_TS is not supported by MS Visual C++ */ /* use function interface instead */ #else # define DLT_LOG_TS(CONTEXT, LOGLEVEL, TS, ...) \ do { \ DltContextData log_local; \ int dlt_local; \ dlt_local = dlt_user_log_write_start(&CONTEXT, &log_local, LOGLEVEL); \ if (dlt_local == DLT_RETURN_TRUE) \ { \ __VA_ARGS__; \ log_local.use_timestamp = DLT_USER_TIMESTAMP; \ log_local.user_timestamp = (uint32_t) TS; \ (void)dlt_user_log_write_finish(&log_local); \ } \ } while (false) #endif /** * Send log message with variable list of messages (intended for non-verbose mode) * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param MSGID the message id of log message * @param ... variable list of arguments * calls to DLT_STRING(), DLT_BOOL(), DLT_FLOAT32(), DLT_FLOAT64(), * DLT_INT(), DLT_UINT(), DLT_RAW() * @note To avoid the MISRA warning "The comma operator has been used outside a for statement" * use a semicolon instead of a comma to separate the __VA_ARGS__. * Example: DLT_LOG_ID(hContext, DLT_LOG_INFO, 0x1234, DLT_STRING("Hello world"); DLT_INT(123)); */ #ifdef _MSC_VER /* DLT_LOG_ID is not supported by MS Visual C++ */ /* use function interface instead */ #else # define DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ...) \ do { \ DltContextData log_local; \ int dlt_local; \ dlt_local = dlt_user_log_write_start_id(&CONTEXT, &log_local, LOGLEVEL, MSGID); \ if (dlt_local == DLT_RETURN_TRUE) \ { \ __VA_ARGS__; \ (void)dlt_user_log_write_finish(&log_local); \ } \ } while(false) #endif /** * Send log message with variable list of messages (intended for non-verbose mode) * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param MSGID the message id of log message * @param TS timestamp to be used for log message * @param ... variable list of arguments * calls to DLT_STRING(), DLT_BOOL(), DLT_FLOAT32(), DLT_FLOAT64(), * DLT_INT(), DLT_UINT(), DLT_RAW() * @note To avoid the MISRA warning "The comma operator has been used outside a for statement" * use a semicolon instead of a comma to separate the __VA_ARGS__. * Example: DLT_LOG_ID_TS(hContext, DLT_LOG_INFO, 0x1234, timestamp, DLT_STRING("Hello world"); DLT_INT(123)); */ #ifdef _MSC_VER /* DLT_LOG_ID_TS is not supported by MS Visual C++ */ /* use function interface instead */ #else # define DLT_LOG_ID_TS(CONTEXT, LOGLEVEL, MSGID, TS, ...) \ do { \ DltContextData log_local; \ int dlt_local; \ dlt_local = dlt_user_log_write_start_id(&CONTEXT, &log_local, LOGLEVEL, MSGID); \ if (dlt_local == DLT_RETURN_TRUE) \ { \ __VA_ARGS__; \ log_local.use_timestamp = DLT_USER_TIMESTAMP; \ log_local.user_timestamp = (uint32_t) TS; \ (void)dlt_user_log_write_finish(&log_local); \ } \ } while(false) #endif /** * Add string parameter to the log messsage. * @param TEXT ASCII string */ #define DLT_STRING(TEXT) \ (void)dlt_user_log_write_string(&log_local, TEXT) /** * Add string parameter with given length to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT ASCII string * @param LEN length in bytes to take from @a TEXT */ #define DLT_SIZED_STRING(TEXT, LEN) \ (void)dlt_user_log_write_sized_string(&log_local, TEXT, LEN) /** * Add constant string parameter to the log messsage. * @param TEXT Constant ASCII string */ #define DLT_CSTRING(TEXT) \ (void)dlt_user_log_write_constant_string(&log_local, TEXT) /** * Add constant string parameter with given length to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT Constant ASCII string * @param LEN length in bytes to take from @a TEXT */ #define DLT_SIZED_CSTRING(TEXT, LEN) \ (void)dlt_user_log_write_sized_constant_string(&log_local, TEXT, LEN) /** * Add utf8-encoded string parameter to the log messsage. * @param TEXT UTF8-encoded string */ #define DLT_UTF8(TEXT) \ (void)dlt_user_log_write_utf8_string(&log_local, TEXT) /** * Add utf8-encoded string parameter with given length to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT UTF8-encoded string * @param LEN length in bytes to take from @a TEXT */ #define DLT_SIZED_UTF8(TEXT, LEN) \ (void)dlt_user_log_write_sized_utf8_string(&log_local, TEXT, LEN) /** * Add constant utf8-encoded string parameter to the log messsage. * @param TEXT Constant UTF8-encoded string */ #define DLT_CUTF8(TEXT) \ (void)dlt_user_log_write_constant_utf8_string(&log_local, TEXT) /** * Add constant utf8-encoded string parameter with given length to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT Constant UTF8-encoded string * @param LEN length in bytes to take from @a TEXT */ #define DLT_SIZED_CUTF8(TEXT, LEN) \ (void)dlt_user_log_write_sized_constant_utf8_string(&log_local, TEXT, LEN) /** * Add string parameter with "name" attribute to the log messsage. * @param TEXT ASCII string * @param NAME "name" attribute */ #define DLT_STRING_ATTR(TEXT, NAME) \ (void)dlt_user_log_write_string_attr(&log_local, TEXT, NAME) /** * Add string parameter with given length and "name" attribute to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT ASCII string * @param LEN length in bytes to take from @a TEXT * @param NAME "name" attribute */ #define DLT_SIZED_STRING_ATTR(TEXT, LEN, NAME) \ (void)dlt_user_log_write_sized_string_attr(&log_local, TEXT, LEN, NAME) /** * Add constant string parameter with "name" attribute to the log messsage. * @param TEXT Constant ASCII string * @param NAME "name" attribute */ #define DLT_CSTRING_ATTR(TEXT, NAME) \ (void)dlt_user_log_write_constant_string_attr(&log_local, TEXT, NAME) /** * Add constant string parameter with given length and "name" attribute to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT Constant ASCII string * @param LEN length in bytes to take from @a TEXT * @param NAME "name" attribute */ #define DLT_SIZED_CSTRING_ATTR(TEXT, LEN, NAME) \ (void)dlt_user_log_write_sized_constant_string_attr(&log_local, TEXT, LEN, NAME) /** * Add utf8-encoded string parameter with "name" attribute to the log messsage. * @param TEXT UTF8-encoded string * @param NAME "name" attribute */ #define DLT_UTF8_ATTR(TEXT, NAME) \ (void)dlt_user_log_write_utf8_string_attr(&log_local, TEXT, NAME) /** * Add utf8-encoded string parameter with given length and "name" attribute to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT UTF8-encoded string * @param LEN length in bytes to take from @a TEXT * @param NAME "name" attribute */ #define DLT_SIZED_UTF8_ATTR(TEXT, LEN, NAME) \ (void)dlt_user_log_write_sized_utf8_string_attr(&log_local, TEXT, LEN, ATTR) /** * Add constant utf8-encoded string parameter with "name" attribute to the log messsage. * @param TEXT Constant UTF8-encoded string * @param NAME "name" attribute */ #define DLT_CUTF8_ATTR(TEXT, NAME) \ (void)dlt_user_log_write_constant_utf8_string_attr(&log_local, TEXT, NAME) /** * Add constant utf8-encoded string parameter with given length and "name" attribute to the log messsage. * The string in @a TEXT does not need to be null-terminated, but * the copied string will be null-terminated at its destination * in the message buffer. * @param TEXT Constant UTF8-encoded string * @param LEN length in bytes to take from @a TEXT * @param NAME "name" attribute */ #define DLT_SIZED_CUTF8_ATTR(TEXT, LEN, NAME) \ (void)dlt_user_log_write_sized_constant_utf8_string_attr(&log_local, TEXT, LEN, NAME) /** * Add boolean parameter to the log messsage. * @param BOOL_VAR Boolean value (mapped to uint8) */ #define DLT_BOOL(BOOL_VAR) \ (void)dlt_user_log_write_bool(&log_local, BOOL_VAR) /** * Add boolean parameter with "name" attribute to the log messsage. * @param BOOL_VAR Boolean value (mapped to uint8) * @param NAME "name" attribute */ #define DLT_BOOL_ATTR(BOOL_VAR, NAME) \ (void)dlt_user_log_write_bool_attr(&log_local, BOOL_VAR, NAME) /** * Add float32 parameter to the log messsage. * @param FLOAT32_VAR Float32 value (mapped to float) */ #define DLT_FLOAT32(FLOAT32_VAR) \ (void)dlt_user_log_write_float32(&log_local, FLOAT32_VAR) /** * Add float64 parameter to the log messsage. * @param FLOAT64_VAR Float64 value (mapped to double) */ #define DLT_FLOAT64(FLOAT64_VAR) \ (void)dlt_user_log_write_float64(&log_local, FLOAT64_VAR) /** * Add float32 parameter with attributes to the log messsage. * @param FLOAT32_VAR Float32 value (mapped to float) * @param NAME "name" attribute * @param UNIT "unit" attribute */ #define DLT_FLOAT32_ATTR(FLOAT32_VAR, NAME, UNIT) \ (void)dlt_user_log_write_float32_attr(&log_local, FLOAT32_VAR, NAME, UNIT) /** * Add float64 parameter with attributes to the log messsage. * @param FLOAT64_VAR Float64 value (mapped to double) * @param NAME "name" attribute * @param UNIT "unit" attribute */ #define DLT_FLOAT64_ATTR(FLOAT64_VAR, NAME, UNIT) \ (void)dlt_user_log_write_float64_attr(&log_local, FLOAT64_VAR, NAME, UNIT) /** * Add integer parameter to the log messsage. * @param INT_VAR integer value */ #define DLT_INT(INT_VAR) \ (void)dlt_user_log_write_int(&log_local, INT_VAR) #define DLT_INT8(INT_VAR) \ (void)dlt_user_log_write_int8(&log_local, INT_VAR) #define DLT_INT16(INT_VAR) \ (void)dlt_user_log_write_int16(&log_local, INT_VAR) #define DLT_INT32(INT_VAR) \ (void)dlt_user_log_write_int32(&log_local, INT_VAR) #define DLT_INT64(INT_VAR) \ (void)dlt_user_log_write_int64(&log_local, INT_VAR) /** * Add integer parameter with attributes to the log messsage. * @param INT_VAR integer value * @param NAME "name" attribute * @param UNIT "unit" attribute */ #define DLT_INT_ATTR(INT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_int_attr(&log_local, INT_VAR, NAME, UNIT) #define DLT_INT8_ATTR(INT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_int8_attr(&log_local, INT_VAR, NAME, UNIT) #define DLT_INT16_ATTR(INT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_int16_attr(&log_local, INT_VAR, NAME, UNIT) #define DLT_INT32_ATTR(INT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_int32_attr(&log_local, INT_VAR, NAME, UNIT) #define DLT_INT64_ATTR(INT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_int64_attr(&log_local, INT_VAR, NAME, UNIT) /** * Add unsigned integer parameter to the log messsage. * @param UINT_VAR unsigned integer value */ #define DLT_UINT(UINT_VAR) \ (void)dlt_user_log_write_uint(&log_local, UINT_VAR) #define DLT_UINT8(UINT_VAR) \ (void)dlt_user_log_write_uint8(&log_local, UINT_VAR) #define DLT_UINT16(UINT_VAR) \ (void)dlt_user_log_write_uint16(&log_local, UINT_VAR) #define DLT_UINT32(UINT_VAR) \ (void)dlt_user_log_write_uint32(&log_local, UINT_VAR) #define DLT_UINT64(UINT_VAR) \ (void)dlt_user_log_write_uint64(&log_local, UINT_VAR) /** * Add unsigned integer parameter with attributes to the log messsage. * @param UINT_VAR unsigned integer value * @param NAME "name" attribute * @param UNIT "unit" attribute */ #define DLT_UINT_ATTR(UINT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_uint_attr(&log_local, UINT_VAR, NAME, UNIT) #define DLT_UINT8_ATTR(UINT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_uint8_attr(&log_local, UINT_VAR, NAME, UNIT) #define DLT_UINT16_ATTR(UINT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_uint16_attr(&log_local, UINT_VAR, NAME, UNIT) #define DLT_UINT32_ATTR(UINT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_uint32_attr(&log_local, UINT_VAR, NAME, UNIT) #define DLT_UINT64_ATTR(UINT_VAR, NAME, UNIT) \ (void)dlt_user_log_write_uint64_attr(&log_local, UINT_VAR, NAME, UNIT) /** * Add binary memory block to the log messages. * @param BUF pointer to memory block * @param LEN length of memory block */ #define DLT_RAW(BUF, LEN) \ (void)dlt_user_log_write_raw(&log_local, BUF, LEN) #define DLT_HEX8(UINT_VAR) \ (void)dlt_user_log_write_uint8_formatted(&log_local, UINT_VAR, DLT_FORMAT_HEX8) #define DLT_HEX16(UINT_VAR) \ (void)dlt_user_log_write_uint16_formatted(&log_local, UINT_VAR, DLT_FORMAT_HEX16) #define DLT_HEX32(UINT_VAR) \ (void)dlt_user_log_write_uint32_formatted(&log_local, UINT_VAR, DLT_FORMAT_HEX32) #define DLT_HEX64(UINT_VAR) \ (void)dlt_user_log_write_uint64_formatted(&log_local, UINT_VAR, DLT_FORMAT_HEX64) #define DLT_BIN8(UINT_VAR) \ (void)dlt_user_log_write_uint8_formatted(&log_local, UINT_VAR, DLT_FORMAT_BIN8) #define DLT_BIN16(UINT_VAR) \ (void)dlt_user_log_write_uint16_formatted(&log_local, UINT_VAR, DLT_FORMAT_BIN16) /** * Add binary memory block with "name" attribute to the log messages. * @param BUF pointer to memory block * @param LEN length of memory block * @param NAME "name" attribute */ #define DLT_RAW_ATTR(BUF, LEN, NAME) \ (void)dlt_user_log_write_raw_attr(&log_local, BUF, LEN, NAME) /** * Architecture independent macro to print pointers */ #define DLT_PTR(PTR_VAR) \ (void)dlt_user_log_write_ptr(&log_local, PTR_VAR) /** * Trace network message * @param CONTEXT object containing information about one special logging context * @param TYPE type of network trace message * @param HEADERLEN length of network message header * @param HEADER pointer to network message header * @param PAYLOADLEN length of network message payload * @param PAYLOAD pointer to network message payload */ #define DLT_TRACE_NETWORK(CONTEXT, TYPE, HEADERLEN, HEADER, PAYLOADLEN, PAYLOAD) \ do { \ if ((CONTEXT).trace_status_ptr && *((CONTEXT).trace_status_ptr) == DLT_TRACE_STATUS_ON) \ { \ (void)dlt_user_trace_network(&(CONTEXT), TYPE, HEADERLEN, HEADER, PAYLOADLEN, PAYLOAD); \ } \ } while(false) /** * Trace network message, allow truncation * @param CONTEXT object containing information about one special logging context * @param TYPE type of network trace message * @param HEADERLEN length of network message header * @param HEADER pointer to network message header * @param PAYLOADLEN length of network message payload * @param PAYLOAD pointer to network message payload */ #define DLT_TRACE_NETWORK_TRUNCATED(CONTEXT, TYPE, HEADERLEN, HEADER, PAYLOADLEN, PAYLOAD) \ do { \ if ((CONTEXT).trace_status_ptr && *((CONTEXT).trace_status_ptr) == DLT_TRACE_STATUS_ON) \ { \ (void)dlt_user_trace_network_truncated(&(CONTEXT), TYPE, HEADERLEN, HEADER, PAYLOADLEN, PAYLOAD, 1); \ } \ } while(false) /** * Trace network message, segment large messages * @param CONTEXT object containing information about one special logging context * @param TYPE type of network trace message * @param HEADERLEN length of network message header * @param HEADER pointer to network message header * @param PAYLOADLEN length of network message payload * @param PAYLOAD pointer to network message payload */ #define DLT_TRACE_NETWORK_SEGMENTED(CONTEXT, TYPE, HEADERLEN, HEADER, PAYLOADLEN, PAYLOAD) \ do { \ if ((CONTEXT).trace_status_ptr && *((CONTEXT).trace_status_ptr) == DLT_TRACE_STATUS_ON) \ { \ (void)dlt_user_trace_network_segmented(&(CONTEXT), TYPE, HEADERLEN, HEADER, PAYLOADLEN, PAYLOAD); \ } \ } while(false) /** * Send log message with string parameter. * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param TEXT ASCII string */ #define DLT_LOG_STRING(CONTEXT, LOGLEVEL, TEXT) \ do { \ if (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) \ { \ (void)dlt_log_string(&(CONTEXT), LOGLEVEL, TEXT); \ } \ } while(false) /** * Send log message with string parameter and integer parameter. * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log messages * @param TEXT ASCII string * @param INT_VAR integer value */ #define DLT_LOG_STRING_INT(CONTEXT, LOGLEVEL, TEXT, INT_VAR) \ do { \ if (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) \ { \ (void)dlt_log_string_int(&(CONTEXT), LOGLEVEL, TEXT, INT_VAR); \ } \ } while(false) /** * Send log message with string parameter and unsigned integer parameter. * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param TEXT ASCII string * @param UINT_VAR unsigned integer value */ #define DLT_LOG_STRING_UINT(CONTEXT, LOGLEVEL, TEXT, UINT_VAR) \ do { \ if (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) \ { \ (void)dlt_log_string_uint(&(CONTEXT), LOGLEVEL, TEXT, UINT_VAR); \ } \ } while(false) /** * Send log message with unsigned integer parameter. * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param UINT_VAR unsigned integer value */ #define DLT_LOG_UINT(CONTEXT, LOGLEVEL, UINT_VAR) \ do { \ if (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) \ { \ (void)dlt_log_uint(&(CONTEXT), LOGLEVEL, UINT_VAR); \ } \ } while(false) /** * Send log message with integer parameter. * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param INT_VAR integer value */ #define DLT_LOG_INT(CONTEXT, LOGLEVEL, INT_VAR) \ do { \ if (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) \ { \ (void)dlt_log_int(&(CONTEXT), LOGLEVEL, INT_VAR); \ } \ } while(false) /** * Send log message with binary memory block. * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message * @param BUF pointer to memory block * @param LEN length of memory block */ #define DLT_LOG_RAW(CONTEXT, LOGLEVEL, BUF, LEN) \ do { \ if (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) \ { \ (void)dlt_log_raw(&(CONTEXT), LOGLEVEL, BUF, LEN); \ } \ } while(false) /** * Send log message with marker. */ #define DLT_LOG_MARKER() \ do { \ (void)dlt_log_marker(); \ } while(false) /** * Switch to verbose mode * */ #define DLT_VERBOSE_MODE() do { \ (void)dlt_verbose_mode(); } while(false) /** * Switch to non-verbose mode * */ #define DLT_NONVERBOSE_MODE() do { \ (void)dlt_nonverbose_mode(); } while(false) /** * Set maximum logged log level and trace status of application * * @param LOGLEVEL This is the log level to be set for the whole application * @param TRACESTATUS This is the trace status to be set for the whole application */ #define DLT_SET_APPLICATION_LL_TS_LIMIT(LOGLEVEL, TRACESTATUS) do { \ (void)dlt_set_application_ll_ts_limit(LOGLEVEL, TRACESTATUS); } while(false) /** * Enable local printing of messages * */ #define DLT_ENABLE_LOCAL_PRINT() do { \ (void)dlt_enable_local_print(); } while(false) /** * Disable local printing of messages * */ #define DLT_DISABLE_LOCAL_PRINT() do { \ (void)dlt_disable_local_print(); } while(false) /** * Check if log level is enabled * * @param CONTEXT object containing information about one special logging context * @param LOGLEVEL the log level of the log message */ #define DLT_IS_LOG_LEVEL_ENABLED(CONTEXT, LOGLEVEL) \ (dlt_user_is_logLevel_enabled(&CONTEXT, LOGLEVEL) == DLT_RETURN_TRUE) /** \} */ #endif /* DLT_USER_MACROS_H */ dlt-daemon-2.18.10/scripts/000077500000000000000000000000001446635226000154065ustar00rootroot00000000000000dlt-daemon-2.18.10/scripts/pre-commit.sample000077500000000000000000000010401446635226000206630ustar00rootroot00000000000000#!/bin/sh gitclangformat=$(which git-clang-format) if [ "$gitclangformat" == "" ] then gitclangformat=$(find /usr/bin/ -name "git-clang-format*") fi against=`git rev-parse --verify HEAD 2>&1` if [ $against == "" ] then # Initial commit: diff against an empty tree object against=5394c6fa5bf40d9bc8619026cbc4c306211a8499 fi $gitclangformat $against -f -q if [ $? != 0 ] then echo "Format error!" echo "Use git clang-format" exit 1 fi # Now update format changes and commit git add $(git diff --name-only --cached) dlt-daemon-2.18.10/src/000077500000000000000000000000001446635226000145065ustar00rootroot00000000000000dlt-daemon-2.18.10/src/CMakeLists.txt000066400000000000000000000025121446635226000172460ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### add_subdirectory( lib ) add_subdirectory( daemon ) add_subdirectory( gateway ) if( WITH_DLT_CONSOLE ) add_subdirectory( console ) endif( WITH_DLT_CONSOLE ) if( WITH_DLT_EXAMPLES ) add_subdirectory( examples ) endif( WITH_DLT_EXAMPLES ) if( WITH_DLT_ADAPTOR_STDIN OR WITH_DLT_ADAPTOR_UDP OR WITH_DLT_ADAPTOR ) add_subdirectory( adaptor ) endif( WITH_DLT_ADAPTOR_STDIN OR WITH_DLT_ADAPTOR_UDP OR WITH_DLT_ADAPTOR ) if( WITH_DLT_TESTS ) add_subdirectory( tests ) endif( WITH_DLT_TESTS ) if( WITH_DLT_SYSTEM ) add_subdirectory( system ) endif( WITH_DLT_SYSTEM ) if( WITH_DLT_DBUS ) add_subdirectory( dbus ) endif( WITH_DLT_DBUS ) if( WITH_DLT_COREDUMPHANDLER ) add_subdirectory( core_dump_handler ) endif( WITH_DLT_COREDUMPHANDLER ) if( WITH_DLT_KPI ) add_subdirectory( kpi ) endif( WITH_DLT_KPI ) if( WITH_DLT_QNX_SYSTEM ) add_subdirectory( dlt-qnx-system ) endif( WITH_DLT_QNX_SYSTEM ) dlt-daemon-2.18.10/src/adaptor/000077500000000000000000000000001446635226000161405ustar00rootroot00000000000000dlt-daemon-2.18.10/src/adaptor/CMakeLists.txt000066400000000000000000000021601446635226000206770ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if (WITH_DLT_ADAPTOR_STDIN OR WITH_DLT_ADAPTOR) set(dlt_adaptor_stdin_SRCS dlt-adaptor-stdin.c) add_executable(dlt-adaptor-stdin ${dlt_adaptor_stdin_SRCS}) target_link_libraries(dlt-adaptor-stdin dlt) set_target_properties(dlt-adaptor-stdin PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-adaptor-stdin RUNTIME DESTINATION bin COMPONENT base) endif() if (WITH_DLT_ADAPTOR_UDP OR WITH_DLT_ADAPTOR) set(dlt_adaptor_udp_SRCS dlt-adaptor-udp.c) add_executable(dlt-adaptor-udp ${dlt_adaptor_udp_SRCS}) target_link_libraries(dlt-adaptor-udp dlt) set_target_properties(dlt-adaptor-udp PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-adaptor-udp RUNTIME DESTINATION bin COMPONENT base) endif() dlt-daemon-2.18.10/src/adaptor/dlt-adaptor-stdin.c000066400000000000000000000157571446635226000216550ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-adaptor-stdin.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-adaptor-stdin.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ */ #include #include #include #include "dlt_common.h" #include "dlt_user.h" #include "dlt_user_macros.h" #define MAXSTRLEN 1024 #define PS_DLT_APP_DESC "stdin adaptor application" #define PS_DLT_CONTEXT_DESC "stdin adaptor context" #define PS_DLT_APP "SINA" #define PS_DLT_CONTEXT "SINC" DLT_DECLARE_CONTEXT(mycontext) int main(int argc, char *argv[]) { char str[MAXSTRLEN]; int opt; char apid[DLT_ID_SIZE]; char ctid[DLT_ID_SIZE]; char version[255]; int timeout = -1; int verbosity = DLT_LOG_INFO; int bflag = 0; dlt_set_id(apid, PS_DLT_APP); dlt_set_id(ctid, PS_DLT_CONTEXT); while ((opt = getopt(argc, argv, "a:c:bht:v:")) != -1) switch (opt) { case 'a': { dlt_set_id(apid, optarg); break; } case 'c': { dlt_set_id(ctid, optarg); break; } case 'b': { bflag = 1; break; } case 't': { timeout = atoi(optarg); break; } case 'h': { dlt_get_version(version, 255); printf("Usage: dlt-adaptor-stdin [options]\n"); printf("Adaptor for forwarding input from stdin to DLT daemon.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -a apid - Set application id to apid (default: SINA)\n"); printf(" -c ctid - Set context id to ctid (default: SINC)\n"); printf(" -b - Flush buffered logs before unregistering app\n"); printf(" -t timeout - Set timeout when sending messages at exit, in ms (Default: 10000 = 10sec)\n"); printf( " -v verbosity level - Set verbosity level (Default: INFO, values: FATAL ERROR WARN INFO DEBUG VERBOSE)\n"); printf(" -h - This help\n"); return 0; break; } case 'v': { if (!strcmp(optarg, "FATAL")) { verbosity = DLT_LOG_FATAL; break; } else if (!strcmp(optarg, "ERROR")) { verbosity = DLT_LOG_ERROR; break; } else if (!strcmp(optarg, "WARN")) { verbosity = DLT_LOG_WARN; break; } else if (!strcmp(optarg, "INFO")) { verbosity = DLT_LOG_INFO; break; } else if (!strcmp(optarg, "DEBUG")) { verbosity = DLT_LOG_DEBUG; break; } else if (!strcmp(optarg, "VERBOSE")) { verbosity = DLT_LOG_VERBOSE; break; } else { printf( "Wrong verbosity level, setting to INFO. Accepted values are: FATAL ERROR WARN INFO DEBUG VERBOSE\n"); verbosity = DLT_LOG_INFO; break; } break; } default: /* '?' */ { fprintf(stderr, "Unknown option '%c'\n", optopt); return -1; } } DLT_REGISTER_APP(apid, PS_DLT_APP_DESC); DLT_REGISTER_CONTEXT(mycontext, ctid, PS_DLT_CONTEXT_DESC); if (timeout > -1) dlt_set_resend_timeout_atexit(timeout); while (fgets(str, MAXSTRLEN, stdin)) if (strcmp(str, "") != 0) DLT_LOG(mycontext, verbosity, DLT_STRING(str)); DLT_UNREGISTER_CONTEXT(mycontext); if (bflag == 1) DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); else DLT_UNREGISTER_APP(); return 0; } dlt-daemon-2.18.10/src/adaptor/dlt-adaptor-udp.c000066400000000000000000000201041446635226000213020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-adaptor-udp.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-adaptor-udp.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ */ #include #include #include #include #include #include #include #include #include #include "dlt_common.h" #include "dlt_user.h" #include "dlt_user_macros.h" /* Port number, to which the syslogd-ng sends its log messages */ #define RCVPORT 47111 #define MAXSTRLEN 1024 #define PU_DLT_APP_DESC "udp adaptor application" #define PU_DLT_CONTEXT_DESC "udp adaptor context" #define PU_DLT_APP "UDPA" #define PU_DLT_CONTEXT "UDPC" DLT_DECLARE_CONTEXT(mycontext) int main(int argc, char *argv[]) { int sock; int bytes_read; socklen_t addr_len; int opt, port; char recv_data[MAXSTRLEN]; struct sockaddr_in client_addr, server_addr; char apid[DLT_ID_SIZE]; char ctid[DLT_ID_SIZE]; char version[255]; int verbosity = DLT_LOG_INFO; dlt_set_id(apid, PU_DLT_APP); dlt_set_id(ctid, PU_DLT_CONTEXT); port = RCVPORT; while ((opt = getopt(argc, argv, "a:c:hp:v:")) != -1) switch (opt) { case 'a': { dlt_set_id(apid, optarg); break; } case 'c': { dlt_set_id(ctid, optarg); break; } case 'h': { dlt_get_version(version, 255); printf("Usage: dlt-adaptor-udp [options]\n"); printf("Adaptor for forwarding received UDP messages to DLT daemon.\n"); printf("%s \n", version); printf("Options:\n"); printf("-a apid - Set application id to apid (default: UDPA)\n"); printf("-c ctid - Set context id to ctid (default: UDPC)\n"); printf("-p - Set receive port number for UDP messages (default: %d) \n", port); printf( "-v verbosity level - Set verbosity level (Default: INFO, values: FATAL ERROR WARN INFO DEBUG VERBOSE)\n"); printf("-h - This help\n"); return 0; break; } case 'p': { port = atoi(optarg); break; } case 'v': { if (!strcmp(optarg, "FATAL")) { verbosity = DLT_LOG_FATAL; break; } else if (!strcmp(optarg, "ERROR")) { verbosity = DLT_LOG_ERROR; break; } else if (!strcmp(optarg, "WARN")) { verbosity = DLT_LOG_WARN; break; } else if (!strcmp(optarg, "INFO")) { verbosity = DLT_LOG_INFO; break; } else if (!strcmp(optarg, "DEBUG")) { verbosity = DLT_LOG_DEBUG; break; } else if (!strcmp(optarg, "VERBOSE")) { verbosity = DLT_LOG_VERBOSE; break; } else { printf( "Wrong verbosity level, setting to INFO. Accepted values are: FATAL ERROR WARN INFO DEBUG VERBOSE\n"); verbosity = DLT_LOG_INFO; break; } break; } default: /* '?' */ { fprintf(stderr, "Unknown option '%c'\n", optopt); exit(3); return 3;/*for parasoft */ } } #ifdef DLT_USE_IPv6 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) #else if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) #endif { perror("Socket"); exit(1); } #ifdef DLT_USE_IPv6 server_addr.sin_family = AF_INET6; #else server_addr.sin_family = AF_INET; #endif server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = INADDR_ANY; memset(&(server_addr.sin_zero), 0, 8); if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { perror("Bind"); return -1; } addr_len = sizeof(struct sockaddr); DLT_REGISTER_APP(apid, PU_DLT_APP_DESC); DLT_REGISTER_CONTEXT(mycontext, ctid, PU_DLT_CONTEXT_DESC); while (1) { bytes_read = 0; bytes_read = recvfrom(sock, recv_data, MAXSTRLEN, 0, (struct sockaddr *)&client_addr, &addr_len); if (bytes_read == -1) { if (errno == EINTR) { continue; } else { DLT_UNREGISTER_CONTEXT(mycontext); DLT_UNREGISTER_APP(); exit(1); } } recv_data[bytes_read] = '\0'; if (bytes_read != 0) DLT_LOG(mycontext, verbosity, DLT_STRING(recv_data)); } DLT_UNREGISTER_CONTEXT(mycontext); DLT_UNREGISTER_APP(); return 0; } dlt-daemon-2.18.10/src/android/000077500000000000000000000000001446635226000161265ustar00rootroot00000000000000dlt-daemon-2.18.10/src/android/dlt-logd-converter.conf000066400000000000000000000013241446635226000225100ustar00rootroot00000000000000# Configuration file of dlt-logd-converter ######################################################################## # General configuration ######################################################################## # The common application ID for Android native applications to appear on DLT client (Default: LOGD) ApplicationID = LOGD # The common context ID for Android native applications to appear on DLT client (Default: LOGF) ContextID = LOGF # Path for JSON file (Default: /vendor/etc/dlt-logdctxt.json) AndroidLogdJSONpath = /vendor/etc/dlt-logdctxt.json # The common context ID for the case where the JSON path is found, # but applications are not listed in JSON file (Default: OTHE) AndroidLogdContextID = OTHE dlt-daemon-2.18.10/src/android/dlt-logd-converter.cpp000066400000000000000000000473231446635226000223560ustar00rootroot00000000000000/** * Copyright (C) 2019-2022 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * dlt-logd-converter : Retrieve log entries from logd and forward them to DLT. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \Author Luu Quang Minh ADIT 2022 * * \file: dlt-logd-converter.cpp * For further information see http://www.covesa.org/. **/ /******************************************************************************* ** ** ** SRC-MODULE: dlt-logd-converter.cpp ** ** ** ** TARGET : ANDROID ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Minh.LuuQuang@vn.bosch.com ** ** ** ** PURPOSE : Retrieve log entries from logd and forward them to DLT. ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include "dlt-logd-converter.hpp" DLT_DECLARE_CONTEXT(dlt_ctx_self) DLT_DECLARE_CONTEXT(dlt_ctx_main) DLT_DECLARE_CONTEXT(dlt_ctx_rdio) DLT_DECLARE_CONTEXT(dlt_ctx_evnt) /* Binary Buffer */ DLT_DECLARE_CONTEXT(dlt_ctx_syst) DLT_DECLARE_CONTEXT(dlt_ctx_crsh) DLT_DECLARE_CONTEXT(dlt_ctx_stat) /* Binary Buffer */ DLT_DECLARE_CONTEXT(dlt_ctx_secu) /* Binary Buffer */ DLT_DECLARE_CONTEXT(dlt_ctx_krnl) DLT_DECLARE_CONTEXT(dlt_ctx_othe) /* Global variables */ DLT_STATIC dlt_logd_configuration *logd_conf = nullptr; volatile sig_atomic_t exit_parser_loop = false; DLT_STATIC unordered_map map_ctx_json; bool json_is_available = false; /** * Print manual page for instruction. */ DLT_STATIC void usage(char *prog_name) { char version[255]; dlt_get_version(version, 255); cout << "Usage: " << prog_name << " [-h] [-c FILENAME]" << endl; cout << "Application to manage Android logs." << endl; cout << "Format and forward Android messages from ANDROID to DLT." << endl; cout << version << endl; cout << "Options:" << endl; cout << " -h Display a short help text." << endl; cout << " -c filename Use an alternative configuration file." << endl; cout << " Default: " << CONFIGURATION_FILE_DIR << endl; } /** * Initialize configuration to default values. */ DLT_STATIC int init_configuration() { logd_conf = new dlt_logd_configuration; if (logd_conf == nullptr) { cerr << "Fail to allocate, out of memory!" << endl; return -1; } logd_conf->appID = strdup("LOGD"); logd_conf->ctxID = strdup("LOGF"); logd_conf->json_file_dir = strdup(JSON_FILE_DIR); logd_conf->default_ctxID = strdup("OTHE"); logd_conf->conf_file_dir = strdup(CONFIGURATION_FILE_DIR); return 0; } /** * Read command line options and set the values in provided structure */ DLT_STATIC int read_command_line(int argc, char *argv[]) { int opt; while ((opt = getopt(argc, argv, "hc:")) != -1) { switch (opt) { case 'h': { usage(argv[0]); exit(0); return -1; } case 'c': { if (logd_conf->conf_file_dir) { delete logd_conf->conf_file_dir; logd_conf->conf_file_dir = nullptr; } logd_conf->conf_file_dir = new char [strlen(optarg)+1]; strcpy(logd_conf->conf_file_dir, optarg); break; } default: { usage(argv[0]); return -1; } } } return 0; } /** * Read options from the configuration file */ DLT_STATIC int load_configuration_file(const char *file_name) { ifstream file(file_name); char *token; string pattern; if (!file.is_open()) { return -1; } while (!file.eof()) { getline(file, pattern); if (pattern.size() == 0) { continue; } if (pattern[0] != '#') { token = strtok(&pattern[0], " \t="); if (strcmp(token, "ApplicationID") == 0) { token = strtok(NULL, " \t="); if (token != nullptr) { if (logd_conf->appID) { delete logd_conf->appID; } logd_conf->appID = strndup(token, DLT_ID_SIZE); } } else if (strcmp(token, "ContextID") == 0) { token = strtok(NULL, " \t="); if (token != nullptr) { if (logd_conf->ctxID) { delete logd_conf->ctxID; } logd_conf->ctxID = strndup(token, DLT_ID_SIZE); } } else if (strcmp(token, "AndroidLogdJSONpath") == 0) { token = strtok(NULL, " \t="); if (token != nullptr) { if (logd_conf->json_file_dir) { delete logd_conf->json_file_dir; } logd_conf->json_file_dir = strndup(token, MAX_LINE); } } else if (strcmp(token, "AndroidLogdContextID") == 0) { token = strtok(NULL, " \t="); if (token != nullptr) { if (logd_conf->default_ctxID) { delete logd_conf->default_ctxID; } logd_conf->default_ctxID = strndup(token, DLT_ID_SIZE); } } } } file.close(); return 0; } DLT_STATIC void clean_mem() { if (logd_conf->appID) { delete logd_conf->appID; logd_conf->appID = nullptr; } if (logd_conf->ctxID) { delete logd_conf->ctxID; logd_conf->ctxID = nullptr; } if (logd_conf->json_file_dir) { delete logd_conf->json_file_dir; logd_conf->json_file_dir = nullptr; } if (logd_conf->default_ctxID) { delete logd_conf->default_ctxID; logd_conf->default_ctxID = nullptr; } if (logd_conf->conf_file_dir) { delete logd_conf->conf_file_dir; logd_conf->conf_file_dir = nullptr; } if (logd_conf) { delete logd_conf; logd_conf = nullptr; } if (json_is_available) { for (auto &map_malloc: map_ctx_json) { delete map_malloc.second; map_malloc.second = nullptr; } map_ctx_json.clear(); } } /** * Parses data from a json file into an internal data * structure and do registration with the new ctxID. */ DLT_STATIC void json_parser() { #ifndef DLT_UNIT_TESTS Json::Value console = Json::nullValue; Json::CharReaderBuilder builder; string errs; ifstream file(logd_conf->json_file_dir); if (parseFromStream(builder, file, &console, &errs)) { json_is_available = true; } if (json_is_available) { Json::Value::iterator iter; DLT_REGISTER_CONTEXT(dlt_ctx_othe, logd_conf->default_ctxID, ""); for (iter = console.begin(); iter != console.end(); ++iter) { string json_ctxID = iter.key().asString(); string json_tag = (*iter)["tag"].asString(); string json_description = (*iter)["description"].asString(); #else if (json_is_available) { string json_ctxID; string json_tag; string json_description; string str = t_load_json_file(); char *token = strtok(&str[0], " "); while(token != nullptr) { json_ctxID = string(token); token = strtok(nullptr, " "); json_tag = string(token); token = strtok(nullptr, " "); json_description = string(token); if (json_description == "null") { json_description = ""; } token = strtok(nullptr, " "); #endif DltContext *ctx = new DltContext(); auto ret = map_ctx_json.emplace(json_tag, ctx); if (!ret.second) { DLT_LOG(dlt_ctx_self, DLT_LOG_WARN, DLT_STRING(json_tag.c_str()), DLT_STRING("is duplicated, please check the json file.")); delete ctx; ctx = nullptr; } else { DLT_REGISTER_CONTEXT(*(ret.first->second), json_ctxID.c_str(), json_description.c_str()); } #ifdef DLT_UNIT_TESTS } } #else } } file.close(); #endif } /** * Doing tag matching in a loop from first * elementof json vector to the end of the list. */ DLT_STATIC DltContext* find_tag_in_json(const char *tag) { string tag_str(tag); auto search = map_ctx_json.find(tag_str); if (search == map_ctx_json.end()) { DLT_LOG(dlt_ctx_self, DLT_LOG_VERBOSE, DLT_STRING(tag), DLT_STRING("could not be found. Apply default contextID:"), DLT_STRING(logd_conf->default_ctxID)); return &(dlt_ctx_othe); } else { DLT_LOG(dlt_ctx_self, DLT_LOG_VERBOSE, DLT_STRING("Tag found and applied:"), DLT_STRING(tag)); return search->second; } } DLT_STATIC struct logger *init_logger(struct logger_list *logger_list, log_id_t log_id) { struct logger *logger; #ifndef DLT_UNIT_TESTS logger = android_logger_open(logger_list, log_id); if (logger == nullptr) { DLT_LOG(dlt_ctx_self, DLT_LOG_WARN, DLT_STRING("Could not open logd buffer ID = "), DLT_INT64(log_id)); } #else logger = t_android_logger_open(logger_list, log_id); #endif return logger; } DLT_STATIC struct logger_list *init_logger_list(bool skip_binary_buffers) { struct logger_list *logger_list; #ifndef DLT_UNIT_TESTS logger_list = android_logger_list_alloc(O_RDONLY, 0, 0); if (logger_list == nullptr) { DLT_LOG(dlt_ctx_self, DLT_LOG_FATAL, DLT_STRING("Could not allocate logger list")); return nullptr; } #else logger_list = t_android_logger_list_alloc(READ_ONLY, 0, 0); if (logger_list == nullptr) { return nullptr; } #endif /** * logd buffer types are defined in: * system/core/include/log/android/log.h */ init_logger(logger_list, LOG_ID_MAIN); init_logger(logger_list, LOG_ID_RADIO); init_logger(logger_list, LOG_ID_SYSTEM); init_logger(logger_list, LOG_ID_KERNEL); init_logger(logger_list, LOG_ID_CRASH); if (!skip_binary_buffers) { init_logger(logger_list, LOG_ID_EVENTS); init_logger(logger_list, LOG_ID_STATS); init_logger(logger_list, LOG_ID_SECURITY); } return logger_list; } DLT_STATIC DltContext *get_log_context_from_log_msg(struct log_msg *log_msg) { if (log_msg) { switch (log_msg->id()) { case LOG_ID_MAIN: return &dlt_ctx_main; case LOG_ID_RADIO: return &dlt_ctx_rdio; case LOG_ID_EVENTS: return &dlt_ctx_evnt; case LOG_ID_SYSTEM: return &dlt_ctx_syst; case LOG_ID_CRASH: return &dlt_ctx_crsh; case LOG_ID_STATS: return &dlt_ctx_stat; case LOG_ID_SECURITY: return &dlt_ctx_secu; case LOG_ID_KERNEL: return &dlt_ctx_krnl; default: return &dlt_ctx_self; } } else { return &dlt_ctx_self; } } DLT_STATIC uint32_t get_timestamp_from_log_msg(struct log_msg *log_msg) { if (log_msg) { /* in 0.1 ms = 100 us */ return (uint32_t)log_msg->entry.sec * 10000 + (uint32_t)log_msg->entry.nsec / 100000; } else { DLT_LOG(dlt_ctx_self, DLT_LOG_WARN, DLT_STRING("Could not receive any log message")); return (uint32_t)DLT_FAIL_TO_GET_LOG_MSG; } } DLT_STATIC DltLogLevelType get_log_level_from_log_msg(struct log_msg *log_msg) { if (log_msg) { android_LogPriority priority = static_cast(log_msg->msg()[0]); switch (priority) { case ANDROID_LOG_VERBOSE: return DLT_LOG_VERBOSE; case ANDROID_LOG_DEBUG: return DLT_LOG_DEBUG; case ANDROID_LOG_INFO: return DLT_LOG_INFO; case ANDROID_LOG_WARN: return DLT_LOG_WARN; case ANDROID_LOG_ERROR: return DLT_LOG_ERROR; case ANDROID_LOG_FATAL: return DLT_LOG_FATAL; case ANDROID_LOG_SILENT: return DLT_LOG_OFF; case ANDROID_LOG_UNKNOWN: case ANDROID_LOG_DEFAULT: default: return DLT_LOG_DEFAULT; } } else { DLT_LOG(dlt_ctx_self, DLT_LOG_WARN, DLT_STRING("Could not receive any log message")); return DLT_LOG_DEFAULT; } } void signal_handler(int signal) { (void) signal; if (signal == SIGTERM) { exit_parser_loop = true; } } DLT_STATIC int logd_parser_loop(struct logger_list *logger_list) { int ret; DltContext *ctx = nullptr; #ifndef DLT_UNIT_TESTS struct log_msg log_msg; DLT_LOG(dlt_ctx_self, DLT_LOG_VERBOSE, DLT_STRING("Entering parsing loop")); while (!exit_parser_loop) { ret = android_logger_list_read(logger_list, &log_msg); if (ret == -EAGAIN || ret == -EINTR) { if (exit_parser_loop == true) { break; } continue; } else if (ret == -EINVAL || ret == -ENOMEM || ret == -ENODEV || ret == -EIO) { DLT_LOG(dlt_ctx_self, DLT_LOG_FATAL, DLT_STRING("Could not retrieve logs, permanent error="), DLT_INT32(ret)); return ret; } else if (ret <= 0) { DLT_LOG(dlt_ctx_self, DLT_LOG_ERROR, DLT_STRING("android_logger_list_read unexpected return="), DLT_INT32(ret)); return ret; } #else extern struct dlt_log_container *dlt_log_data; extern struct log_msg t_log_msg; struct log_msg &log_msg = t_log_msg; ret = t_android_logger_list_read(logger_list, &log_msg); if (ret == -EAGAIN || ret == -EINTR || ret == -EINVAL || ret == -ENOMEM || ret == -ENODEV || ret == -EIO) { return ret; } #endif /* Look into system/core/liblog/logprint.c for buffer format. "\0\0" */ const char *tag = ""; const char *message = ""; if (log_msg.entry.len > 1) { tag = log_msg.msg() + 1; } if (log_msg.entry.len > 1 + strlen(tag) + 1) { message = tag + strlen(tag) + 1; } /* Find tag in JSON file, apply new contextID if available */ if ((log_msg.id() == LOG_ID_MAIN) && (json_is_available)) { ctx = find_tag_in_json(tag); } else { ctx = get_log_context_from_log_msg(&log_msg); } DltLogLevelType log_level = get_log_level_from_log_msg(&log_msg); uint32_t ts = get_timestamp_from_log_msg(&log_msg); #ifndef DLT_UNIT_TESTS /* Binary buffers are not supported by DLT_STRING DLT_RAW would need the message length */ DLT_LOG_TS(*ctx, log_level, ts, DLT_STRING(tag), DLT_INT32(log_msg.entry.pid), DLT_UINT32(log_msg.entry.tid), DLT_STRING(message)); } DLT_LOG(dlt_ctx_self, DLT_LOG_VERBOSE, DLT_STRING("Exited parsing loop")); #else dlt_log_data->ctx = ctx; dlt_log_data->log_level = log_level; dlt_log_data->ts = ts; dlt_log_data->tag = tag; dlt_log_data->message = message; #endif return EXIT_SUCCESS; } #ifndef DLT_UNIT_TESTS int main(int argc, char *argv[]) { (void) argc; (void) argv; bool skip_binary_buffers = true; if (init_configuration() < 0) { cerr << "dlt-logd-converter could not allocate memory." << endl; return -1; } if (read_command_line(argc, argv) < 0) { cerr << "Failed to read command line!" << endl; return -1; } if (load_configuration_file(logd_conf->conf_file_dir) < 0) { cout << "No configuration file found, use default values!" << endl; } DLT_REGISTER_APP(logd_conf->appID, "logd -> dlt adapter"); DLT_REGISTER_CONTEXT(dlt_ctx_self, logd_conf->ctxID, "logd retriever"); DLT_REGISTER_CONTEXT(dlt_ctx_rdio, "RDIO", "logd type: rdio"); DLT_REGISTER_CONTEXT(dlt_ctx_syst, "SYST", "logd type: syst"); DLT_REGISTER_CONTEXT(dlt_ctx_crsh, "CRSH", "logd type: crsh"); DLT_REGISTER_CONTEXT(dlt_ctx_krnl, "KRNL", "logd type: krnl"); if (!skip_binary_buffers) { DLT_REGISTER_CONTEXT(dlt_ctx_evnt, "EVNT", "logd type: evnt"); DLT_REGISTER_CONTEXT(dlt_ctx_stat, "STAT", "logd type: stat"); DLT_REGISTER_CONTEXT(dlt_ctx_secu, "SECU", "logd type: secu"); } /* Parse json data into internal data structure and do registration */ json_parser(); if (json_is_available) { DLT_LOG(dlt_ctx_self, DLT_LOG_INFO, DLT_STRING("Found JSON file at "), DLT_STRING(logd_conf->json_file_dir), DLT_STRING(". Extension is ON!")); } else { DLT_LOG(dlt_ctx_self, DLT_LOG_INFO, DLT_STRING("No JSON file available at "), DLT_STRING(logd_conf->json_file_dir); DLT_STRING(". Extension is OFF!")); DLT_REGISTER_CONTEXT(dlt_ctx_main, "MAIN", "logd type: main"); } struct sigaction act; act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGTERM, &act, 0); struct logger_list *logger_list; /* Binary buffers are currently not supported */ logger_list = init_logger_list(skip_binary_buffers); if (logger_list == nullptr) { return EXIT_FAILURE; } int ret; /* Main loop */ ret = logd_parser_loop(logger_list); android_logger_list_free(logger_list); DLT_UNREGISTER_CONTEXT(dlt_ctx_krnl); DLT_UNREGISTER_CONTEXT(dlt_ctx_crsh); DLT_UNREGISTER_CONTEXT(dlt_ctx_syst); DLT_UNREGISTER_CONTEXT(dlt_ctx_rdio); DLT_UNREGISTER_CONTEXT(dlt_ctx_self); if (!skip_binary_buffers) { DLT_UNREGISTER_CONTEXT(dlt_ctx_evnt); DLT_UNREGISTER_CONTEXT(dlt_ctx_stat); DLT_UNREGISTER_CONTEXT(dlt_ctx_secu); } if (json_is_available) { DLT_UNREGISTER_CONTEXT(dlt_ctx_othe); for (auto &tag_map: map_ctx_json) { DLT_UNREGISTER_CONTEXT(*(tag_map.second)); } } else { DLT_UNREGISTER_CONTEXT(dlt_ctx_main); } DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); clean_mem(); return ret; } #endif dlt-daemon-2.18.10/src/android/dlt-logd-converter.rc000066400000000000000000000001751446635226000221720ustar00rootroot00000000000000service dlt-logd-converter /vendor/bin/dlt-logd-converter class late_start user system group system disabled dlt-daemon-2.18.10/src/android/dlt-logdctxt.json000066400000000000000000000004211446635226000214270ustar00rootroot00000000000000{ "QTIV": { "tag": "QtiVehicleHal ", "description": "" }, "NETW": { "tag": "NetworkSecurityConfig", "description": "" }, "PROC": { "tag": "ProcessState", "description": "" }, "ZYGO": { "tag": "Zygote", "description": "" } } dlt-daemon-2.18.10/src/console/000077500000000000000000000000001446635226000161505ustar00rootroot00000000000000dlt-daemon-2.18.10/src/console/CMakeLists.txt000066400000000000000000000030101446635226000207020ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### set(dlt_control_common_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/dlt-control-common.c) add_library(dlt_control_common_lib STATIC ${dlt_control_common_SRCS}) target_link_libraries(dlt_control_common_lib dlt ${DLT_JSON_LIBRARY}) set(TARGET_LIST "") if (WITH_DLT_CONSOLE_RECEIVE) list(APPEND TARGET_LIST dlt-receive) endif() if (WITH_DLT_CONSOLE_CONVERT) list(APPEND TARGET_LIST dlt-convert) endif() if(NOT WITH_DLT_CONSOLE_WO_CTRL) add_subdirectory(logstorage) if (WITH_DLT_CONSOLE_CONTROL) list(APPEND TARGET_LIST dlt-control) endif() if (WITH_DLT_CONSOLE_PASSIVE_NODE_CTRL) list(APPEND TARGET_LIST dlt-passive-node-ctrl) endif() endif() if(NOT WITH_DLT_CONSOLE_WO_SBTM) list(APPEND TARGET_LIST dlt-sortbytimestamp) endif() foreach(target IN LISTS TARGET_LIST) set(target_SRCS ${target}) add_executable(${target} ${target_SRCS}) target_link_libraries(${target} dlt dlt_control_common_lib) set_target_properties(${target} PROPERTIES LINKER_LANGUAGE C) install(TARGETS ${target} RUNTIME DESTINATION bin COMPONENT base) endforeach() dlt-daemon-2.18.10/src/console/dlt-control-common.c000066400000000000000000000733741446635226000220610ustar00rootroot00000000000000/** * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-control-common.c * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-control-common.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** ** fb Frederic Berat ADIT ** *******************************************************************************/ #define pr_fmt(fmt) "Common control: "fmt #include #include #include #include #include #include #include #include #include "dlt_common.h" #include "dlt_protocol.h" #include "dlt_client.h" #include "dlt-control-common.h" #ifdef EXTENDED_FILTERING # if defined(__linux__) || defined(__ANDROID_API__) # include /* for json filter parsing on Linux and Android */ # endif # ifdef __QNX__ # include /* for json filter parsing on QNX */ # endif #endif #define DLT_CTRL_APID "DLTC" #define DLT_CTRL_CTID "DLTC" /** @brief Analyze the daemon answer * * This function as to be provided by the user of the connection. * * @param answer The textual answer of the daemon * @param payload The daemons answer payload * @param length The daemons answer payload length * * @return User defined. */ static int (*response_analyzer_cb)(char *, void *, int); static pthread_t daemon_connect_thread; static DltClient g_client; static int callback_return = -1; static pthread_mutex_t answer_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t answer_cond = PTHREAD_COND_INITIALIZER; static int local_verbose; static char local_ecuid[DLT_CTRL_ECUID_LEN]; /* Name of ECU */ static int local_timeout; static char local_filename[DLT_MOUNT_PATH_MAX]= {0}; /* Path to dlt.conf */ int get_verbosity(void) { return local_verbose; } void set_verbosity(int v) { local_verbose = !!v; } char *get_ecuid(void) { return local_ecuid; } void set_ecuid(char *ecuid) { char *ecuid_conf = NULL; if (local_ecuid != ecuid) { /* If user pass NULL, read ECUId from dlt.conf */ if (ecuid == NULL) { if (dlt_parse_config_param("ECUId", &ecuid_conf) == 0) { memset(local_ecuid, 0, DLT_CTRL_ECUID_LEN); strncpy(local_ecuid, ecuid_conf, DLT_CTRL_ECUID_LEN); local_ecuid[DLT_CTRL_ECUID_LEN -1] = '\0'; if (ecuid_conf !=NULL) free(ecuid_conf); } else { pr_error("Cannot read ECUid from dlt.conf\n"); } } else { /* Set user passed ECUID */ memset(local_ecuid, 0, DLT_CTRL_ECUID_LEN); strncpy(local_ecuid, ecuid, DLT_CTRL_ECUID_LEN); local_ecuid[DLT_CTRL_ECUID_LEN - 1] = '\0'; } } } int get_timeout(void) { return local_timeout; } void set_timeout(int t) { local_timeout = DLT_CTRL_TIMEOUT; if (t > 1) local_timeout = t; else pr_error("Timeout to small. Set to default: %d", DLT_CTRL_TIMEOUT); } void set_send_serial_header(const int value) { g_client.send_serial_header = value; } void set_resync_serial_header(const int value) { g_client.resync_serial_header = value; } int dlt_parse_config_param(char *config_id, char **config_data) { FILE *pFile = NULL; int value_length = DLT_LINE_LEN; char line[DLT_LINE_LEN - 1] = { 0 }; char token[DLT_LINE_LEN] = { 0 }; char value[DLT_LINE_LEN] = { 0 }; char *pch = NULL; const char *filename = NULL; if (*config_data != NULL) *config_data = NULL; /* open configuration file */ if (local_filename[0] != 0) { filename = local_filename; } else { filename = CONFIGURATION_FILES_DIR "/dlt.conf"; } pFile = fopen(filename, "r"); if (pFile != NULL) { while (1) { /* fetch line from configuration file */ if (fgets(line, value_length - 1, pFile) != NULL) { if (strncmp(line, config_id, strlen(config_id)) == 0) { pch = strtok(line, " =\r\n"); token[0] = 0; value[0] = 0; while (pch != NULL) { if (token[0] == 0) { strncpy(token, pch, sizeof(token) - 1); token[sizeof(token) - 1] = 0; } else { strncpy(value, pch, sizeof(value) - 1); value[sizeof(value) - 1] = 0; break; } pch = strtok(NULL, " =\r\n"); } if (token[0] && value[0]) { if (strcmp(token, config_id) == 0) { *(config_data) = (char *) calloc(DLT_DAEMON_FLAG_MAX, sizeof(char)); memcpy(*config_data, value, DLT_DAEMON_FLAG_MAX - 1); } } } } else { break; } } fclose (pFile); } else { fprintf(stderr, "Cannot open configuration file: %s\n", filename); } if (*config_data == NULL) return -1; return 0; } /** @brief Prepare the extra headers of a DLT message * * Modifies the extra headers of the message so that it can be sent. * * @param msg The message to be prepared * @param header The base header to be used. * * @return 0 on success, -1 otherwise. */ static int prepare_extra_headers(DltMessage *msg, uint8_t *header) { uint32_t shift = 0; pr_verbose("Preparing extra headers.\n"); if (!msg || !header) return -1; shift = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp)); /* Set header extra parameters */ dlt_set_id(msg->headerextra.ecu, get_ecuid()); msg->headerextra.tmsp = dlt_uptime(); /* Copy header extra parameters to header buffer */ if (dlt_message_set_extraparameters(msg, get_verbosity()) == -1) { pr_error("Cannot copy header extra parameter\n"); return -1; } /* prepare extended header */ msg->extendedheader = (DltExtendedHeader *)(header + shift); msg->extendedheader->msin = DLT_MSIN_CONTROL_REQUEST; msg->extendedheader->noar = 1; /* one payload packet */ /* Dummy values have to be set */ dlt_set_id(msg->extendedheader->apid, DLT_CTRL_APID); dlt_set_id(msg->extendedheader->ctid, DLT_CTRL_CTID); return 0; } /** @brief Prepare the headers of a DLT message * * Modifies the headers of the message so that it can be sent. * * @param msg The message to be prepared * @param header The base header to be used. * * @return 0 on success, -1 otherwise. */ static int prepare_headers(DltMessage *msg, uint8_t *header) { uint32_t len = 0; pr_verbose("Preparing headers.\n"); if (!msg || !header) return -1; msg->storageheader = (DltStorageHeader *)header; if (dlt_set_storageheader(msg->storageheader, "") == -1) { pr_error("Storage header initialization failed.\n"); return -1; } /* prepare standard header */ msg->standardheader = (DltStandardHeader *)(header + sizeof(DltStorageHeader)); msg->standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1; #if (BYTE_ORDER == BIG_ENDIAN) msg->standardheader->htyp = (msg->standardheader->htyp | DLT_HTYP_MSBF); #endif msg->standardheader->mcnt = 0; /* prepare length information */ msg->headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp)); len = (uint32_t) (msg->headersize - sizeof(DltStorageHeader) + msg->datasize); if (len > UINT16_MAX) { pr_error("Message header is too long.\n"); return -1; } msg->standardheader->len = DLT_HTOBE_16(len); return 0; } /** @brief Prepare a DLT message. * * The DLT message is built using the data given by the user. * The data is basically composed of a buffer and a size. * * @param data The message body to be used to build the DLT message. * * @return 0 on success, -1 otherwise. */ static DltMessage *dlt_control_prepare_message(DltControlMsgBody *data) { DltMessage *msg = NULL; pr_verbose("Preparing message.\n"); if (data == NULL) { pr_error("Data for message body is NULL\n"); return NULL; } msg = calloc(1, sizeof(DltMessage)); if (msg == NULL) { pr_error("Cannot allocate memory for Dlt Message\n"); return NULL; } if (dlt_message_init(msg, get_verbosity()) == -1) { pr_error("Cannot initialize Dlt Message\n"); free(msg); return NULL; } /* prepare payload of data */ msg->databuffersize = msg->datasize = (uint32_t) data->size; /* Allocate memory for Dlt Message's buffer */ msg->databuffer = (uint8_t *)calloc(1, data->size); if (msg->databuffer == NULL) { pr_error("Cannot allocate memory for data buffer\n"); free(msg); return NULL; } /* copy data into message */ memcpy(msg->databuffer, data->data, data->size); /* prepare storage header */ if (prepare_headers(msg, msg->headerbuffer)) { dlt_message_free(msg, get_verbosity()); free(msg); return NULL; } /* prepare extra headers */ if (prepare_extra_headers(msg, msg->headerbuffer)) { dlt_message_free(msg, get_verbosity()); free(msg); return NULL; } return msg; } /** @brief Initialize the connection with the daemon * * The connection is initialized using an internal callback. The user's * response analyzer will be finally executed by this callback. * The client pointer is used to established the connection. * * @param client A pointer to a valid client structure * @param cb The internal callback to be executed while receiving a new message * * @return 0 on success, -1 otherwise. */ static int dlt_control_init_connection(DltClient *client, void *cb) { int (*callback)(DltMessage *message, void *data) = cb; if (!cb || !client) { pr_error("%s: Invalid parameters\n", __func__); return -1; } pr_verbose("Initializing the connection.\n"); if (dlt_client_init(client, get_verbosity()) != 0) { pr_error("Failed to register callback (NULL)\n"); return -1; } dlt_client_register_message_callback(callback); client->socketPath = NULL; if (dlt_parse_config_param("ControlSocketPath", &client->socketPath) != 0) { /* Failed to read from conf, copy default */ if (dlt_client_set_socket_path(client, DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH) == -1) { pr_error("set socket path didn't succeed\n"); return -1; } } client->mode = DLT_CLIENT_MODE_UNIX; return dlt_client_connect(client, get_verbosity()); } /** @brief Daemon listener function * * This function will continuously read on the DLT socket, until an error occurs * or the thread executing this function is canceled. * * @param data Thread parameter * * @return The thread parameter given as argument. */ static void *dlt_control_listen_to_daemon(void *data) { pr_verbose("Ready to receive DLT answers.\n"); dlt_client_main_loop(&g_client, NULL, get_verbosity()); return data; } /** @brief Internal callback for DLT response * * This function is called by the dlt_client_main_loop once a response is read * from the DLT socket. * After some basic checks, the user's response analyzer is called. The return * value of the analyzer is then provided back to the dlt_control_send_message * function to be given back as a return value. * As this function is called in a dedicated thread, the return value is * provided using a global variable. * Access to this variable is controlled through a dedicated mutex. * New values are signaled using a dedicated condition variable. * * @param message The DLT answer * @param data Unused * * @return The analyzer return value or -1 on early errors. */ static int dlt_control_callback(DltMessage *message, void *data) { char text[DLT_RECEIVE_BUFSIZE] = { 0 }; (void)data; if (message == NULL) { pr_error("Received message is null\n"); return -1; } /* prepare storage header */ if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) dlt_set_storageheader(message->storageheader, message->headerextra.ecu); else dlt_set_storageheader(message->storageheader, "LCTL"); dlt_message_header(message, text, DLT_RECEIVE_BUFSIZE, get_verbosity()); /* Extracting payload */ dlt_message_payload(message, text, DLT_RECEIVE_BUFSIZE, DLT_OUTPUT_ASCII, get_verbosity()); /* * Checking payload with the provided callback and return the result */ pthread_mutex_lock(&answer_lock); callback_return = response_analyzer_cb(text, message->databuffer, (int) message->datasize); pthread_cond_signal(&answer_cond); pthread_mutex_unlock(&answer_lock); return callback_return; } /** @brief Send a message to the daemon and wait for the asynchronous answer. * * The answer is received and analyzed by a dedicated thread. Thus we need * to wait for the signal from this thread and then read the return value * to be provided to the user. * In case of timeout, this function fails. * The message provided by the user is formated in DLT format before sending. * * @param body The message provided by the user * @param timeout The time to wait before considering that no answer will come * * @return The user response analyzer return value, -1 in case of early error. */ int dlt_control_send_message(DltControlMsgBody *body, int timeout) { struct timespec t; DltMessage *msg = NULL; if (!body) { pr_error("%s: Invalid input.\n", __func__); return -1; } if (clock_gettime(CLOCK_REALTIME, &t) == -1) { pr_error("Cannot read system time.\n"); return -1; } t.tv_sec += timeout; /* send command to daemon here */ msg = dlt_control_prepare_message(body); if (msg == NULL) { pr_error("Control message preparation failed\n"); return -1; } pthread_mutex_lock(&answer_lock); /* Re-init the return value */ callback_return = -1; if (dlt_client_send_message_to_socket(&g_client, msg) != DLT_RETURN_OK) { pr_error("Sending message to daemon failed\n"); dlt_message_free(msg, get_verbosity()); free(msg); /* make sure the mutex is unlocked to prevent deadlocks */ pthread_mutex_unlock(&answer_lock); return -1; } /* * When a timeouts occurs, pthread_cond_timedwait() * shall nonetheless release and re-acquire the mutex referenced by mutex */ pthread_cond_timedwait(&answer_cond, &answer_lock, &t); pthread_mutex_unlock(&answer_lock); /* Destroying the message */ dlt_message_free(msg, get_verbosity()); free(msg); /* At this point either the value is already correct, either it's still -1. * Then, we don't care to lock the access. */ return callback_return; } /** @brief Control communication initialization * * This will prepare the DLT connection and the thread dedicated to the * response listening. * * @param response_analyzer User defined function used to analyze the response * @param ecuid The ECUID to provide to the daemon * @param verbosity The verbosity level * * @return 0 on success, -1 otherwise. */ int dlt_control_init(int (*response_analyzer)(char *, void *, int), char *ecuid, int verbosity) { if (!response_analyzer || !ecuid) { pr_error("%s: Invalid input.\n", __func__); return -1; } response_analyzer_cb = response_analyzer; set_ecuid(ecuid); set_verbosity(verbosity); if (dlt_control_init_connection(&g_client, dlt_control_callback) != 0) { pr_error("Connection initialization failed\n"); dlt_client_cleanup(&g_client, get_verbosity()); return -1; } /* Contact DLT daemon */ if (pthread_create(&daemon_connect_thread, NULL, dlt_control_listen_to_daemon, NULL) != 0) { pr_error("Cannot create thread to communicate with DLT daemon.\n"); return -1; } return 0; } /** @brief Control communication clean-up * * Cancels the listener thread and clean=up the dlt client structure. * * @return 0 on success, -1 otherwise. */ int dlt_control_deinit(void) { /* At this stage, we want to stop sending/receiving * from dlt-daemon. So in order to avoid cancellation * at recv(), shutdown and close the socket */ if (g_client.receiver.fd) { shutdown(g_client.receiver.fd, SHUT_RDWR); close(g_client.receiver.fd); g_client.receiver.fd = -1; } /* Waiting for thread to complete */ pthread_join(daemon_connect_thread, NULL); /* Closing the socket */ return dlt_client_cleanup(&g_client, get_verbosity()); } #ifdef EXTENDED_FILTERING /* EXTENDED_FILTERING */ # if defined(__linux__) || defined(__ANDROID_API__) DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose) { if ((filter == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; if(verbose) pr_verbose("dlt_json_filter_load()\n"); FILE *handle; char buffer[JSON_FILTER_SIZE*DLT_FILTER_MAX]; struct json_object *j_parsed_json; struct json_object *j_app_id; struct json_object *j_context_id; struct json_object *j_log_level; struct json_object *j_payload_min; struct json_object *j_payload_max; enum json_tokener_error jerr; char app_id[DLT_ID_SIZE + 1] = ""; char context_id[DLT_ID_SIZE + 1] = ""; int32_t log_level = 0; int32_t payload_max = INT32_MAX; int32_t payload_min = 0; handle = fopen(filename, "r"); if (handle == NULL) { pr_error("Filter file %s cannot be opened!\n", filename); return DLT_RETURN_ERROR; } if (fread(buffer, sizeof(buffer), 1, handle) != 0) { if (!feof(handle)) { pr_error("Filter file %s is to big for reading it with current buffer!\n", filename); return DLT_RETURN_ERROR; } } j_parsed_json = json_tokener_parse_verbose(buffer, &jerr); if (jerr != json_tokener_success) { pr_error("Faild to parse given filter %s: %s\n", filename, json_tokener_error_desc(jerr)); return DLT_RETURN_ERROR; } printf("The following filter(s) are applied: \n"); pr_verbose("The following filter(s) are applied: \n"); int iterator = 0; json_object_object_foreach(j_parsed_json, key, val) { if (iterator >= DLT_FILTER_MAX) { pr_error("Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n", DLT_FILTER_MAX); break; } printf("%s:\n", key); pr_verbose("%s:\n", key); if (json_object_object_get_ex(val, "AppId", &j_app_id)) strncpy(app_id, json_object_get_string(j_app_id), DLT_ID_SIZE); else dlt_set_id(app_id, ""); if (json_object_object_get_ex(val, "ContextId", &j_context_id)) strncpy(context_id, json_object_get_string(j_context_id), DLT_ID_SIZE); else dlt_set_id(context_id, ""); if (json_object_object_get_ex(val, "LogLevel", &j_log_level)) log_level = json_object_get_int(j_log_level); else log_level = 0; if (json_object_object_get_ex(val, "PayloadMin", &j_payload_min)) payload_min = json_object_get_int(j_payload_min); else payload_min = 0; if (json_object_object_get_ex(val, "PayloadMax", &j_payload_max)) payload_max = json_object_get_int(j_payload_max); else payload_max = INT32_MAX; dlt_filter_add(filter, app_id, context_id, log_level, payload_min, payload_max, verbose); printf("\tAppId: %.*s\n", DLT_ID_SIZE, app_id); pr_verbose("\tAppId: %.*s\n", DLT_ID_SIZE, app_id); printf("\tConextId: %.*s\n", DLT_ID_SIZE, context_id); pr_verbose("\tConextId: %.*s\n", DLT_ID_SIZE, context_id); printf("\tLogLevel: %i\n", log_level); pr_verbose("\tLogLevel: %i\n", log_level); printf("\tPayloadMin: %i\n", payload_min); pr_verbose("\tPayloadMin: %i\n", payload_min); printf("\tPayloadMax: %i\n", payload_max); pr_verbose("\tPayloadMax: %i\n", payload_max); iterator++; } fclose(handle); return DLT_RETURN_OK; } # endif /* __Linux__ */ # ifdef __QNX__ DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose) { if ((filter == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; if(verbose) pr_verbose("dlt_json_filter_load()\n"); json_decoder_t *j_decoder = json_decoder_create(); const char *s_app_id; const char *s_context_id; int32_t log_level = 0; int32_t payload_max = INT32_MAX; int32_t payload_min = 0; json_decoder_error_t ret = json_decoder_parse_file(j_decoder, filename); if (ret != JSON_DECODER_OK) { pr_error("Faild to parse given filter %s: json_decoder_error_t is %i\n", filename, ret); return DLT_RETURN_ERROR; } json_decoder_push_object(j_decoder, NULL, true); int iterator = 0; bool end_of_json = false; while (!end_of_json) { if (iterator >= DLT_FILTER_MAX) { pr_error("Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n", DLT_FILTER_MAX); break; } if (json_decoder_next(j_decoder) == JSON_DECODER_NOT_FOUND) end_of_json = true; json_decoder_previous(j_decoder); printf("%s:\n", json_decoder_name(j_decoder)); json_decoder_push_object(j_decoder, NULL, true); if (json_decoder_get_string(j_decoder, "AppId", &s_app_id, true) != JSON_DECODER_OK) s_app_id = ""; if (json_decoder_get_string(j_decoder, "ContextId", &s_context_id, true) != JSON_DECODER_OK) s_context_id = ""; if (json_decoder_get_int(j_decoder, "LogLevel", &log_level, true) != JSON_DECODER_OK) log_level = 0; if (json_decoder_get_int(j_decoder, "PayloadMin", &payload_min, true) != JSON_DECODER_OK) payload_min = 0; if (json_decoder_get_int(j_decoder, "PayloadMax", &payload_max, true) != JSON_DECODER_OK) payload_max = INT32_MAX; char app_id[DLT_ID_SIZE]; char context_id[DLT_ID_SIZE]; strncpy(app_id, s_app_id, DLT_ID_SIZE); strncpy(context_id, s_context_id, DLT_ID_SIZE); dlt_filter_add(filter, app_id, context_id, log_level, payload_min, payload_max, verbose); printf("\tAppId: %.*s\n", DLT_ID_SIZE, app_id); printf("\tConextId: %.*s\n", DLT_ID_SIZE, context_id); printf("\tLogLevel: %i\n", log_level); printf("\tPayloadMin: %i\n", payload_min); printf("\tPayloadMax: %i\n", payload_max); json_decoder_pop(j_decoder); iterator++; } json_decoder_destroy(j_decoder); return DLT_RETURN_OK; } # endif /* __QNX__ */ #endif /* EXTENDED_FILTERING */ #ifdef EXTENDED_FILTERING /* EXTENDED_FILTERING */ # if defined(__linux__) || defined(__ANDROID_API__) DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose) { if ((filter == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; if(verbose) pr_verbose("dlt_json_filter_save()\n"); struct json_object *json_filter_obj = json_object_new_object(); for (int num = 0; num < filter->counter; num++) { struct json_object *tmp_json_obj = json_object_new_object(); char filter_name[JSON_FILTER_NAME_SIZE]; sprintf(filter_name, "filter%i", num); if (filter->apid[num][DLT_ID_SIZE - 1] != 0) json_object_object_add(tmp_json_obj, "AppId", json_object_new_string_len(filter->apid[num], DLT_ID_SIZE)); else json_object_object_add(tmp_json_obj, "AppId", json_object_new_string(filter->apid[num])); if (filter->ctid[num][DLT_ID_SIZE - 1] != 0) json_object_object_add(tmp_json_obj, "ContextId", json_object_new_string_len(filter->ctid[num], DLT_ID_SIZE)); else json_object_object_add(tmp_json_obj, "ContextId", json_object_new_string(filter->ctid[num])); json_object_object_add(tmp_json_obj, "LogLevel", json_object_new_int(filter->log_level[num])); json_object_object_add(tmp_json_obj, "PayloadMin", json_object_new_int(filter->payload_min[num])); json_object_object_add(tmp_json_obj, "PayloadMax", json_object_new_int(filter->payload_max[num])); json_object_object_add(json_filter_obj, filter_name, tmp_json_obj); } printf("Saving current filter into '%s'\n", filename); json_object_to_file((char*)filename, json_filter_obj); return DLT_RETURN_OK; } # endif /* __Linux__ */ # ifdef __QNX__ DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose) { if ((filter == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; if(verbose) pr_verbose("dlt_json_filter_save()\n"); char s_app_id[DLT_ID_SIZE + 1]; char s_context_id[DLT_ID_SIZE + 1]; json_encoder_t *j_encoder = json_encoder_create(); json_encoder_start_object(j_encoder, NULL); for (int num = 0; num < filter->counter; num++) { char filter_name[JSON_FILTER_NAME_SIZE]; sprintf(filter_name, "filter%i", num); json_encoder_start_object(j_encoder, filter_name); strncpy(s_app_id, filter->apid[num], DLT_ID_SIZE); if (filter->apid[num][DLT_ID_SIZE - 1] != 0) s_app_id[DLT_ID_SIZE] = '\0'; strncpy(s_context_id, filter->ctid[num], DLT_ID_SIZE); if (filter->ctid[num][DLT_ID_SIZE - 1] != 0) s_context_id[DLT_ID_SIZE] = '\0'; json_encoder_add_string(j_encoder, "AppId", s_app_id); json_encoder_add_string(j_encoder, "ContextId", s_context_id); json_encoder_add_int(j_encoder, "LogLevel", filter->log_level[num]); json_encoder_add_int(j_encoder, "PayloadMin", filter->payload_min[num]); json_encoder_add_int(j_encoder, "PayloadMax", filter->payload_max[num]); json_encoder_end_object(j_encoder); } json_encoder_end_object(j_encoder); printf("Saving current filter into '%s'\n", filename); FILE *handle = fopen(filename, "w"); int filter_buffer_size = 100 * (filter->counter); char filter_buffer[filter_buffer_size]; snprintf(filter_buffer, filter_buffer_size, json_encoder_buffer(j_encoder)); fprintf(handle, filter_buffer); fclose(handle); json_encoder_destroy(j_encoder); return DLT_RETURN_OK; } # endif /* __QNX__ */ #endif /* EXTENDED_FILTERING */ dlt-daemon-2.18.10/src/console/dlt-control-common.h000066400000000000000000000071231446635226000220530ustar00rootroot00000000000000/** * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-control-common.h * For further information see http://www.covesa.org/. */ #ifndef _DLT_CONTROL_COMMON_H_ #define _DLT_CONTROL_COMMON_H_ #include #include "dlt_common.h" #define DLT_CTRL_TIMEOUT 10 #define DLT_CTRL_ECUID_LEN 10 #define DLT_DAEMON_FLAG_MAX 256 #define JSON_FILTER_NAME_SIZE 16 /* Size of buffer for the filter names in json filter files */ #define JSON_FILTER_SIZE 200 /* Size in bytes, that the definition of one filter with all parameters needs */ #ifndef pr_fmt # define pr_fmt(fmt) fmt #endif #ifndef USE_STDOUT # define PRINT_OUT stderr #else # define PRINT_OUT stdout #endif #define pr_error(fmt, ...) \ ({ fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); }) #define pr_verbose(fmt, ...) \ ({ if (get_verbosity()) { fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); } }) #define DLT_CTRL_DEFAULT_ECUID "ECU1" #define DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH "/tmp/dlt-ctrl.sock" #define NANOSEC_PER_MILLISEC 1000000 #define NANOSEC_PER_SEC 1000000000 /* To be used as Dlt Message body when sending to DLT daemon */ typedef struct { void *data; /**< data to be send to DLT Daemon */ uint32_t size; /**< size of that data */ } DltControlMsgBody; /* As verbosity, ecuid, timeout, send_serial_header, resync_serial_header are * needed during the communication, defining getter and setters here. * Then there is no need to define them in the control's user application. */ int get_verbosity(void); void set_verbosity(int); char *get_ecuid(void); void set_ecuid(char *); int get_timeout(void); void set_timeout(int); void set_send_serial_header(const int value); void set_resync_serial_header(const int value); /* Parse dlt.conf file and return the value of requested configuration */ int dlt_parse_config_param(char *config_id, char **config_data); /* Initialize the connection to the daemon */ int dlt_control_init(int (*response_analyser)(char *, void *, int), char *ecuid, int verbosity); /* Send a message to the daemon. The call is not thread safe. */ int dlt_control_send_message(DltControlMsgBody *, int); /* Destroys the connection to the daemon */ int dlt_control_deinit(void); #ifdef EXTENDED_FILTERING /** * Load json filter from file. * @param filter pointer to structure of organising DLT filter * @param filename filename to load filters from * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose); /** * Save filter in json format to file. * @param filter pointer to structure of organising DLT filter * @param filename filename to safe filters into * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose); #endif #endif dlt-daemon-2.18.10/src/console/dlt-control.c000066400000000000000000000743211446635226000205640ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-control.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-control.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include /* for isprint() */ #include /* for atoi() */ #include /* for writev() */ #include /* for open() */ #include "dlt_client.h" #include "dlt_user.h" #include "dlt-control-common.h" #define DLT_GLOGINFO_APID_NUM_MAX 150 #define DLT_GLOGINFO_DATA_MAX 800 #define DLT_GET_LOG_INFO_HEADER 18 /*Get log info header size in response text */ #define DLT_INVALID_LOG_LEVEL 0xF #define DLT_INVALID_TRACE_STATUS 0xF /* Option of GET_LOG_INFO */ #define DLT_SERVICE_GET_LOG_INFO_OPT7 7 /* get Apid, ApDescription, Ctid, CtDescription, loglevel, tracestatus */ /** * The structure of the DLT Service header */ typedef struct { uint32_t service_id; /**< service ID */ uint8_t status; /**< response status */ } DLT_PACKED DltServiceHeader; DltClient g_dltclient; /* Function prototypes */ int dlt_receive_message_callback(DltMessage *message, void *data); typedef struct { int vflag; int yflag; char *evalue; char *avalue; char *cvalue; int svalue; char *mvalue; char *xvalue; int tvalue; int lvalue; int rvalue; int dvalue; int fvalue; int ivalue; int oflag; int gflag; int jvalue; int kvalue; int bvalue; int port; int sendSerialHeaderFlag; int resyncSerialHeaderFlag; char ecuid[4]; DltFile file; DltFilter filter; } DltReceiveData; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-control [options] hostname/serial_device_name\n"); printf("Send control message to DLT daemon.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -v Verbose mode\n"); printf(" -h Usage\n"); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -y Serial device mode\n"); printf(" -b baudrate Serial device baudrate (Default: 115200)\n"); printf(" -e ecuid Set ECU ID (Default: RECV)\n"); printf("\n"); printf(" -a id Control message application id\n"); printf(" -c id Control message context id\n"); printf(" -s id Control message injection service id\n"); printf(" -m message Control message injection in ASCII\n"); printf(" -x message Control message injection in Hex e.g. 'ad 01 24 ef'\n"); printf(" -t milliseconds Timeout to terminate application (Default:1000)'\n"); printf(" -l loglevel Set the log level (0=off - 6=verbose default= -1)\n"); printf(" supported options:\n"); printf(" -l level -a apid -c ctid\n"); printf(" -l level -a abc* (set level for all ctxts of apps name starts with abc)\n"); printf(" -l level -a apid (set level for all ctxts of this app)\n"); printf(" -l level -c xyz* (set level for all ctxts whose name starts with xyz)\n"); printf(" -l level -c ctid (set level for the particular ctxt)\n"); printf(" -l level (set level for all the registered contexts)\n"); printf(" -r tracestatus Set the trace status (0=off - 1=on,255=default)\n"); printf(" supported options:\n"); printf(" -r tracestatus -a apid -c ctid\n"); printf(" -r tracestatus -a abc* (set status for all ctxts of apps name starts with abc)\n"); printf(" -r tracestatus -a apid (set status for all ctxts of this app)\n"); printf(" -r tracestatus -c xyz* (set status for all ctxts whose name starts with xyz)\n"); printf(" -r tracestatus -c ctid (set status for the particular ctxt)\n"); printf(" -r tracestatus (set status for all the registered contexts)\n"); printf(" -d loglevel Set the default log level (0=off - 5=verbose)\n"); printf(" -f tracestatus Set the default trace status (0=off - 1=on)\n"); printf(" -i enable Enable timing packets (0=off - 1=on)\n"); printf(" -o Store configuration\n"); printf(" -g Reset to factory default\n"); printf(" -j Get log info\n"); printf(" -k Get software version\n"); printf(" -u unix port\n"); printf(" -p port Use the given port instead the default port\n"); printf(" Cannot be used with serial devices\n"); } /** * Function for sending get log info ctrl msg and printing the response. */ void dlt_process_get_log_info(void) { char apid[DLT_ID_SIZE + 1] = { 0 }; char ctid[DLT_ID_SIZE + 1] = { 0 }; AppIDsType app; ContextIDsInfoType con; int i = 0; int j = 0; DltServiceGetLogInfoResponse *resp = (DltServiceGetLogInfoResponse *)calloc(1, sizeof(DltServiceGetLogInfoResponse)); if (NULL == resp) { fprintf(stderr, "ERROR: calloc for resp data failed.\n"); return; } /* prepare request data */ resp->service_id = DLT_SERVICE_ID_GET_LOG_INFO; resp->status = DLT_SERVICE_RESPONSE_ERROR; /* send control message*/ if (0 != dlt_client_get_log_info(&g_dltclient)) { fprintf(stderr, "ERROR: Could not get log info\n"); dlt_client_cleanup_get_log_info(resp); resp = NULL; return; } if (dlt_client_main_loop(&g_dltclient, (void *)resp, 0) == DLT_RETURN_TRUE) fprintf(stdout, "DLT-daemon's response is invalid.\n"); if (resp->service_id == DLT_SERVICE_ID_GET_LOG_INFO && resp->status >= GET_LOG_INFO_STATUS_MIN && resp->status <= GET_LOG_INFO_STATUS_MAX) { for (i = 0; i < resp->log_info_type.count_app_ids; i++) { app = resp->log_info_type.app_ids[i]; dlt_print_id(apid, app.app_id); if (app.app_description != 0) printf("APID:%4.4s %s\n", apid, app.app_description); else printf("APID:%4.4s \n", apid); for (j = 0; j < app.count_context_ids; j++) { con = app.context_id_info[j]; dlt_print_id(ctid, con.context_id); if (con.context_description != 0) printf("CTID:%4.4s %2d %2d %s\n", ctid, con.log_level, con.trace_status, con.context_description); else printf("CTID:%4.4s %2d %2d\n", ctid, con.log_level, con.trace_status); } } } dlt_client_cleanup_get_log_info(resp); resp = NULL; } /** * Function for sending get software version ctrl msg and printing the response. */ void dlt_process_get_software_version(void) { DltServiceGetSoftwareVersionResponse *resp = (DltServiceGetSoftwareVersionResponse *)calloc(1, sizeof(DltServiceGetSoftwareVersionResponse)); if (NULL == resp) { fprintf(stderr, "ERROR: calloc for resp data failed.\n"); return; } /* prepare request data */ resp->service_id = DLT_SERVICE_ID_GET_SOFTWARE_VERSION; resp->status = DLT_SERVICE_RESPONSE_ERROR; /* send control message*/ if (0 != dlt_client_get_software_version(&g_dltclient)) { fprintf(stderr, "ERROR: Get software version failed.\n"); free(resp); resp = NULL; return; } if (dlt_client_main_loop(&g_dltclient, (void *)resp, 0) == DLT_RETURN_TRUE) fprintf(stdout, "DLT-daemon's response is invalid.\n"); if (resp->service_id == DLT_SERVICE_ID_GET_SOFTWARE_VERSION && resp->status == DLT_SERVICE_RESPONSE_OK && resp->payload != NULL) { printf("%s\n", resp->payload); free(resp->payload); resp->payload = NULL; } free(resp); resp = NULL; } /** * Main function of tool. */ int main(int argc, char *argv[]) { DltReceiveData dltdata; int c; int ret; int index; char *endptr = NULL; struct timespec ts; /* Initialize dltdata */ dltdata = (DltReceiveData) { .tvalue = 1000, .lvalue = DLT_INVALID_LOG_LEVEL, .rvalue = DLT_INVALID_TRACE_STATUS, .dvalue = -1, .fvalue = -1, .ivalue = -1, .oflag = -1, .gflag = -1, .port = 3490 }; /* Fetch command line arguments */ opterr = 0; /* Default return value */ ret = 0; while ((c = getopt (argc, argv, "vhSRye:b:a:c:s:m:x:t:l:r:d:f:i:ogjkup:")) != -1) switch (c) { case 'v': { dltdata.vflag = 1; break; } case 'h': { usage(); return -1; } case 'S': { dltdata.sendSerialHeaderFlag = 1; break; } case 'R': { dltdata.resyncSerialHeaderFlag = 1; break; } case 'y': { dltdata.yflag = DLT_CLIENT_MODE_SERIAL; break; } case 'e': { dltdata.evalue = optarg; break; } case 'b': { dltdata.bvalue = atoi(optarg); break; } case 'a': { dltdata.avalue = optarg; if (strlen(dltdata.avalue) > DLT_ID_SIZE) { fprintf (stderr, "Invalid application id\n"); return -1; } break; } case 'c': { dltdata.cvalue = optarg; if (strlen(dltdata.cvalue) > DLT_ID_SIZE) { fprintf (stderr, "Invalid context id\n"); return -1; } break; } case 's': { dltdata.svalue = atoi(optarg); break; } case 'm': { dltdata.mvalue = optarg; break; } case 'x': { dltdata.xvalue = optarg; break; } case 't': { dltdata.tvalue = atoi(optarg); break; } case 'l': { dltdata.lvalue = (int) strtol(optarg, &endptr, 10); if ((dltdata.lvalue < DLT_LOG_DEFAULT) || (dltdata.lvalue > DLT_LOG_VERBOSE)) { fprintf (stderr, "invalid log level, supported log level 0-6\n"); return -1; } break; } case 'r': { dltdata.rvalue = (int) strtol(optarg, &endptr, 10); if ((dltdata.rvalue < DLT_TRACE_STATUS_DEFAULT) || (dltdata.rvalue > DLT_TRACE_STATUS_ON)) { fprintf (stderr, "invalid trace status, supported trace status -1, 0, 1\n"); return -1; } break; } case 'd': { dltdata.dvalue = atoi(optarg); break; } case 'f': { dltdata.fvalue = atoi(optarg); break; } case 'i': { dltdata.ivalue = atoi(optarg); break; } case 'o': { dltdata.oflag = 1; break; } case 'g': { dltdata.gflag = 1; break; } case 'j': { dltdata.jvalue = 1; break; } case 'k': { dltdata.kvalue = 1; break; } case 'u': { dltdata.yflag = DLT_CLIENT_MODE_UNIX; break; } case 'p': { dltdata.port = atoi(optarg); break; } case '?': { if ((optopt == 'o') || (optopt == 'f')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1; /*for parasoft */ } } /* Initialize DLT Client */ dlt_client_init(&g_dltclient, dltdata.vflag); /* Register callback to be called when message was received */ dlt_client_register_message_callback(dlt_receive_message_callback); /* Setup DLT Client structure */ if (dltdata.yflag == DLT_CLIENT_MODE_SERIAL) { g_dltclient.mode = DLT_CLIENT_MODE_SERIAL; } else if (dltdata.yflag == DLT_CLIENT_MODE_UNIX) { g_dltclient.mode = DLT_CLIENT_MODE_UNIX; g_dltclient.socketPath = NULL; if (dlt_parse_config_param("ControlSocketPath", &g_dltclient.socketPath) == DLT_RETURN_ERROR) { /* Failed to read from conf, copy default */ if (dlt_client_set_socket_path(&g_dltclient, DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH) == -1) { pr_error("set socket path didn't succeed\n"); return -1; } } } else { g_dltclient.mode = DLT_CLIENT_MODE_TCP; } if (g_dltclient.mode == DLT_CLIENT_MODE_TCP) { g_dltclient.port = dltdata.port; for (index = optind; index < argc; index++) if (dlt_client_set_server_ip(&g_dltclient, argv[index]) == -1) { pr_error("set server ip didn't succeed\n"); return -1; } if (g_dltclient.servIP == 0) { /* no hostname selected, show usage and terminate */ fprintf(stderr, "ERROR: No hostname selected\n"); usage(); dlt_client_cleanup(&g_dltclient, dltdata.vflag); return -1; } } else if (g_dltclient.mode == DLT_CLIENT_MODE_SERIAL) { for (index = optind; index < argc; index++) if (dlt_client_set_serial_device(&g_dltclient, argv[index]) == -1) { pr_error("set serial device didn't succeed\n"); return -1; } if (g_dltclient.serialDevice == 0) { /* no serial device name selected, show usage and terminate */ fprintf(stderr, "ERROR: No serial device name specified\n"); usage(); return -1; } dlt_client_setbaudrate(&g_dltclient, dltdata.bvalue); } /* Update the send and resync serial header flags based on command line option */ g_dltclient.send_serial_header = dltdata.sendSerialHeaderFlag; g_dltclient.resync_serial_header = dltdata.resyncSerialHeaderFlag; /* initialise structure to use DLT file */ dlt_file_init(&(dltdata.file), dltdata.vflag); /* first parse filter file if filter parameter is used */ dlt_filter_init(&(dltdata.filter), dltdata.vflag); if (dltdata.evalue) { dlt_set_id(dltdata.ecuid, dltdata.evalue); dlt_set_id(g_dltclient.ecuid, dltdata.evalue); } else { dltdata.evalue = NULL; if (dlt_parse_config_param("ECUId", &dltdata.evalue) == 0) { dlt_set_id(dltdata.ecuid, dltdata.evalue); dlt_set_id(g_dltclient.ecuid, dltdata.evalue); free (dltdata.evalue); } else { fprintf(stderr, "ERROR: Failed to read ECUId from dlt.conf \n"); } } /* Connect to TCP socket or open serial device */ if (dlt_client_connect(&g_dltclient, dltdata.vflag) != DLT_RETURN_ERROR) { /* send injection message */ if (dltdata.mvalue && dltdata.avalue && dltdata.cvalue) { /* ASCII */ printf("Send injection message:\n"); printf("AppId: %s\n", dltdata.avalue); printf("ConId: %s\n", dltdata.cvalue); printf("ServiceId: %d\n", dltdata.svalue); printf("Message: %s\n", dltdata.mvalue); /* send control message in ascii */ if (dlt_client_send_inject_msg(&g_dltclient, dltdata.avalue, dltdata.cvalue, (uint32_t) dltdata.svalue, (uint8_t *)dltdata.mvalue, (uint32_t) strlen(dltdata.mvalue)) != DLT_RETURN_OK) { fprintf(stderr, "ERROR: Could not send inject message\n"); ret = -1; } } else if (dltdata.xvalue && dltdata.avalue && dltdata.cvalue) { /* Hex */ uint8_t buffer[1024]; int size = 1024; printf("Send injection message:\n"); printf("AppId: %s\n", dltdata.avalue); printf("ConId: %s\n", dltdata.cvalue); printf("ServiceId: %d\n", dltdata.svalue); printf("Message: %s\n", dltdata.xvalue); dlt_hex_ascii_to_binary(dltdata.xvalue, buffer, &size); printf("Size: %d\n", size); /* send control message in hex */ if (dlt_client_send_inject_msg(&g_dltclient, dltdata.avalue, dltdata.cvalue, (uint32_t) dltdata.svalue, buffer, (uint32_t)size) != DLT_RETURN_OK) { fprintf(stderr, "ERROR: Could not send inject message\n"); ret = -1; } } else if (dltdata.lvalue != DLT_INVALID_LOG_LEVEL) /*&& dltdata.avalue && dltdata.cvalue)*/ { if ((dltdata.avalue == 0) && (dltdata.cvalue == 0)) { if (dltdata.vflag) { printf("Set all log level:\n"); printf("Loglevel: %d\n", dltdata.lvalue); } if (0 != dlt_client_send_all_log_level(&g_dltclient, (uint8_t) dltdata.lvalue)) { fprintf(stderr, "ERROR: Could not send log level\n"); ret = -1; } } else { /* log level */ if (dltdata.vflag) { printf("Set log level:\n"); printf("AppId: %s\n", dltdata.avalue); printf("ConId: %s\n", dltdata.cvalue); printf("Loglevel: %d\n", dltdata.lvalue); } /* send control message*/ if (0 != dlt_client_send_log_level(&g_dltclient, dltdata.avalue, dltdata.cvalue, (uint8_t) dltdata.lvalue)) { fprintf(stderr, "ERROR: Could not send log level\n"); ret = -1; } } } else if (dltdata.rvalue != DLT_INVALID_TRACE_STATUS) { if ((dltdata.avalue == 0) && (dltdata.cvalue == 0)) { if (dltdata.vflag) { printf("Set all trace status:\n"); printf("Tracestatus: %d\n", dltdata.rvalue); } if (0 != dlt_client_send_all_trace_status(&g_dltclient, (uint8_t) dltdata.rvalue)) { fprintf(stderr, "ERROR: Could not send trace status\n"); ret = -1; } } else { /* trace status */ if (dltdata.vflag) { printf("Set trace status:\n"); printf("AppId: %s\n", dltdata.avalue); printf("ConId: %s\n", dltdata.cvalue); printf("Tracestatus: %d\n", dltdata.rvalue); } /* send control message*/ if (0 != dlt_client_send_trace_status(&g_dltclient, dltdata.avalue, dltdata.cvalue, (uint8_t) dltdata.rvalue)) { fprintf(stderr, "ERROR: Could not send trace status\n"); ret = -1; } } } else if (dltdata.dvalue != -1) { /* default log level */ printf("Set default log level:\n"); printf("Loglevel: %d\n", dltdata.dvalue); /* send control message in*/ if (dlt_client_send_default_log_level(&g_dltclient, (uint8_t) dltdata.dvalue) != DLT_RETURN_OK) { fprintf (stderr, "ERROR: Could not send default log level\n"); ret = -1; } } else if (dltdata.fvalue != -1) { /* default trace status */ printf("Set default trace status:\n"); printf("TraceStatus: %d\n", dltdata.fvalue); /* send control message in*/ if (dlt_client_send_default_trace_status(&g_dltclient, (uint8_t) dltdata.fvalue) != DLT_RETURN_OK) { fprintf (stderr, "ERROR: Could not send default trace status\n"); ret = -1; } } else if (dltdata.ivalue != -1) { /* timing pakets */ printf("Set timing pakets:\n"); printf("Timing packets: %d\n", dltdata.ivalue); /* send control message in*/ if (dlt_client_send_timing_pakets(&g_dltclient, (uint8_t) dltdata.ivalue) != DLT_RETURN_OK) { fprintf (stderr, "ERROR: Could not send timing packets\n"); ret = -1; } } else if (dltdata.oflag != -1) { /* default trace status */ printf("Store config\n"); /* send control message in*/ if (dlt_client_send_store_config(&g_dltclient) != DLT_RETURN_OK) { fprintf (stderr, "ERROR: Could not send store config\n"); ret = -1; } } else if (dltdata.gflag != -1) { /* reset to factory default */ printf("Reset to factory default\n"); /* send control message in*/ if (dlt_client_send_reset_to_factory_default(&g_dltclient) != DLT_RETURN_OK) { fprintf (stderr, "ERROR: Could not send reset to factory default\n"); ret = -1; } } else if (dltdata.jvalue == 1) { /* get log info */ printf("Get log info:\n"); dlt_process_get_log_info(); } else if (dltdata.kvalue == 1) { /* Get software version */ printf("Get software version:\n"); dlt_process_get_software_version(); } /* Dlt Client Main Loop */ /*dlt_client_main_loop(&dltclient, &dltdata, dltdata.vflag); */ /* Wait timeout */ ts.tv_sec = (dltdata.tvalue * NANOSEC_PER_MILLISEC) / NANOSEC_PER_SEC; ts.tv_nsec = (dltdata.tvalue * NANOSEC_PER_MILLISEC) % NANOSEC_PER_SEC; nanosleep(&ts, NULL); } else { ret = -1; } /* Dlt Client Cleanup */ dlt_client_cleanup(&g_dltclient, dltdata.vflag); if (g_dltclient.socketPath != NULL) free(g_dltclient.socketPath); dlt_file_free(&(dltdata.file), dltdata.vflag); dlt_filter_free(&(dltdata.filter), dltdata.vflag); return ret; } int dlt_receive_message_callback(DltMessage *message, void *data) { static char resp_text[DLT_RECEIVE_BUFSIZE]; int ret = DLT_RETURN_OK; uint32_t id = 0; uint32_t uint32_tmp = 0; uint8_t *ptr; int32_t datalength; DltServiceHeader *req_header = NULL; if ((message == NULL) || (data == NULL) || !DLT_MSG_IS_CONTROL_RESPONSE(message)) return -1; /* get request service id */ req_header = (DltServiceHeader *)data; /* get response service id */ ptr = message->databuffer; datalength =(int32_t) message->datasize; DLT_MSG_READ_VALUE(uint32_tmp, ptr, datalength, uint32_t); id = DLT_ENDIAN_GET_32(message->standardheader->htyp, uint32_tmp); if ((id > DLT_SERVICE_ID) && (id < DLT_SERVICE_ID_LAST_ENTRY) && (id == req_header->service_id)) { switch (id) { case DLT_SERVICE_ID_GET_LOG_INFO: { DltServiceGetLogInfoResponse *resp = (DltServiceGetLogInfoResponse *)data; /* prepare storage header */ if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) dlt_set_storageheader(message->storageheader, message->headerextra.ecu); else dlt_set_storageheader(message->storageheader, "LCTL"); /* get response data */ ret = dlt_message_header(message, resp_text, DLT_RECEIVE_BUFSIZE, 0); if (ret < 0) { fprintf(stderr, "GET_LOG_INFO message_header result failed.\n"); dlt_client_cleanup(&g_dltclient, 0); return -1; } ret = dlt_message_payload(message, resp_text, DLT_RECEIVE_BUFSIZE, DLT_OUTPUT_ASCII, 0); if (ret < 0) { fprintf(stderr, "GET_LOG_INFO message_payload result failed.\n"); dlt_client_cleanup(&g_dltclient, 0); return -1; } ret = dlt_set_loginfo_parse_service_id(resp_text, &resp->service_id, &resp->status); if ((ret == 0) && (resp->service_id == DLT_SERVICE_ID_GET_LOG_INFO)) { ret = dlt_client_parse_get_log_info_resp_text(resp, resp_text); if (ret != 0) { fprintf(stderr, "GET_LOG_INFO failed [status=%d]\n", resp->status); dlt_client_cleanup(&g_dltclient, 0); return -1; } dlt_client_cleanup(&g_dltclient, 0); } break; } case DLT_SERVICE_ID_GET_SOFTWARE_VERSION: { DltServiceGetSoftwareVersionResponse *resp = (DltServiceGetSoftwareVersionResponse *)data; resp->service_id = id; DLT_MSG_READ_VALUE(resp->status, ptr, datalength, uint8_t); DLT_MSG_READ_VALUE(uint32_tmp, ptr, datalength, uint32_t); resp->length = DLT_ENDIAN_GET_32(message->standardheader->htyp, uint32_tmp); if (resp->status != DLT_SERVICE_RESPONSE_OK) { fprintf(stderr, "GET_SOFTWARE_VERSION failed [status=%d]\n", resp->status); dlt_client_cleanup(&g_dltclient, 0); return -1; } resp->payload = (char *)calloc(resp->length + 1, sizeof(char)); if (resp->payload != NULL) memcpy(resp->payload, message->databuffer + message->datasize - resp->length, resp->length); dlt_client_cleanup(&g_dltclient, 0); break; } default: { break; } } } return ret; } dlt-daemon-2.18.10/src/console/dlt-convert.c000066400000000000000000000426231446635226000205640ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-convert.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-convert.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include #include #include #include #include #include #include #include #include #include /* writev() */ #include "dlt_common.h" #define COMMAND_SIZE 1024 /* Size of command */ #define FILENAME_SIZE 1024 /* Size of filename */ #define DLT_EXTENSION "dlt" #define DLT_CONVERT_WS "/tmp/dlt_convert_workspace/" /** * Print usage information of tool. */ void usage() { char version[DLT_CONVERT_TEXTBUFSIZE]; dlt_get_version(version, 255); printf("Usage: dlt-convert [options] [commands] file1 [file2]\n"); printf("Read DLT files, print DLT messages as ASCII and store the messages again.\n"); printf("Use filters to filter DLT messages.\n"); printf("Use Ranges and Output file to cut DLT files.\n"); printf("Use two files and Output file to join DLT files.\n"); printf("%s \n", version); printf("Commands:\n"); printf(" -h Usage\n"); printf(" -a Print DLT file; payload as ASCII\n"); printf(" -x Print DLT file; payload as hex\n"); printf(" -m Print DLT file; payload as hex and ASCII\n"); printf(" -s Print DLT file; only headers\n"); printf(" -o filename Output messages in new DLT file\n"); printf("Options:\n"); printf(" -v Verbose mode\n"); printf(" -c Count number of messages\n"); printf(" -f filename Enable filtering of messages\n"); printf(" -b number First messages to be handled\n"); printf(" -e number Last message to be handled\n"); printf(" -w Follow dlt file while file is increasing\n"); printf(" -t Handling input compressed files (tar.gz)\n"); } void empty_dir(const char *dir) { struct dirent **files = { 0 }; struct stat st; uint32_t n = 0; char tmp_filename[FILENAME_SIZE] = { 0 }; uint32_t i; if (dir == NULL) fprintf(stderr, "ERROR: %s: invalid arguments\n", __FUNCTION__); if (stat(dir, &st) == 0) { if (S_ISDIR(st.st_mode)) { n = (uint32_t) scandir(dir, &files, NULL, alphasort); /* Do not include /. and /.. */ if (n < 2) fprintf(stderr, "ERROR: Failed to scan %s with error %s\n", dir, strerror(errno)); else if (n == 2) printf("%s is already empty\n", dir); else { for (i = 2; i < n; i++) { memset(tmp_filename, 0, FILENAME_SIZE); snprintf(tmp_filename, FILENAME_SIZE, "%s%s", dir, files[i]->d_name); if (remove(tmp_filename) != 0) fprintf(stderr, "ERROR: Failed to delete %s with error %s\n", tmp_filename, strerror(errno)); } if (files) { for (i = 0; i < n ; i++) if (files[i]) { free(files[i]); files[i] = NULL; } free(files); files = NULL; } } } else fprintf(stderr, "ERROR: %s is not a directory\n", dir); } else fprintf(stderr, "ERROR: Failed to stat %s with error %s\n", dir, strerror(errno)); } /** * Main function of tool. */ int main(int argc, char *argv[]) { int vflag = 0; int cflag = 0; int aflag = 0; int sflag = 0; int xflag = 0; int mflag = 0; int wflag = 0; int tflag = 0; char *fvalue = 0; char *bvalue = 0; char *evalue = 0; char *ovalue = 0; int index; int c; DltFile file; DltFilter filter; int ohandle = -1; int num, begin, end; char text[DLT_CONVERT_TEXTBUFSIZE] = { 0 }; /* For handling compressed files */ char tmp_filename[FILENAME_SIZE] = { 0 }; struct stat st = { 0 }; struct dirent **files = { 0 }; int n = 0; int i = 0; struct iovec iov[2]; int bytes_written = 0; int syserr = 0; opterr = 0; while ((c = getopt (argc, argv, "vcashxmwtf:b:e:o:")) != -1) { switch (c) { case 'v': { vflag = 1; break; } case 'c': { cflag = 1; break; } case 'a': { aflag = 1; break; } case 's': { sflag = 1; break; } case 'x': { xflag = 1; break; } case 'm': { mflag = 1; break; } case 'w': { wflag = 1; break; } case 't': { tflag = 1; break; } case 'h': { usage(); return -1; } case 'f': { fvalue = optarg; break; } case 'b': { bvalue = optarg; break; } case 'e': { evalue = optarg; break; } case 'o': { ovalue = optarg; break; } case '?': { if ((optopt == 'f') || (optopt == 'b') || (optopt == 'e') || (optopt == 'o')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { return -1; /*for parasoft */ } } } /* Initialize structure to use DLT file */ dlt_file_init(&file, vflag); /* first parse filter file if filter parameter is used */ if (fvalue) { if (dlt_filter_load(&filter, fvalue, vflag) < DLT_RETURN_OK) { dlt_file_free(&file, vflag); return -1; } dlt_file_set_filter(&file, &filter, vflag); } if (ovalue) { ohandle = open(ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (ohandle == -1) { dlt_file_free(&file, vflag); fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", ovalue); return -1; } } if (tflag) { /* Prepare the temp dir to untar compressed files */ if (stat(DLT_CONVERT_WS, &st) == -1) { if (mkdir(DLT_CONVERT_WS, 0700) != 0) { fprintf(stderr,"ERROR: Cannot create temp dir %s!\n", DLT_CONVERT_WS); if (ovalue) close(ohandle); return -1; } } else { if (S_ISDIR(st.st_mode)) empty_dir(DLT_CONVERT_WS); else fprintf(stderr, "ERROR: %s is not a directory", DLT_CONVERT_WS); } for (index = optind; index < argc; index++) { /* Check extension of input file * If it is a compressed file, uncompress it */ if (strcmp(get_filename_ext(argv[index]), DLT_EXTENSION) != 0) { syserr = dlt_execute_command(NULL, "tar", "xf", argv[index], "-C", DLT_CONVERT_WS, NULL); if (syserr != 0) fprintf(stderr, "ERROR: Failed to uncompress %s to %s with error [%d]\n", argv[index], DLT_CONVERT_WS, WIFEXITED(syserr)); } else { syserr = dlt_execute_command(NULL, "cp", argv[index], DLT_CONVERT_WS, NULL); if (syserr != 0) fprintf(stderr, "ERROR: Failed to copy %s to %s with error [%d]\n", argv[index], DLT_CONVERT_WS, WIFEXITED(syserr)); } } n = scandir(DLT_CONVERT_WS, &files, NULL, alphasort); if (n == -1) { fprintf(stderr,"ERROR: Cannot scan temp dir %s!\n", DLT_CONVERT_WS); if (ovalue) close(ohandle); return -1; } /* do not include ./ and ../ in the files */ argc = optind + (n - 2); } for (index = optind; index < argc; index++) { if (tflag) { memset(tmp_filename, 0, FILENAME_SIZE); snprintf(tmp_filename, FILENAME_SIZE, "%s%s", DLT_CONVERT_WS, files[index - optind + 2]->d_name); argv[index] = tmp_filename; } /* load, analyze data file and create index list */ if (dlt_file_open(&file, argv[index], vflag) >= DLT_RETURN_OK) { while (dlt_file_read(&file, vflag) >= DLT_RETURN_OK) { } } if (aflag || sflag || xflag || mflag || ovalue) { if (bvalue) begin = atoi(bvalue); else begin = 0; if (evalue && (wflag == 0)) end = atoi(evalue); else end = file.counter - 1; if ((begin < 0) || (begin >= file.counter)) { fprintf(stderr, "ERROR: Selected first message %d is out of range!\n", begin); if (ovalue) close(ohandle); dlt_file_free(&file, vflag); return -1; } if ((end < 0) || (end >= file.counter) || (end < begin)) { fprintf(stderr, "ERROR: Selected end message %d is out of range!\n", end); if (ovalue) close(ohandle); dlt_file_free(&file, vflag); return -1; } for (num = begin; num <= end; num++) { if (dlt_file_message(&file, num, vflag) < DLT_RETURN_OK) continue; if (xflag) { printf("%d ", num); if (dlt_message_print_hex(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK) continue; } else if (aflag) { printf("%d ", num); if (dlt_message_header(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK) continue; printf("%s ", text); if (dlt_message_payload(&file.msg, text, DLT_CONVERT_TEXTBUFSIZE, DLT_OUTPUT_ASCII, vflag) < DLT_RETURN_OK) continue; printf("[%s]\n", text); } else if (mflag) { printf("%d ", num); if (dlt_message_print_mixed_plain(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK) continue; } else if (sflag) { printf("%d ", num); if (dlt_message_header(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK) continue; printf("%s \n", text); } /* if file output enabled write message */ if (ovalue) { iov[0].iov_base = file.msg.headerbuffer; iov[0].iov_len = (uint32_t) file.msg.headersize; iov[1].iov_base = file.msg.databuffer; iov[1].iov_len = (uint32_t) file.msg.datasize; bytes_written =(int) writev(ohandle, iov, 2); if (0 > bytes_written) { printf("in main: writev(ohandle, iov, 2); returned an error!"); close(ohandle); dlt_file_free(&file, vflag); return -1; } } /* check for new messages if follow flag set */ if (wflag && (num == end)) { while (1) { while (dlt_file_read(&file, 0) >= 0){ } if (end == (file.counter - 1)) { /* Sleep if no new message was received */ struct timespec req; req.tv_sec = 0; req.tv_nsec = 100000000; nanosleep(&req, NULL); } else { /* set new end of log file and continue reading */ end = file.counter - 1; break; } } } } } if (cflag) { printf("Total number of messages: %d\n", file.counter_total); if (file.filter) printf("Filtered number of messages: %d\n", file.counter); } } if (ovalue) close(ohandle); if (tflag) { empty_dir(DLT_CONVERT_WS); if (files) { for (i = 0; i < n ; i++) if (files[i]) free(files[i]); free(files); } rmdir(DLT_CONVERT_WS); } if (index == optind) { /* no file selected, show usage and terminate */ fprintf(stderr, "ERROR: No file selected\n"); usage(); return -1; } dlt_file_free(&file, vflag); return 0; } dlt-daemon-2.18.10/src/console/dlt-passive-node-ctrl.c000066400000000000000000000321221446635226000224340ustar00rootroot00000000000000/** * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka ADIT 2015 * * \file dlt-passive-node-ctrl.c * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-passive-node-ctrl.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** CL Christoph Lipka ADIT ** *******************************************************************************/ #include #include #include #include #include #include "dlt_protocol.h" #include "dlt_client.h" #include "dlt-control-common.h" #include "dlt_daemon_connection_types.h" #define MAX_RESPONSE_LENGTH 32 #define DLT_NODE_CONNECT 1 #define DLT_NODE_DISCONNECT 0 #define DLT_NODE_CONNECT_UNDEF 999 #define DLT_GATEWAY_CONNECTED 2 #define DLT_NODE_CONNECTED_STR "Connected" #define DLT_NODE_DISCONNECTED_STR "Disconnected" #define UNDEFINED 999 static struct PassiveNodeOptions { unsigned int command; /**< passive node control command */ unsigned int connection_state; /**< connection state */ char node_id[DLT_ID_SIZE]; /**< node identifier */ long timeout; /**< Default timeout */ } g_options = { .command = UNDEFINED, .connection_state = UNDEFINED, .node_id = { '\0' }, }; unsigned int get_command(void) { return g_options.command; } void set_command(unsigned int c) { g_options.command = c; } unsigned int get_connection_state(void) { return g_options.connection_state; } void set_connection_state(unsigned int s) { if ((s == DLT_NODE_CONNECT) || (s == DLT_NODE_DISCONNECT)) { g_options.connection_state = s; set_command(DLT_SERVICE_ID_PASSIVE_NODE_CONNECT); } else { pr_error("Connection status %u invalid\n", s); exit(-1); } } void set_node_id(char *id) { if (id == 0) { pr_error("node identifier is NULL\n"); exit(-1); } else { strncpy(g_options.node_id, id, DLT_ID_SIZE); } } char *get_node_id() { return g_options.node_id; } /** * @brief Print passive node status information * * @param info DltServicePassiveNodeConnectionInfo */ static void dlt_print_passive_node_status( DltServicePassiveNodeConnectionInfo *info) { unsigned int i = 0; char *status; if (info == NULL) return; printf("\nPassive Node connection status:\n" "---------------------------------\n"); for (i = 0; i < info->num_connections; i++) { if (info->connection_status[i] == DLT_GATEWAY_CONNECTED) status = DLT_NODE_CONNECTED_STR; else status = DLT_NODE_DISCONNECTED_STR; printf("%.4s: %s\n", &info->node_id[i * DLT_ID_SIZE], status); } printf("\n"); } /** * @brief Analyze received DLT Daemon response * * This function checks the received message. In particular, it checks the * answer string 'service(\, {ok, error, perm_denied})'. In any case the * g_callback_return variable will be set as well which is evaluated in the * main function after the communication thread returned. * * @param answer Recieved response * @param payload Received DLT Message * @param len Length of received DLT message * @return 0 if daemon returns 'ok' message, -1 otherwise */ static int dlt_passive_node_analyze_response(char *answer, void *payload, int len) { int ret = -1; char resp_ok[MAX_RESPONSE_LENGTH] = { 0 }; if ((answer == NULL) || (payload == NULL)) return -1; snprintf(resp_ok, MAX_RESPONSE_LENGTH, "service(%u), ok", get_command()); pr_verbose("Response received: '%s'\n", answer); pr_verbose("Response expected: '%s'\n", resp_ok); if (strncmp(answer, resp_ok, strlen(resp_ok)) == 0) { ret = 0; if (get_command() == DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS) { if ((int)sizeof(DltServicePassiveNodeConnectionInfo) > len) { pr_error("Received payload is smaller than expected\n"); pr_verbose("Expected: %zu,\nreceived: %d", sizeof(DltServicePassiveNodeConnectionInfo), len); ret = -1; } else { DltServicePassiveNodeConnectionInfo *info = (DltServicePassiveNodeConnectionInfo *)(payload); if (info == NULL) { fprintf(stderr, "Received response is NULL\n"); return -1; } dlt_print_passive_node_status(info); } } } return ret; } /** * @brief Prepare message body to be send to DLT Daemon * * @return Pointer ot DltControlMsgBody, NULL otherwise */ DltControlMsgBody *dlt_passive_node_prepare_message_body() { DltControlMsgBody *mb = calloc(1, sizeof(DltControlMsgBody)); char *ecuid = get_node_id(); if (mb == NULL) return NULL; if (get_command() == DLT_SERVICE_ID_PASSIVE_NODE_CONNECT) { mb->data = calloc(1, sizeof(DltServicePassiveNodeConnect)); if (mb->data == NULL) { free(mb); return NULL; } mb->size = sizeof(DltServicePassiveNodeConnect); DltServicePassiveNodeConnect *serv = (DltServicePassiveNodeConnect *) mb->data; serv->service_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECT; serv->connection_status = get_connection_state(); memcpy(serv->node_id, ecuid, DLT_ID_SIZE); } else { /* DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS */ mb->data = calloc(1, sizeof(DltServicePassiveNodeConnectionInfo)); if (mb->data == NULL) { free(mb); return NULL; } mb->size = sizeof(DltServicePassiveNodeConnectionInfo); DltServicePassiveNodeConnectionInfo *serv = (DltServicePassiveNodeConnectionInfo *)mb->data; serv->service_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS; } return mb; } /** * @brief Destroy message body */ void dlt_passive_node_destroy_message_body(DltControlMsgBody *msg_body) { if (msg_body == NULL) return; if (msg_body->data != NULL) free(msg_body->data); free(msg_body); } /** * @brief Send a single command to DLT daemon and wait for response * * @return 0 on success, -1 on error */ static int dlt_passive_node_ctrl_single_request() { int ret = -1; /* Initializing the communication with the daemon */ if (dlt_control_init(dlt_passive_node_analyze_response, get_ecuid(), get_verbosity()) != 0) { pr_error("Failed to initialize connection with the daemon.\n"); return ret; } /* prepare message body */ DltControlMsgBody *msg_body = NULL; msg_body = dlt_passive_node_prepare_message_body(); if (msg_body == NULL) { pr_error("Data for Dlt Message body is NULL\n"); return ret; } ret = dlt_control_send_message(msg_body, get_timeout()); dlt_passive_node_destroy_message_body(msg_body); dlt_control_deinit(); return ret; } static void usage() { printf("Usage: dlt-passive-node-ctrl [options]\n"); printf("Send a trigger to DLT daemon to (dis)connect a passive node " "or get current passive node status \n"); printf("\n"); printf("Options:\n"); printf(" -c Connection status (1 - connect, 0 - disconnect)\n"); printf(" -h Usage\n"); printf(" -n passive Node identifier (e.g. ECU2)\n"); printf(" -s Show passive node(s) connection status\n"); printf(" -t Specify connection timeout (Default: %ds)\n", DLT_CTRL_TIMEOUT); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -v Set verbose flag (Default:%d)\n", get_verbosity()); } /** * @brief Parse application arguments * * The arguments are parsed and saved in static structure for future use. * * @param argc amount of arguments * @param argv argument table * @return 0 on success, -1 otherwise */ static int parse_args(int argc, char *argv[]) { int c = 0; int state = -1; /* Get command line arguments */ opterr = 0; while ((c = getopt(argc, argv, "c:hn:st:SRv")) != -1) switch (c) { case 'c': state = (int)strtol(optarg, NULL, 10); if ((state == DLT_NODE_CONNECT) || (state == DLT_NODE_DISCONNECT)) { set_connection_state((unsigned int) state); set_command(DLT_SERVICE_ID_PASSIVE_NODE_CONNECT); } else { pr_error("unknown connection state: %d\n", state); return -1; } break; case 'h': usage(); return -1; case 'n': set_node_id(optarg); break; case 's': set_command(DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS); break; case 't': set_timeout((int) strtol(optarg, NULL, 10)); break; case 'S': { set_send_serial_header(1); break; } case 'R': { set_resync_serial_header(1); break; } case 'v': set_verbosity(1); pr_verbose("Now in verbose mode.\n"); break; case '?': if (isprint(optopt)) pr_error("Unknown option -%c.\n", optopt); else pr_error("Unknown option character \\x%x.\n", optopt); usage(); return -1; default: pr_error("Try %s -h for more information.\n", argv[0]); return -1; } return 0; } /** * @brief Entry point * * Execute the argument parser and call the main feature accordingly * * @param argc amount of arguments * @param argv argument table * @return 0 on success, -1 otherwise */ int main(int argc, char *argv[]) { int ret = 0; set_ecuid(NULL); set_timeout(DLT_CTRL_TIMEOUT); set_send_serial_header(0); set_resync_serial_header(0); /* Get command line arguments */ if (parse_args(argc, argv) != 0) return -1; if ((get_command() == UNDEFINED) || ((get_command() == DLT_SERVICE_ID_PASSIVE_NODE_CONNECT) && (g_options.node_id[0] == '\0') && (g_options.connection_state == DLT_NODE_CONNECT_UNDEF))) { pr_error("No valid parameter configuration given!\n"); usage(); return -1; } pr_verbose("Sending command to DLT daemon.\n"); /* one shot request */ ret = dlt_passive_node_ctrl_single_request(); pr_verbose("Exiting.\n"); return ret; } dlt-daemon-2.18.10/src/console/dlt-receive.c000066400000000000000000000547611446635226000205340ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-receive.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-receive.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include /* for isprint() */ #include /* for atoi() */ #include /* for S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH */ #include /* for open() */ #include /* for writev() */ #include #include #include #include #include #include #ifdef __linux__ # include #else # include #endif #include #include "dlt_client.h" #include "dlt-control-common.h" #define DLT_RECEIVE_ECU_ID "RECV" DltClient dltclient; void signal_handler(int signal) { switch (signal) { case SIGHUP: case SIGTERM: case SIGINT: case SIGQUIT: /* stop main loop */ shutdown(dltclient.receiver.fd, SHUT_RD); break; default: /* This case should never happen! */ break; } /* switch */ } /* Function prototypes */ int dlt_receive_message_callback(DltMessage *message, void *data); typedef struct { int aflag; int sflag; int xflag; int mflag; int vflag; int yflag; int uflag; char *ovalue; char *ovaluebase; /* ovalue without ".dlt" */ char *fvalue; /* filename for space separated filter file ( ) */ char *jvalue; /* filename for json filter file */ char *evalue; int bvalue; int sendSerialHeaderFlag; int resyncSerialHeaderFlag; int64_t climit; char ecuid[4]; int ohandle; int64_t totalbytes; /* bytes written so far into the output file, used to check the file size limit */ int part_num; /* number of current output file if limit was exceeded */ DltFile file; DltFilter filter; int port; char *ifaddr; } DltReceiveData; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-receive [options] hostname/serial_device_name\n"); printf("Receive DLT messages from DLT daemon and print or store the messages.\n"); printf("Use filters to filter received messages.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -a Print DLT messages; payload as ASCII\n"); printf(" -x Print DLT messages; payload as hex\n"); printf(" -m Print DLT messages; payload as hex and ASCII\n"); printf(" -s Print DLT messages; only headers\n"); printf(" -v Verbose mode\n"); printf(" -h Usage\n"); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -y Serial device mode\n"); printf(" -u UDP multicast mode\n"); printf(" -i addr Host interface address\n"); printf(" -b baudrate Serial device baudrate (Default: 115200)\n"); printf(" -e ecuid Set ECU ID (Default: RECV)\n"); printf(" -o filename Output messages in new DLT file\n"); printf(" -c limit Restrict file size to bytes when output to file\n"); printf(" When limit is reached, a new file is opened. Use K,M,G as\n"); printf(" suffix to specify kilo-, mega-, giga-bytes respectively\n"); printf(" -f filename Enable filtering of messages with space separated list ( )\n"); printf(" -j filename Enable filtering of messages with filter defined in json file\n"); printf(" -p port Use the given port instead the default port\n"); printf(" Cannot be used with serial devices\n"); } int64_t convert_arg_to_byte_size(char *arg) { size_t i; int64_t factor; int64_t result; /* check if valid input */ for (i = 0; i < strlen(arg) - 1; ++i) if (!isdigit(arg[i])) return -2; /* last character */ factor = 1; if ((arg[strlen(arg) - 1] == 'K') || (arg[strlen(arg) - 1] == 'k')) factor = 1024; else if ((arg[strlen(arg) - 1] == 'M') || (arg[strlen(arg) - 1] == 'm')) factor = 1024 * 1024; else if ((arg[strlen(arg) - 1] == 'G') || (arg[strlen(arg) - 1] == 'g')) factor = 1024 * 1024 * 1024; else if (!isdigit(arg[strlen(arg) - 1])) return -2; /* range checking */ int64_t const mult = atoll(arg); if (((INT64_MAX) / factor) < mult) /* Would overflow! */ return -2; result = factor * mult; /* The result be at least the size of one message * One message consists of its header + user data: */ DltMessage msg; int64_t min_size = sizeof(msg.headerbuffer); min_size += 2048 /* DLT_USER_BUF_MAX_SIZE */; if (min_size > result) { dlt_vlog(LOG_ERR, "ERROR: Specified limit: %" PRId64 "is smaller than a the size of a single message: %" PRId64 "!\n", result, min_size); result = -2; } return result; } /* * open output file */ int dlt_receive_open_output_file(DltReceiveData *dltdata) { /* if (file_already_exists) */ glob_t outer; if (glob(dltdata->ovalue, #ifndef __ANDROID_API__ GLOB_TILDE | #endif GLOB_NOSORT, NULL, &outer) == 0) { if (dltdata->vflag) dlt_vlog(LOG_INFO, "File %s already exists, need to rename first\n", dltdata->ovalue); if (dltdata->part_num < 0) { char pattern[PATH_MAX + 1]; pattern[PATH_MAX] = 0; snprintf(pattern, PATH_MAX, "%s.*.dlt", dltdata->ovaluebase); glob_t inner; /* sort does not help here because we have to traverse the * full result in any case. Remember, a sorted list would look like: * foo.1.dlt * foo.10.dlt * foo.1000.dlt * foo.11.dlt */ if (glob(pattern, #ifndef __ANDROID_API__ GLOB_TILDE | #endif GLOB_NOSORT, NULL, &inner) == 0) { /* search for the highest number used */ size_t i; for (i = 0; i < inner.gl_pathc; ++i) { /* convert string that follows the period after the initial portion, * e.g. gt.gl_pathv[i] = foo.1.dlt -> atoi("1.dlt"); */ int cur = atoi(&inner.gl_pathv[i][strlen(dltdata->ovaluebase) + 1]); if (cur > dltdata->part_num) dltdata->part_num = cur; } } globfree(&inner); ++dltdata->part_num; } char filename[PATH_MAX + 1]; filename[PATH_MAX] = 0; snprintf(filename, PATH_MAX, "%s.%i.dlt", dltdata->ovaluebase, dltdata->part_num++); if (rename(dltdata->ovalue, filename) != 0) dlt_vlog(LOG_ERR, "ERROR: rename %s to %s failed with error %s\n", dltdata->ovalue, filename, strerror(errno)); else if (dltdata->vflag) dlt_vlog(LOG_INFO, "Renaming existing file from %s to %s\n", dltdata->ovalue, filename); } /* if (file_already_exists) */ globfree(&outer); dltdata->ohandle = open(dltdata->ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); return dltdata->ohandle; } void dlt_receive_close_output_file(DltReceiveData *dltdata) { if (dltdata->ohandle) { close(dltdata->ohandle); dltdata->ohandle = -1; } } /** * Main function of tool. */ int main(int argc, char *argv[]) { DltReceiveData dltdata; memset(&dltdata, 0, sizeof(dltdata)); int c; int index; /* Initialize dltdata */ dltdata.climit = -1; /* default: -1 = unlimited */ dltdata.ohandle = -1; dltdata.part_num = -1; dltdata.port = 3490; /* Config signal handler */ struct sigaction act; /* Initialize signal handler struct */ memset(&act, 0, sizeof(act)); act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); sigaction(SIGHUP, &act, 0); sigaction(SIGTERM, &act, 0); sigaction(SIGINT, &act, 0); sigaction(SIGQUIT, &act, 0); /* Fetch command line arguments */ opterr = 0; while ((c = getopt (argc, argv, "vashSRyuxmf:j:o:e:b:c:p:i:")) != -1) switch (c) { case 'v': { dltdata.vflag = 1; break; } case 'a': { dltdata.aflag = 1; break; } case 's': { dltdata.sflag = 1; break; } case 'x': { dltdata.xflag = 1; break; } case 'm': { dltdata.mflag = 1; break; } case 'h': { usage(); return -1; } case 'S': { dltdata.sendSerialHeaderFlag = 1; break; } case 'R': { dltdata.resyncSerialHeaderFlag = 1; break; } case 'y': { dltdata.yflag = 1; break; } case 'u': { dltdata.uflag = 1; break; } case 'i': { dltdata.ifaddr = optarg; break; } case 'f': { dltdata.fvalue = optarg; break; } case 'j': { #ifdef EXTENDED_FILTERING dltdata.jvalue = optarg; break; #else fprintf (stderr, "Extended filtering is not supported. Please build with the corresponding cmake option to use it.\n"); return -1; #endif } case 'o': { dltdata.ovalue = optarg; size_t to_copy = strlen(dltdata.ovalue); if (strcmp(&dltdata.ovalue[to_copy - 4], ".dlt") == 0) to_copy = to_copy - 4; dltdata.ovaluebase = (char *)calloc(1, to_copy + 1); if (dltdata.ovaluebase == NULL) { fprintf (stderr, "Memory allocation failed.\n"); return -1; } dltdata.ovaluebase[to_copy] = '\0'; memcpy(dltdata.ovaluebase, dltdata.ovalue, to_copy); break; } case 'e': { dltdata.evalue = optarg; break; } case 'b': { dltdata.bvalue = atoi(optarg); break; } case 'p': { dltdata.port = atoi(optarg); break; } case 'c': { dltdata.climit = convert_arg_to_byte_size(optarg); if (dltdata.climit < -1) { fprintf (stderr, "Invalid argument for option -c.\n"); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } break; } case '?': { if ((optopt == 'o') || (optopt == 'f') || (optopt == 'c')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1; /*for parasoft */ } } /* Initialize DLT Client */ dlt_client_init(&dltclient, dltdata.vflag); /* Register callback to be called when message was received */ dlt_client_register_message_callback(dlt_receive_message_callback); /* Setup DLT Client structure */ if(dltdata.uflag) { dltclient.mode = DLT_CLIENT_MODE_UDP_MULTICAST; } else { dltclient.mode = dltdata.yflag; } if (dltclient.mode == DLT_CLIENT_MODE_TCP || dltclient.mode == DLT_CLIENT_MODE_UDP_MULTICAST) { dltclient.port = dltdata.port; unsigned int servIPLength = 1; // Counting the terminating 0 byte for (index = optind; index < argc; index++) { servIPLength += strlen(argv[index]); if (index > optind) { servIPLength++; // For the comma delimiter } } if (servIPLength > 1) { char* servIPString = malloc(servIPLength); strcpy(servIPString, argv[optind]); for (index = optind + 1; index < argc; index++) { strcat(servIPString, ","); strcat(servIPString, argv[index]); } int retval = dlt_client_set_server_ip(&dltclient, servIPString); free(servIPString); if (retval == -1) { fprintf(stderr, "set server ip didn't succeed\n"); return -1; } } if (dltclient.servIP == 0) { /* no hostname selected, show usage and terminate */ fprintf(stderr, "ERROR: No hostname selected\n"); usage(); dlt_client_cleanup(&dltclient, dltdata.vflag); return -1; } if (dltdata.ifaddr != 0) { if (dlt_client_set_host_if_address(&dltclient, dltdata.ifaddr) != DLT_RETURN_OK) { fprintf(stderr, "set host interface address didn't succeed\n"); return -1; } } } else { for (index = optind; index < argc; index++) if (dlt_client_set_serial_device(&dltclient, argv[index]) == -1) { fprintf(stderr, "set serial device didn't succeed\n"); return -1; } if (dltclient.serialDevice == 0) { /* no serial device name selected, show usage and terminate */ fprintf(stderr, "ERROR: No serial device name specified\n"); usage(); return -1; } dlt_client_setbaudrate(&dltclient, dltdata.bvalue); } /* Update the send and resync serial header flags based on command line option */ dltclient.send_serial_header = dltdata.sendSerialHeaderFlag; dltclient.resync_serial_header = dltdata.resyncSerialHeaderFlag; /* initialise structure to use DLT file */ dlt_file_init(&(dltdata.file), dltdata.vflag); /* first parse filter file if filter parameter is used */ dlt_filter_init(&(dltdata.filter), dltdata.vflag); if (dltdata.fvalue) { if (dlt_filter_load(&(dltdata.filter), dltdata.fvalue, dltdata.vflag) < DLT_RETURN_OK) { dlt_file_free(&(dltdata.file), dltdata.vflag); return -1; } dlt_file_set_filter(&(dltdata.file), &(dltdata.filter), dltdata.vflag); } #ifdef EXTENDED_FILTERING if (dltdata.jvalue) { if (dlt_json_filter_load(&(dltdata.filter), dltdata.jvalue, dltdata.vflag) < DLT_RETURN_OK) { dlt_file_free(&(dltdata.file), dltdata.vflag); return -1; } dlt_file_set_filter(&(dltdata.file), &(dltdata.filter), dltdata.vflag); } #endif /* open DLT output file */ if (dltdata.ovalue) { if (dltdata.climit > -1) { dlt_vlog(LOG_INFO, "Using file size limit of %" PRId64 "bytes\n", dltdata.climit); dltdata.ohandle = dlt_receive_open_output_file(&dltdata); } else { /* in case no limit for the output file is given, we simply overwrite any existing file */ dltdata.ohandle = open(dltdata.ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); } if (dltdata.ohandle == -1) { dlt_file_free(&(dltdata.file), dltdata.vflag); fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", dltdata.ovalue); return -1; } } if (dltdata.evalue) dlt_set_id(dltdata.ecuid, dltdata.evalue); else dlt_set_id(dltdata.ecuid, DLT_RECEIVE_ECU_ID); /* Connect to TCP socket or open serial device */ if (dlt_client_connect(&dltclient, dltdata.vflag) != DLT_RETURN_ERROR) { /* Dlt Client Main Loop */ dlt_client_main_loop(&dltclient, &dltdata, dltdata.vflag); /* Dlt Client Cleanup */ dlt_client_cleanup(&dltclient, dltdata.vflag); } /* dlt-receive cleanup */ if (dltdata.ovalue) close(dltdata.ohandle); free(dltdata.ovaluebase); dlt_file_free(&(dltdata.file), dltdata.vflag); dlt_filter_free(&(dltdata.filter), dltdata.vflag); return 0; } int dlt_receive_message_callback(DltMessage *message, void *data) { DltReceiveData *dltdata; static char text[DLT_RECEIVE_BUFSIZE]; struct iovec iov[2]; int bytes_written; if ((message == 0) || (data == 0)) return -1; dltdata = (DltReceiveData *)data; /* prepare storage header */ if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) dlt_set_storageheader(message->storageheader, message->headerextra.ecu); else dlt_set_storageheader(message->storageheader, dltdata->ecuid); if (((dltdata->fvalue || dltdata->jvalue) == 0) || (dlt_message_filter_check(message, &(dltdata->filter), dltdata->vflag) == DLT_RETURN_TRUE)) { /* if no filter set or filter is matching display message */ if (dltdata->xflag) { dlt_message_print_hex(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); } else if (dltdata->aflag) { dlt_message_header(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); printf("%s ", text); dlt_message_payload(message, text, DLT_RECEIVE_BUFSIZE, DLT_OUTPUT_ASCII, dltdata->vflag); printf("[%s]\n", text); } else if (dltdata->mflag) { dlt_message_print_mixed_plain(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); } else if (dltdata->sflag) { dlt_message_header(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); printf("%s \n", text); } /* if file output enabled write message */ if (dltdata->ovalue) { iov[0].iov_base = message->headerbuffer; iov[0].iov_len = (uint32_t)message->headersize; iov[1].iov_base = message->databuffer; iov[1].iov_len = (uint32_t)message->datasize; if (dltdata->climit > -1) { uint32_t bytes_to_write = message->headersize + message->datasize; if ((bytes_to_write + dltdata->totalbytes > dltdata->climit)) { dlt_receive_close_output_file(dltdata); if (dlt_receive_open_output_file(dltdata) < 0) { printf( "ERROR: dlt_receive_message_callback: Unable to open log when maximum filesize was reached!\n"); return -1; } dltdata->totalbytes = 0; } } bytes_written = (int)writev(dltdata->ohandle, iov, 2); dltdata->totalbytes += bytes_written; if (0 > bytes_written) { printf("dlt_receive_message_callback: writev(dltdata->ohandle, iov, 2); returned an error!"); return -1; } } } return 0; } dlt-daemon-2.18.10/src/console/dlt-sortbytimestamp.c000066400000000000000000000353411446635226000223510ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2018, Codethink Ltd. * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Jonathan Sambrook * * \copyright Copyright © 2018 Codethink Ltd. \n * Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-sortbytimestamp.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-sortbytimestamp.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Jonathan Sambrook jonathasambrook@codethink.co.uk ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** js Jonathan Sambrook Codethink ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include /* writev() */ #include "dlt_common.h" #define DLT_VERBUFSIZE 255 #define FIFTY_SEC_IN_MSEC 500000 #define THREE_MIN_IN_SEC 180 typedef struct sTimestampIndex { int num; uint32_t tmsp; uint32_t systmsp; } TimestampIndex; int verbosity = 0; /** * Print information, conditional upon requested verbosity level */ void verbose(int level, char *msg, ...) PRINTF_FORMAT(2, 3); void verbose(int level, char *msg, ...) { if (level <= verbosity) { if (verbosity > 1) { /* timestamp */ time_t tnow = time((time_t *)0); if (tnow != -1) { char snow[50]; ctime_r(&tnow, snow); /* suppress newline char */ snow[strlen(snow) - 1] = 0; printf("%s: ", snow); } } int len = (int) strlen(msg); va_list args; va_start (args, msg); vprintf(msg, args); va_end(args); /* lines without a terminal newline aren't guaranteed to be displayed */ if (msg[len - 1] != '\n') fflush(stdout); } } /** * Comparison function for use with qsort * Used for time stamp */ int compare_index_timestamps(const void *a, const void *b) { int ret = -1; if (((TimestampIndex *)a)->tmsp > ((TimestampIndex *)b)->tmsp) ret = 1; else if (((TimestampIndex *)a)->tmsp == ((TimestampIndex *)b)->tmsp) ret = 0; return ret; } /** * Comparison function for use with qsort * Used for system time */ int compare_index_systime(const void *a, const void *b) { int ret = -1; if(((TimestampIndex *) a)->systmsp > ((TimestampIndex *) b)->systmsp) ret = 1; else if(((TimestampIndex *) a)->systmsp == ((TimestampIndex *) b)->systmsp) ret = 0; return ret; } /** * Write the messages in the order specified by the given index */ void write_messages(int ohandle, DltFile *file, TimestampIndex *timestamps, uint32_t message_count) { struct iovec iov[2]; ssize_t bytes_written; uint32_t i = 0; int last_errno = 0; verbose(1, "Writing %d messages\n", message_count); for (i = 0; i < message_count; ++i) { errno = 0; if ((0 == i % 1001) || (i == message_count - 1)) verbose(2, "Writing message %d\r", i); if (dlt_file_message(file, timestamps[i].num, 0) < DLT_RETURN_OK) continue; iov[0].iov_base = file->msg.headerbuffer; iov[0].iov_len = file->msg.headersize; iov[1].iov_base = file->msg.databuffer; iov[1].iov_len = file->msg.datasize; bytes_written = writev(ohandle, iov, 2); last_errno = errno; if (0 > bytes_written) { printf("%s: returned an error [%s]!\n", __func__, strerror(last_errno)); if (ohandle > 0) { close(ohandle); ohandle = -1; } if (timestamps) { free(timestamps); timestamps = NULL; } dlt_file_free(file, 0); exit (-1); } } verbose (2, "\n"); } /** * Print usage information of tool. */ void usage() { char version[DLT_VERBUFSIZE]; dlt_get_version(version, DLT_VERBUFSIZE); printf("Usage: dlt-sortbytimestamp [options] [commands] file_in file_out\n"); printf("Read DLT file, sort by timestamp and store the messages again.\n"); printf("Use filters to filter DLT messages.\n"); printf("Use range to cut DLT file. Indices are zero based.\n"); printf("%s \n", version); printf("Commands:\n"); printf(" -h Usage\n"); printf("Options:\n"); printf(" -v Verbosity. Multiple uses will effect an increase in loquacity\n"); printf(" -c Count number of messages\n"); printf(" -f filename Enable filtering of messages\n"); printf(" -b number First message in range to be handled (default: first message)\n"); printf(" -e number Last message in range to be handled (default: last message)\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { int vflag = 0; int cflag = 0; char *fvalue = 0; char *bvalue = 0; char *evalue = 0; char *ivalue = 0; char *ovalue = 0; TimestampIndex *timestamp_index = 0; TimestampIndex *temp_timestamp_index = 0; uint32_t message_count = 0; uint32_t count = 0; uint32_t start = 0; uint32_t delta_tmsp = 0; uint32_t delta_systime = 0; size_t i; int c; DltFile file; DltFilter filter; int ohandle = -1; int num, begin, end; opterr = 0; verbose(1, "Configuring\n"); while ((c = getopt (argc, argv, "vchf:b:e:")) != -1) { switch (c) { case 'v': { verbosity += 1; break; } case 'c': { cflag = 1; break; } case 'h': { usage(); return -1; } case 'f': { fvalue = optarg; break; } case 'b': { bvalue = optarg; break; } case 'e': { evalue = optarg; break; } case '?': { if ((optopt == 'f') || (optopt == 'b') || (optopt == 'e')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { usage(); return -1; /*for parasoft */ } } } /* Don't use vflag on quietest levels */ if (verbosity > 2) vflag = 1; verbose (1, "Initializing\n"); /* Initialize structure to use DLT file */ dlt_file_init(&file, vflag); /* first parse filter file if filter parameter is used */ if (fvalue) { if (bvalue || evalue) { fprintf(stderr, "ERROR: can't specify a range *and* filtering!\n"); dlt_file_free(&file, vflag); return -1; } if (dlt_filter_load(&filter, fvalue, vflag) < DLT_RETURN_OK) { dlt_file_free(&file, vflag); return -1; } dlt_file_set_filter(&file, &filter, vflag); } ivalue = argv[optind]; if (!ivalue) { dlt_file_free(&file, vflag); fprintf(stderr, "ERROR: Need an input file!\n"); return -1; } ovalue = argv[optind + 1]; if (ovalue) { ohandle = open(ovalue, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (ohandle == -1) { dlt_file_free(&file, vflag); fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", ovalue); return -1; } } else { dlt_file_free(&file, vflag); fprintf(stderr, "ERROR: Need an output file!\n"); return -1; } verbose(1, "Loading\n"); /* load, analyze data file and create index list */ if (dlt_file_open(&file, ivalue, vflag) >= DLT_RETURN_OK) { while (dlt_file_read(&file, vflag) >= DLT_RETURN_OK) { } } if (cflag) { if (fvalue) printf("Loaded %d messages, %d after filtering.\n", file.counter_total, file.counter); else printf("Loaded %d messages.\n", file.counter_total); } if (bvalue) begin = atoi(bvalue); else begin = 0; if (evalue) end = atoi(evalue); else end = file.counter - 1; if ((begin < 0) || (end < 0) || (begin > end) || (begin >= file.counter) || (end >= file.counter)) { fprintf(stderr, "ERROR: Selected message [begin-end]-[%d-%d] is out of range!\n", begin, end); dlt_file_free(&file, vflag); close(ohandle); return -1; } verbose(2, "Begin: %d End: %d Range: %d\n", begin, end, 1 + end - begin); verbose(1, "Allocating memory\n"); message_count = (uint32_t) (1 + end - begin); timestamp_index = (TimestampIndex *) malloc(sizeof(TimestampIndex) * (message_count + 1)); if (timestamp_index == NULL) { fprintf(stderr, "ERROR: Failed to allocate memory for message index!\n"); dlt_file_free(&file, vflag); close(ohandle); return -1; } verbose(1, "Filling %d entries\n", message_count); for (num = begin; num <= end; num++) { if (dlt_file_message(&file, num, vflag) < DLT_RETURN_OK) continue; timestamp_index[num - begin].num = num; timestamp_index[num - begin].systmsp = file.msg.storageheader->seconds; timestamp_index[num - begin].tmsp = file.msg.headerextra.tmsp; } /* This step is extending the array one more element by copying the first element */ timestamp_index[num].num = timestamp_index[0].num; timestamp_index[num].systmsp = timestamp_index[0].systmsp; timestamp_index[num].tmsp = timestamp_index[0].tmsp; verbose(1, "Sorting\n"); qsort((void *) timestamp_index, message_count, sizeof(TimestampIndex), compare_index_systime); for (num = begin; num <= end; num++) { delta_tmsp = (uint32_t)llabs((int64_t)timestamp_index[num + 1].tmsp - timestamp_index[num].tmsp); delta_systime = (uint32_t)llabs((int64_t)timestamp_index[num + 1].systmsp - timestamp_index[num].systmsp); /* * Here is a try to detect a new cycle of boot in system. * Relatively, if there are gaps whose systime is larger than 3 mins and * timestamp is larger than 15 secs should be identified as a new boot cycle. */ count++; if(delta_tmsp > FIFTY_SEC_IN_MSEC || delta_systime >= THREE_MIN_IN_SEC) { verbose(1, "Detected a new cycle of boot\n"); temp_timestamp_index = (TimestampIndex *) malloc(sizeof(TimestampIndex) * count); if (temp_timestamp_index == NULL) { fprintf(stderr, "ERROR: Failed to allocate memory for array\n"); dlt_file_free(&file, vflag); close(ohandle); return -1; } for (i = 0; i < count; i++) { memcpy((void*) &temp_timestamp_index[i], (void*) ×tamp_index[start + i], sizeof(TimestampIndex)); } qsort((void *) temp_timestamp_index, count, sizeof(TimestampIndex), compare_index_timestamps); write_messages(ohandle, &file, temp_timestamp_index, count); free(temp_timestamp_index); temp_timestamp_index = NULL; start = start + count; count = 0; } } /* * In case there is only cycle of boot in DLT file, * sort the DLT file again by timestamp then write * all messages out. */ if (count == message_count) { qsort((void *) timestamp_index, message_count + 1, sizeof(TimestampIndex), compare_index_timestamps); write_messages(ohandle, &file, timestamp_index, count); } close(ohandle); verbose(1, "Tidying up.\n"); free(timestamp_index); timestamp_index = NULL; dlt_file_free(&file, vflag); return 0; } dlt-daemon-2.18.10/src/console/filter.txt000066400000000000000000000000241446635226000201720ustar00rootroot00000000000000ABCD IJKL TEST LOG dlt-daemon-2.18.10/src/console/logstorage/000077500000000000000000000000001446635226000203165ustar00rootroot00000000000000dlt-daemon-2.18.10/src/console/logstorage/CMakeLists.txt000066400000000000000000000023651446635226000230640ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2015, ADIT GmbH # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### add_definitions(-Werror) set(dlt-logstorage-ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-list.c) if(WITH_DLT_LOGSTORAGE_CTRL_UDEV) set(dlt-logstorage-ctrl_SRCS ${dlt-logstorage-ctrl_SRCS} dlt-logstorage-udev.c) set(LOGSTORAGE_LIBRARY udev) endif() if(WITH_SYSTEMD) set(dlt-logstorage-ctrl_SRCS ${dlt-logstorage-ctrl_SRCS} ${PROJECT_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c) endif() add_executable(dlt-logstorage-ctrl ${dlt-logstorage-ctrl_SRCS} ${dlt_control_common_SRCS}) target_link_libraries(dlt-logstorage-ctrl dlt ${LOGSTORAGE_LIBRARY} dlt_control_common_lib) set_target_properties(dlt-logstorage-ctrl PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-logstorage-ctrl RUNTIME DESTINATION bin COMPONENT base) dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-common.c000066400000000000000000000222241446635226000247010ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-common.c * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-logstorage-common.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** Frederic Berat fberat@de.adit-jv.com ** ** PURPOSE : ** ** ** ** REMARKS : Code extracted from dlt-control-common.c and reworked. ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** ** fb Frederic Berat ADIT ** *******************************************************************************/ #define pr_fmt(fmt) "Logstorage common: "fmt #include #include #include #include #include #include #include #include #include #include "dlt_common.h" #include "dlt_protocol.h" #include "dlt_client.h" #include "dlt-control-common.h" #include "dlt-logstorage-common.h" #ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE # include "dlt-logstorage-udev.h" #endif #include "dlt-logstorage-prop.h" static struct LogstorageOptions { int event_type; /**< EVENT_UNMOUNTING/EVENT_MOUNTED */ char device_path[DLT_MOUNT_PATH_MAX]; /**< Default Mount path */ DltLogstorageHandler handler_type; /**< be controlled by udev or prop */ long timeout; /**< Default timeout */ } g_options = { .event_type = EVENT_MOUNTED, .handler_type = CTRL_NOHANDLER, }; DltLogstorageHandler get_handler_type(void) { return g_options.handler_type; } void set_handler_type(char *type) { g_options.handler_type = CTRL_UDEV; if (type && check_proprietary_handling(type)) g_options.handler_type = CTRL_PROPRIETARY; } int get_default_event_type(void) { return g_options.event_type; } void set_default_event_type(long type) { g_options.event_type = (int) type; } char *get_default_path(void) { return g_options.device_path; } void set_default_path(char *path) { memset(g_options.device_path, 0, DLT_MOUNT_PATH_MAX); if (path != NULL) strncpy(g_options.device_path, path, DLT_MOUNT_PATH_MAX - 1); } /* Used by the handlers */ static DltLogstorageCtrl lctrl; DltLogstorageCtrl *get_logstorage_control(void) { return &lctrl; } void *dlt_logstorage_get_handler_cb(void) { return lctrl.callback; } int dlt_logstorage_get_handler_fd(void) { return lctrl.fd; } /** @brief Initialized the handler based on configuration * * @return 0 on success, -1 otherwise. */ int dlt_logstorage_init_handler(void) { switch (get_handler_type()) { case CTRL_PROPRIETARY: return dlt_logstorage_prop_init(); case CTRL_UDEV: default: #ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE return dlt_logstorage_udev_init(); #else return -1; #endif } } /** @brief Clean-up the handler based on configuration * * @return 0 on success, -1 otherwise. */ int dlt_logstorage_deinit_handler(void) { switch (get_handler_type()) { case CTRL_PROPRIETARY: return dlt_logstorage_prop_deinit(); case CTRL_UDEV: default: #ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE return dlt_logstorage_udev_deinit(); #else return -1; #endif } } /** @brief Search for config file in given mount point * * The file is searched at the top directory. The function exits once it * founds it. * * @param mnt_point The mount point to check * * @return 1 if the file is found, 0 otherwise. */ int dlt_logstorage_check_config_file(char *mnt_point) { struct dirent **files; int n; int i = 0; int ret = 0; if ((mnt_point == NULL) || (mnt_point[0] == '\0')) { pr_error("Mount point missing.\n"); return ret; } pr_verbose("Now scanning %s\n", mnt_point); n = scandir(mnt_point, &files, NULL, alphasort); if (n <= 0) { pr_error("Cannot read mounted directory\n"); return ret; } do { pr_verbose("Checking %s.\n", files[i]->d_name); if (strncmp(files[i]->d_name, CONF_NAME, strlen(CONF_NAME)) == 0) { /* We found it ! */ pr_verbose("File found.\n"); ret = 1; break; } } while (++i < n); for (i = 0; i < n; i++) free(files[i]); free(files); return ret; } /** @brief Check if given mount point is writable * * @param mnt_point The mount point to check * * @return 1 if the file is writable, 0 otherwise. */ int dlt_logstorage_check_directory_permission(char *mnt_point) { if (mnt_point == NULL) { pr_error("Given mount point is NULL\n"); return 0; } if (access(mnt_point, W_OK) == 0) return 1; return 0; } /** @brief Prepares the body of the message to be send to DLT * * @param body A pointer to the MsgBody structure pointer * @param conn_type The type of the event (Mounted/Unmounting) * @param path The mount point path. * * @return The body once built or NULL. */ static DltControlMsgBody *prepare_message_body(DltControlMsgBody **body, int conn_type, char *path) { DltServiceOfflineLogstorage *serv = NULL; if (path == NULL) { pr_error("Mount path is uninitialized.\n"); return NULL; } pr_verbose("Sending event %d for %s.\n", conn_type, path); *body = calloc(1, sizeof(DltControlMsgBody)); if (!*body) { pr_error("Not able to allocate memory for body.\n"); return *body; } (*body)->data = calloc(1, sizeof(DltServiceOfflineLogstorage)); if (!(*body)->data) { free(*body); *body = NULL; pr_error("Not able to allocate memory for body data.\n"); return NULL; } (*body)->size = sizeof(DltServiceOfflineLogstorage); serv = (DltServiceOfflineLogstorage *)(*body)->data; serv->service_id = DLT_SERVICE_ID_OFFLINE_LOGSTORAGE; serv->connection_type = (uint8_t) conn_type; /* mount_point is DLT_MOUNT_PATH_MAX + 1 long, * and the memory is already zeroed. */ strncpy(serv->mount_point, path, DLT_MOUNT_PATH_MAX - 1); pr_verbose("Body is now ready.\n"); return *body; } /** @brief Send a logstorage event to DLT * * @param type The type of the event (Mounted/Unmounting) * @param mount_point The mount point for this event * * @return 0 On success, -1 otherwise. */ int dlt_logstorage_send_event(int type, char *mount_point) { int ret = 0; DltControlMsgBody *msg_body = NULL; /* mount_point is checked against NULL in the preparation */ if (!prepare_message_body(&msg_body, type, mount_point)) { pr_error("Data for Dlt Message body is NULL\n"); return -1; } ret = dlt_control_send_message(msg_body, get_timeout()); free(msg_body->data); free(msg_body); return ret; } dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-common.h000066400000000000000000000051061446635226000247060ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-common.h * For further information see http://www.covesa.org/. */ #ifndef _DLT_LOGSTORAGE_COMMON_H_ #define _DLT_LOGSTORAGE_COMMON_H_ #define CONF_NAME "dlt_logstorage.conf" #define EVENT_UNMOUNTING 0 #define EVENT_MOUNTED 1 #define EVENT_SYNC_CACHE 2 typedef enum { CTRL_NOHANDLER = 0, /**< one shot application */ CTRL_UDEV, /**< Handles udev events */ CTRL_PROPRIETARY /**< Handles proprietary event */ } DltLogstorageHandler; DltLogstorageHandler get_handler_type(void); void set_handler_type(char *); char *get_default_path(void); void set_default_path(char *); int get_default_event_type(void); void set_default_event_type(long type); typedef struct { int fd; int (*callback)(void); /* callback for event handling */ void *prvt; /* Private data */ } DltLogstorageCtrl; /* Get a reference to the logstorage control instance */ DltLogstorageCtrl *get_logstorage_control(void); void *dlt_logstorage_get_handler_cb(void); int dlt_logstorage_get_handler_fd(void); int dlt_logstorage_init_handler(void); int dlt_logstorage_deinit_handler(void); /** * Send an event to the dlt daemon * * @param type Event type (EVENT_UNMOUNTING/EVENT_MOUNTED) * @param mount_point The mount point path concerned by this event * * @return 0 on success, -1 on error */ int dlt_logstorage_send_event(int, char *); /** @brief Search for config file in given mount point * * The file is searched at the top directory. The function exits once it * founds it. * * @param mnt_point The mount point to check * * @return 1 if the file is found, 0 otherwise. */ int dlt_logstorage_check_config_file(char *); /** @brief Check if given mount point is writable * * @param mnt_point The mount point to check * * @return 1 if the file is writable, 0 otherwise. */ int dlt_logstorage_check_directory_permission(char *mnt_point); #endif dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-ctrl.c000066400000000000000000000443701446635226000243630ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-ctrl.c * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-logstorage-ctrl.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Syed Hameed shameed@jp.adit-jv.com ** ** Christoph Lipka clipka@jp.adit-jv.com ** ** AnithaAmmaji.baggam@in.bosch.com ** ** Frederic Berat fberat@de.adit-jv.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** sh Syed Hameed ADIT ** ** cl Christoph Lipka ADIT ** ** BA Anitha BA ADIT ** ** fb Frederic Berat ADIT ** *******************************************************************************/ #define pr_fmt(fmt) "Logstorage control: "fmt #include #include #include #include #include #include #include #include #if defined(__linux__) # include "sd-daemon.h" #endif #include "dlt_protocol.h" #include "dlt_client.h" #include "dlt-control-common.h" #include "dlt-logstorage-common.h" #include "dlt-logstorage-ctrl.h" #define POLL_TIME_OUT 500 #define EV_MASK_REJECTED (POLLERR | POLLHUP | POLLNVAL) #define DLT_LOGSTORAGE_CTRL_EXIT 1 static int must_exit; struct dlt_event { struct pollfd pfd; void *func; }; /** @brief Triggers the application exit * * The application will exit on next poll timeout. */ void dlt_logstorage_exit(void) { must_exit = DLT_LOGSTORAGE_CTRL_EXIT; } /** @brief Check if the application must exit * * The application will exit on next poll timeout. */ int dlt_logstorage_must_exit(void) { return must_exit; } /** @brief Signal handler. * * Triggers the exit of the application in case of specific signals * * @param signo The value of the signal received. */ static void catch_signal(int signo) { if (signo) { pr_error("Signal %d received, exiting.", signo); dlt_logstorage_exit(); } } /** @brief Install a handler for some signals * * Handler are installed on exit related signals. That allows to exit from * the main loop gracefully. */ static void install_signal_handler(void) { int signals[] = { SIGINT, SIGQUIT, SIGTERM, 0 }; unsigned int i; struct sigaction sa; pr_verbose("Installing signal handler.\n"); /* install a signal handler for the above listed signals */ for (i = 0; signals[i]; i++) { memset(&sa, 0, sizeof(sa)); sa.sa_handler = catch_signal; if (sigaction(signals[i], &sa, NULL) < 0) pr_error("Failed to install signal %u handler. Error: %s\n", signals[i], strerror(errno)); } } #define MAX_RESPONSE_LENGTH 32 /** @brief Analyze the daemon answer to a request * * This function checks whether if the daemon answered positively to * the request or not. * * @param data The textual answer * @param payload The answer payload * @param len The answer payload length * @return 0 on success, -1 otherwise. */ static int analyze_response(char *data, void *payload, int len) { int ret = -1; char resp_ok[MAX_RESPONSE_LENGTH] = { 0 }; char resp_warning[MAX_RESPONSE_LENGTH] = { 0 }; char resp_perm_denied[MAX_RESPONSE_LENGTH] = { 0 }; if ((data == NULL) || (payload == NULL)) return -1; /* satisfy compiler */ (void)payload; (void)len; snprintf(resp_ok, MAX_RESPONSE_LENGTH, "service(%d), ok", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); snprintf(resp_warning, MAX_RESPONSE_LENGTH, "service(%d), warning", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); snprintf(resp_perm_denied, MAX_RESPONSE_LENGTH, "service(%d), perm_denied", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); if (strncmp(data, resp_ok, strlen(resp_ok)) == 0) ret = 0; if (strncmp(data, resp_warning, strlen(resp_warning)) == 0) { pr_error("Warning:Some filter configurations are ignored due to configuration issues \n"); ret = 0; } if (strncmp(data, resp_perm_denied, strlen(resp_perm_denied)) == 0) { pr_error("Warning: Permission denied.\n"); ret = 0; } pr_verbose("Response received: '%s'\n", data); pr_verbose("Response expected: '%s'\n", resp_ok); return ret; } /** @brief Add a new event to watch * * This function could be exported to be used by udev/prop so that they can * register several events. * * @param ev_hdl The structure containing the file descriptors * @param fd The file descriptor to watch * @param cb The callback to be called on event. * * @return 0 on success, -1 if the parameters are invalid. */ static int dlt_logstorage_ctrl_add_event(struct dlt_event *ev_hdl, int fd, void *cb) { if ((fd < 0) || !cb || !ev_hdl) { pr_error("Wrong parameter to add event (%d %p)\n", fd, cb); return -1; } pr_verbose("Setting up the event handler with (%d, %p).\n", fd, cb); ev_hdl->func = cb; ev_hdl->pfd.fd = fd; return 0; } /** @brief Main execution loop * * Waits on events, and executes the callbacks retrieved * back from the event structure. * * @return 0 on success, -1 otherwise. */ static int dlt_logstorage_ctrl_execute_event_loop(struct dlt_event *ev) { int ret = 0; int (*callback)() = ev->func; ret = poll(&ev->pfd, 1, POLL_TIME_OUT); if (ret <= 0) { if (errno == EINTR) ret = 0; if (ret < 0) pr_error("poll error: %s\n", strerror(errno)); return ret; } if (ev->pfd.revents == 0) return 0; if (ev->pfd.events & EV_MASK_REJECTED) { pr_error("Error while polling. Event received: 0x%x\n", ev->pfd.events); /* We only support one event producer. * Error means that this producer died. */ pr_error("Now closing fd and exiting.\n"); close(ev->pfd.fd); ev->pfd.fd = -1; dlt_logstorage_exit(); return -1; } if (!callback) { pr_error("Callback not found, exiting.\n"); dlt_logstorage_exit(); return -1; } pr_verbose("Got new event, calling %p.\n", callback); if (callback() < 0) { pr_error("Error while calling the callback, exiting.\n"); dlt_logstorage_exit(); return -1; } return 0; } /** @brief Start event loop and receive messages from DLT. * * The function will first install the signal handler, * then create the poll instance, initialize the communication controller, * initialize the event handler and finally start the polling. * * @return 0 on success, -1 on error */ static int dlt_logstorage_ctrl_setup_event_loop(void) { int ret = 0; struct dlt_event ev_hdl = { .pfd = { .fd = -1, .events = POLLIN } }; install_signal_handler(); pr_verbose("Creating poll instance.\n"); /* Initializing the communication with the daemon */ while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && !dlt_logstorage_must_exit()) { pr_error("Failed to initialize connection with the daemon.\n"); pr_error("Retrying to connect in %ds.\n", get_timeout()); sleep((unsigned int) get_timeout()); } if (dlt_logstorage_must_exit()) { pr_verbose("Exiting.\n"); return 0; } pr_verbose("Initializing event generator.\n"); if (dlt_logstorage_init_handler() < 0) { pr_error("Failed to initialize handler.\n"); dlt_control_deinit(); return -1; } if (dlt_logstorage_ctrl_add_event(&ev_hdl, dlt_logstorage_get_handler_fd(), dlt_logstorage_get_handler_cb()) < 0) { pr_error("add_event error: %s\n", strerror(errno)); dlt_logstorage_exit(); } while (!dlt_logstorage_must_exit() && (ret == 0)) ret = dlt_logstorage_ctrl_execute_event_loop(&ev_hdl); /* Clean up */ dlt_logstorage_deinit_handler(); dlt_control_deinit(); return ret; } /** @brief Send a single command to DLT daemon and wait for response * * @return 0 on success, -1 otherwise. */ static int dlt_logstorage_ctrl_single_request() { int ret = 0; /* in case sync all caches, an empty path is given */ if (get_default_event_type() != EVENT_SYNC_CACHE) { /* Check if a 'CONF_NAME' file is present at the given path */ if (!dlt_logstorage_check_config_file(get_default_path())) { pr_error("No '%s' file available at: %s\n", CONF_NAME, get_default_path()); return -1; } if (!dlt_logstorage_check_directory_permission(get_default_path())) { pr_error("'%s' is not writable\n", get_default_path()); return -1; } } /* Initializing the communication with the daemon */ while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && !dlt_logstorage_must_exit()) { pr_error("Failed to initialize connection with the daemon.\n"); pr_error("Retrying to connect in %ds.\n", get_timeout()); sleep( (unsigned int) get_timeout()); } pr_verbose("event type is [%d]\t device path is [%s]\n", get_default_event_type(), get_default_path()); ret = dlt_logstorage_send_event(get_default_event_type(), get_default_path()); dlt_control_deinit(); return ret; } /** @brief Print out the application help */ static void usage(void) { printf("Usage: dlt-logstorage-ctrl [options]\n"); printf("Send a trigger to DLT daemon to connect/disconnect" "a certain logstorage device\n"); printf("\n"); printf("Options:\n"); printf(" -c --command Connection type: connect = 1, disconnect = 0\n"); printf(" -d[prop] --daemonize=prop Run as daemon: prop = use proprietary handler\n"); printf(" 'prop' may be replaced by any meaningful word\n"); printf(" If prop is not specified, udev will be used\n"); printf(" -e --ecuid Set ECU ID (Default: %s)\n", DLT_CTRL_DEFAULT_ECUID); printf(" -h --help Usage\n"); printf(" -p --path Mount point path\n"); printf(" -s[path] --snapshot=path Sync Logstorage cache\n"); printf(" Don't use -s together with -d and -c\n"); printf(" -t Specify connection timeout (Default: %ds)\n", DLT_CTRL_TIMEOUT); printf(" -S --send-header Send message with serial header (Default: Without serial header)\n"); printf(" -R --resync-header Enable resync serial header\n"); printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity()); } static struct option long_options[] = { {"command", required_argument, 0, 'c'}, {"daemonize", optional_argument, 0, 'd'}, {"ecuid", required_argument, 0, 'e'}, {"help", no_argument, 0, 'h'}, {"path", required_argument, 0, 'p'}, {"snapshot", optional_argument, 0, 's'}, {"timeout", required_argument, 0, 't'}, {"send-header", no_argument, 0, 'S'}, {"resync-header", no_argument, 0, 'R'}, {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0} }; /** @brief Parses the application arguments * * The arguments are parsed and saved in static structure for future use. * * @param argc The amount of arguments * @param argv The table of arguments * * @return 0 on success, -1 otherwise */ static int parse_args(int argc, char *argv[]) { int c = -1; int long_index = 0; while ((c = getopt_long(argc, argv, ":s::t:hSRe:p:d::c:v", long_options, &long_index)) != -1) switch (c) { case 's': set_default_event_type(EVENT_SYNC_CACHE); if ((optarg != NULL) && (strlen(optarg) >= DLT_MOUNT_PATH_MAX)) { pr_error("Mount path '%s' too long\n", optarg); return -1; } set_default_path(optarg); break; case 't': set_timeout((int) strtol(optarg, NULL, 10)); break; case 'S': { set_send_serial_header(1); break; } case 'R': { set_resync_serial_header(1); break; } case 'h': usage(); return -1; case 'e': set_ecuid(optarg); break; case 'd': pr_verbose("Choosing handler.\n"); set_handler_type(optarg); pr_verbose("Handler chosen: %d.\n", get_handler_type()); break; case 'p': if (strlen(optarg) >= DLT_MOUNT_PATH_MAX) { pr_error("Mount path '%s' too long\n", optarg); return -1; } set_default_path(optarg); break; case 'c': set_default_event_type(strtol(optarg, NULL, 10)); break; case 'v': set_verbosity(1); pr_verbose("Now in verbose mode.\n"); break; case ':': pr_error("Option -%c requires an argument.\n", optopt); usage(); return -1; case '?': if (isprint(optopt)) pr_error("Unknown option -%c.\n", optopt); else pr_error("Unknown option character \\x%x.\n", optopt); usage(); return -1; default: pr_error("Try %s -h for more information.\n", argv[0]); return -1; } if ((get_default_event_type() == EVENT_SYNC_CACHE) && (get_handler_type() != CTRL_NOHANDLER)) { pr_error("Sync caches not available in daemon mode\n"); return -1; } return 0; } #if !defined(DLT_SYSTEMD_ENABLE) int sd_notify(int unset_environment, const char *state) { /* Satisfy Compiler for warnings */ (void)unset_environment; (void)state; return 0; } #endif /** @brief Entry point * * Execute the argument parser and call the main feature accordingly. * * @param argc The amount of arguments * @param argv The table of arguments * * @return 0 on success, -1 otherwise */ int main(int argc, char *argv[]) { int ret = 0; set_ecuid(NULL); set_timeout(DLT_CTRL_TIMEOUT); set_send_serial_header(0); set_resync_serial_header(0); /* Get command line arguments */ if (parse_args(argc, argv) != 0) return -1; /* all parameter valid, start communication with daemon or setup * communication with control daemon */ if (get_handler_type() == CTRL_NOHANDLER) { pr_verbose("One shot.\n"); ret = dlt_logstorage_ctrl_single_request(); if (ret < 0) pr_error("Message failed to be send. Please check DLT config.\n"); } else { pr_verbose("Entering in daemon mode.\n"); /* Let's daemonize */ if (sd_notify(0, "READY=1") <= 0) { pr_verbose("SD notify failed, manually daemonizing.\n"); /* No message can be sent or Systemd is not available. * Daemonizing manually. */ if (daemon(1, 1)) { pr_error("Failed to daemonize: %s\n", strerror(errno)); return EXIT_FAILURE; } } pr_verbose("Executing the event loop\n"); ret = dlt_logstorage_ctrl_setup_event_loop(); } pr_verbose("Exiting.\n"); return ret; } dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-ctrl.h000066400000000000000000000016161446635226000243640ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * * \file dlt-logstorage-ctrl.h * For further information see http://www.covesa.org/. */ #ifndef _DLT_LOGSTORAGE_CONTROL_H_ #define _DLT_LOGSTORAGE_CONTROL_H_ /* Triggers the exit at the end of the event */ void dlt_logstorage_exit(void); #endif dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-list.c000066400000000000000000000164601446635226000243710ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Anitha.BA ADIT 2015 * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-list.c * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-logstorage-list.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** Anitha.B.A anithaammaji.baggam@in.bosch.com ** ** Frederic Berat fberat@de.adit-jv.com ** ** ** ** PURPOSE : linked list implementation for storing the device info ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** BA Anitha ADIT ** ** cl Christoph Lipka ADIT ** ** fb Frederic Berat ADIT ** *******************************************************************************/ #define pr_fmt(fmt) "Log storage list: "fmt #include #include #include #include #include "dlt_common.h" #include "dlt-control-common.h" #include "dlt-logstorage-common.h" static struct LogstorageDeviceInfo { char *dev_node; /**< The device node */ char *mnt_point; /**< Mount point for this device */ struct LogstorageDeviceInfo *prev; /**< Previous element of the list */ struct LogstorageDeviceInfo *next; /**< Next element of the list */ } *g_info; /** @brief Prints the device list in verbose mode * * This can be used to debug the behavior. * Therefore, it's only available in verbose mode. */ void print_list() { struct LogstorageDeviceInfo *ptr = g_info; pr_verbose(" -------Device list-------\n"); while (ptr != NULL) { pr_verbose("%p:\t[%s][%s] \n", ptr, ptr->dev_node, ptr->mnt_point); ptr = ptr->next; } pr_verbose(" -------Device list end-------\n\n"); return; } /** @brief Find element in the list based on device node * * Allows to check whether a device is already in the list or * to find out the one to be removed. * * @param node The device node to look for * * @return The element of the list found, NULL either. */ static struct LogstorageDeviceInfo *logstorage_find_dev_info(const char *node) { struct LogstorageDeviceInfo *ptr = g_info; if (!node) return NULL; pr_verbose("Looking for %s.\n", node); while (ptr != NULL) { if (strncmp(ptr->dev_node, node, DLT_MOUNT_PATH_MAX) == 0) { pr_verbose("%s found in %p.\n", node, ptr); break; } else { ptr = ptr->next; } } return ptr; } /** @brief Add new device in the list * * The device is only added if a configuration file has been found and * if it's not already in the list. * * @param node The device node to add * @param path The corresponding mount point path * * @return 0 on success, -1 in case of error. */ int logstorage_store_dev_info(const char *node, const char *path) { struct LogstorageDeviceInfo *ptr = NULL; size_t path_len = 0; if ((node == NULL) || (path == NULL)) { pr_error("Invalid input\n"); return -1; } if (logstorage_find_dev_info(node)) { pr_verbose("%s already in list.\n", node); print_list(); return 0; } ptr = calloc(1, sizeof(struct LogstorageDeviceInfo)); if (ptr == NULL) { pr_error("Node creation failed\n"); return -1; } ptr->dev_node = strdup(node); path_len = strlen(path); if (path_len > DLT_MOUNT_PATH_MAX) path_len = (size_t)DLT_MOUNT_PATH_MAX; ptr->mnt_point = (char *)calloc(1, path_len + 1); if (ptr->mnt_point == NULL) { pr_error("memory allocation failed for mnt_point\n"); free(ptr); ptr = NULL; return -1; } ptr->mnt_point[path_len] = '\0'; memcpy(ptr->mnt_point, path, path_len); /* Put it on head */ ptr->next = g_info; if (g_info) g_info->prev = ptr; g_info = ptr; pr_verbose("%s added to list.\n", node); print_list(); return 0; } /** @brief Remove a device from the list * * If the device is removed from the list, the mount point * pointer is given back to the caller. That means that * he has to free it. * * @param node The device node to be removed * * @return the mount point if the node is found, NULL either. */ char *logstorage_delete_dev_info(const char *node) { struct LogstorageDeviceInfo *del = NULL; char *ret = NULL; del = logstorage_find_dev_info(node); if (del == NULL) { pr_verbose("%s not found in list.\n", node); print_list(); return ret; } /* Has to be freed by the caller */ ret = del->mnt_point; if (del->prev) del->prev->next = del->next; if (del->next) del->next->prev = del->prev; if (del == g_info) g_info = g_info->next; free(del->dev_node); free(del); pr_verbose("%s removed from list.\n", node); print_list(); return ret; } dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-list.h000066400000000000000000000021571446635226000243740ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka clipka@jp.adit-jv.com * \author Anitha BA ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-list.h * For further information see http://www.covesa.org/. */ #ifndef _DLT_LOGSTORAGE_LIST_H_ #define _DLT_LOGSTORAGE_LIST_H_ /* Return 0 it the node as been added (or is already present) */ int logstorage_store_dev_info(const char *node, const char *path); /* Returns the mount point if node has been found and deleted. NULL either */ char *logstorage_delete_dev_info(const char *node); #endif dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-prop.h000066400000000000000000000033231446635226000243750ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-udev.h * For further information see http://www.covesa.org/. */ #ifndef _DLT_LOGSTORAGE_PROP_H_ #define _DLT_LOGSTORAGE_PROP_H_ #ifndef HAS_PROPRIETARY_LOGSTORAGE /** @brief Initialize proprietary connection * * @return 0 */ static inline int dlt_logstorage_prop_init(void) { return 0; } /** @brief Clean-up proprietary connection * * @return 0 */ static inline int dlt_logstorage_prop_deinit(void) { return 0; } /** @brief Check whether user wants to use proprietary handler * * @return 0 */ static inline int check_proprietary_handling(char *type) { (void)type; return 0; } #else /** * Initialize proprietary connection * * @return 0 on success, -1 on error */ int dlt_logstorage_prop_init(void); /** * Clean-up proprietary connection * * @return 0 on success, -1 on error */ int dlt_logstorage_prop_deinit(void); /** * Check whether user wants to use proprietary event handler * * @return 1 if yes, 0 either. */ int check_proprietary_handling(char *); #endif /* HAS_PROPRIETARY_LOGSTORAGE */ #endif /* _DLT_LOGSTORAGE_PROP_H_ */ dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-udev.c000066400000000000000000000320401446635226000243510ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-udev.c * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-logstorage-udev.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** Frederic Berat fberat@de.adit-jv.com ** ** ** ** PURPOSE : For udev-based handling of any device ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** ** fb Frederic Berat ADIT ** *******************************************************************************/ #define pr_fmt(fmt) "Udev control: "fmt #include #include #include #include #include #include #include #include #include "dlt-control-common.h" #include "dlt-logstorage-common.h" #include "dlt-logstorage-list.h" #include "dlt-logstorage-udev.h" typedef struct { struct udev *udev; /**< Udev instance */ struct udev_monitor *mon; /**< Udev monitor instance */ } LogstorageCtrlUdev; /** @brief Get mount point of a device node * * This function search for the mount point in /proc/mounts * based on the device node. * * @param dev_node Device node as string * * @return mount path or NULL on error */ static char *dlt_logstorage_udev_get_mount_point(char *dev_node) { struct mntent *ent; FILE *f; char *mnt_point = NULL; if (dev_node == NULL) return NULL; f = setmntent("/proc/mounts", "r"); if (f == NULL) { pr_error("Cannot read /proc/mounts\n"); return NULL; } while (NULL != (ent = getmntent(f))) if (strncmp(ent->mnt_fsname, dev_node, strlen(ent->mnt_fsname)) == 0) { mnt_point = strdup(ent->mnt_dir); if (mnt_point == NULL) { pr_error("Cannot duplicate string.\n"); return NULL; } /* Remounting rw */ if (strlen(mnt_point)) /* capabilities needed. Thus we don't really car on failure. * Therefor we can ignore the return value. */ (void)mount(NULL, mnt_point, NULL, MS_REMOUNT, ent->mnt_opts); break; } endmntent(f); return mnt_point; } /** @brief Check if the daemon needs to be notified by the event * * On mount event: * If the device mount point contains the DLT configuration file, * the function will then send a message to the daemon. * On Unmounting event: * Check if the device was on the list, remove it and send the message * to the daemon. * * @param event The kind of event happening * @param part The device partition to be checked * * @return 0 on success, -1 if an error occured. */ static int check_mountpoint_from_partition(int event, struct udev_device *part) { int logstorage_dev = 0; char *mnt_point = NULL; char *dev_node = NULL; int ret = 0; if (!part) { pr_verbose("No partition structure given.\n"); return -1; } pr_verbose("Checking mount point.\n"); if (!udev_device_get_devnode(part)) { pr_verbose("Skipping as no devnode.\n"); return 0; } dev_node = strdup(udev_device_get_devnode(part)); if (dev_node == NULL) { pr_error("Cannot allocate memory for to store string\n"); return -1; } if (event == EVENT_MOUNTED) { mnt_point = dlt_logstorage_udev_get_mount_point(dev_node); logstorage_dev = dlt_logstorage_check_config_file(mnt_point); if (logstorage_dev) { /* Configuration file available, add node to internal list */ logstorage_store_dev_info(dev_node, mnt_point); } else { free(mnt_point); mnt_point = NULL; } } else { /* remove device information */ mnt_point = logstorage_delete_dev_info(dev_node); } if (mnt_point) { ret = dlt_logstorage_send_event(event, mnt_point); if (ret) pr_error("Can't send event for %s to DLT.\n", mnt_point); } free(dev_node); free(mnt_point); return 0; } /** @brief Handles the udev events * * On event, it finds the corresponding action, and calls * check_mountpoint_from_partition with the corresponding event. * * @return 0 on success, -1 on error. */ static int logstorage_udev_udevd_callback(void) { const char *action; int ret = 0; DltLogstorageCtrl *lctrl = get_logstorage_control(); LogstorageCtrlUdev *prvt = NULL; struct udev_device *partition = NULL; struct timespec ts; if (!lctrl) { pr_error("Not able to get logstorage control instance.\n"); return -1; } prvt = (LogstorageCtrlUdev *)lctrl->prvt; if ((!prvt) || (!prvt->mon)) { pr_error("Not able to get private data.\n"); return -1; } partition = udev_monitor_receive_device(prvt->mon); if (!partition) { pr_error("Not able to get partition.\n"); return -1; } action = udev_device_get_action(partition); if (!action) { pr_error("Not able to get action.\n"); udev_device_unref(partition); return -1; } pr_verbose("%s action received from udev for %s.\n", action, udev_device_get_devnode(partition)); if (strncmp(action, "add", sizeof("add")) == 0) { /*TODO: This can be replaced by polling on /proc/mount. * we could get event on modification, and keep track on a list * of mounted devices. New devices could be check that way. * That also would solve the unmount event issue. * Then, udev is only interesting to simplify the check on new devices, * and/or for hot unplug (without unmount). */ ts.tv_sec = 0; ts.tv_nsec = 500 * NANOSEC_PER_MILLISEC; nanosleep(&ts, NULL); ret = check_mountpoint_from_partition(EVENT_MOUNTED, partition); } else if (strncmp(action, "remove", sizeof("remove")) == 0) { ret = check_mountpoint_from_partition(EVENT_UNMOUNTING, partition); } udev_device_unref(partition); return ret; } /** @brief Check all partitions on the system to find configuration file * * The function looks for block devices that are of "partition" type. * Then, it gets the node, and call check_mountpoint_from_partition with it. * * @param udev The udev device used to find all the nodes * * @return 0 on success, -1 otherwise. */ static int dlt_logstorage_udev_check_mounted(struct udev *udev) { if (udev == NULL) { pr_error("%s: udev structure is NULL\n", __func__); return -1; } /* Create a list of the devices in the 'partition' subsystem. */ struct udev_enumerate *enumerate = udev_enumerate_new(udev); struct udev_list_entry *devices = NULL; struct udev_list_entry *dev_list_entry = NULL; if (!enumerate) { pr_error("Can't enumerate devices.\n"); return -1; } udev_enumerate_add_match_subsystem(enumerate, "block"); udev_enumerate_add_match_property(enumerate, "DEVTYPE", "partition"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each list entry, get the corresponding device */ udev_list_entry_foreach(dev_list_entry, devices) { const char *path; struct udev_device *partition = NULL; /* Get the filename of the /sys entry for the device * and create a udev_device object representing it */ path = udev_list_entry_get_name(dev_list_entry); partition = udev_device_new_from_syspath(udev, path); if (!partition) continue; pr_verbose("Found device %s %s %s.\n", path, udev_device_get_devnode(partition), udev_device_get_devtype(partition)); /* Check the device and clean-up */ check_mountpoint_from_partition(EVENT_MOUNTED, partition); udev_device_unref(partition); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); return 0; } /** @brief Clean-up the udev data * * That will destroy all the private data. * * @return 0 on success, -1 otherwise. */ int dlt_logstorage_udev_deinit(void) { DltLogstorageCtrl *lctrl = get_logstorage_control(); LogstorageCtrlUdev *prvt = NULL; if (!lctrl) return -1; prvt = (LogstorageCtrlUdev *)lctrl->prvt; if (prvt == NULL) return -1; if (prvt->mon) udev_monitor_unref(prvt->mon); if (prvt->udev) udev_unref(prvt->udev); free(prvt); lctrl->prvt = NULL; return 0; } /** @brief Initialize the private data * * That function will create the udev device and monitor. * * @return 0 on success, -1 otherwise. */ int dlt_logstorage_udev_init(void) { int ret = 0; DltLogstorageCtrl *lctrl = get_logstorage_control(); LogstorageCtrlUdev *prvt = NULL; pr_verbose("Initializing.\n"); if (!lctrl) { pr_error("Not able to get logstorage control instance.\n"); return -1; } lctrl->prvt = calloc(1, sizeof(LogstorageCtrlUdev)); if (!lctrl->prvt) { pr_error("No memory to allocate private data.\n"); return -1; } prvt = (LogstorageCtrlUdev *)lctrl->prvt; /* Initialize udev object */ prvt->udev = udev_new(); if (!prvt->udev) { pr_error("Cannot initialize udev object\n"); dlt_logstorage_udev_deinit(); return -1; } /* setup udev monitor which will report events when * devices attached to the system change. Events include * "add", "remove", "change", etc */ prvt->mon = udev_monitor_new_from_netlink(prvt->udev, "udev"); if (!prvt->mon) { pr_error("Cannot initialize udev monitor\n"); dlt_logstorage_udev_deinit(); return -1; } ret = udev_monitor_filter_add_match_subsystem_devtype(prvt->mon, "block", NULL); if (ret) { pr_error("Cannot attach filter to monitor: %s.\n", strerror(-ret)); dlt_logstorage_udev_deinit(); return -1; } ret = udev_monitor_enable_receiving(prvt->mon); if (ret < 0) { pr_error("Cannot start receiving: %s.\n", strerror(-ret)); dlt_logstorage_udev_deinit(); return -1; } /* get file descriptor */ lctrl->fd = udev_monitor_get_fd(prvt->mon); /* set callback function */ lctrl->callback = &logstorage_udev_udevd_callback; /* check if there is something already mounted */ return dlt_logstorage_udev_check_mounted(prvt->udev); } dlt-daemon-2.18.10/src/console/logstorage/dlt-logstorage-udev.h000066400000000000000000000020221446635226000243530ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * \author Christoph Lipka ADIT 2015 * \author Frederic Berat ADIT 2015 * * \file dlt-logstorage-udev.h * For further information see http://www.covesa.org/. */ #ifndef _DLT_LOGSTORAGE_UDEV_H_ #define _DLT_LOGSTORAGE_UDEV_H_ /** * Initialize udev connection * * @return 0 on success, -1 on error */ int dlt_logstorage_udev_init(void); /** * Clean-up udev connection * * @return 0 on success, -1 on error */ int dlt_logstorage_udev_deinit(void); #endif dlt-daemon-2.18.10/src/core_dump_handler/000077500000000000000000000000001446635226000201605ustar00rootroot00000000000000dlt-daemon-2.18.10/src/core_dump_handler/50-coredump.conf.cmake000066400000000000000000000007551446635226000241550ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### kernel.core_pattern=|@CMAKE_INSTALL_PREFIX@/bin/dlt-cdh %t %p %s %e dlt-daemon-2.18.10/src/core_dump_handler/CMakeLists.txt000066400000000000000000000030261446635226000227210ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if(WITH_DLT_COREDUMPHANDLER) set(PLATFORM_DIR ${PROJECT_SOURCE_DIR}/src/core_dump_handler/${TARGET_CPU_NAME}) set(dlt_cdh_SRCS dlt_cdh.c dlt_cdh_context.c dlt_cdh_coredump.c ${PLATFORM_DIR}/dlt_cdh_cpuinfo.c dlt_cdh_crashid.c dlt_cdh_streamer.c) set(COREDUMP_CONF_DIR "/usr/lib/sysctl.d/") #add_definitions( -fno-strict-aliasing ) if(WITH_CITYHASH) set(CITYHASH_DIR ${PROJECT_SOURCE_DIR}/src/core_dump_handler/cityhash_c) add_definitions(-DHAS_CITYHASH_C) set(dlt_cdh_SRCS ${CITYHASH_DIR}/city_c.c ${dlt_cdh_SRCS}) endif(WITH_CITYHASH) add_executable(dlt-cdh ${dlt_cdh_SRCS}) target_link_libraries(dlt-cdh ${ZLIB_LIBRARY}) set_target_properties(dlt-cdh PROPERTIES LINKER_LANGUAGE C) configure_file(${PROJECT_SOURCE_DIR}/src/core_dump_handler/50-coredump.conf.cmake ${PROJECT_BINARY_DIR}/core_dump_handler/50-coredump.conf) install(TARGETS dlt-cdh RUNTIME DESTINATION bin COMPONENT base) install(FILES ${PROJECT_BINARY_DIR}/core_dump_handler/50-coredump.conf DESTINATION ${COREDUMP_CONF_DIR}) endif(WITH_DLT_COREDUMPHANDLER) dlt-daemon-2.18.10/src/core_dump_handler/README000066400000000000000000000016101446635226000210360ustar00rootroot00000000000000To build use cmake with -DWITH_DLT_COREDUMPHANDLER=ON -DTARGET_CPU_NAME={i686|x86_64} Temporary replacement of default crash handler: If you don't want to make the change persistent just become root (not sudo) and execute the following ("man core" for details): echo "|/usr/local/bin/dlt-cdh %t %p %s %e" > /proc/sys/kernel/core_pattern (replace /usr/local/bin with the path dlt-cdh has been installed to) Persistent replacement of default crash handler: We have to generate "50-coredump.conf" in "/usr/lib/sysctl.d/" which is done automatically by "make install". Unfortunately at least on Fedora systems we also have to remove abrt with "yum remove abrtd*" because this ruthlessly overwrites our change at every boot. This must be done when installing this stuff as Debian package. To enable the core dump handler without rebooting we have to execute "sysctl -p /usr/lib/sysctl.d/50-coredump.conf" dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/000077500000000000000000000000001446635226000222765ustar00rootroot00000000000000dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/COPYING000066400000000000000000000021251446635226000233310ustar00rootroot00000000000000// Copyright (c) 2011 Google, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE.dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/README000066400000000000000000000165401446635226000231640ustar00rootroot00000000000000CityHash, a family of hash functions for strings. Introduction ============ CityHash provides hash functions for strings. The functions mix the input bits thoroughly but are not suitable for cryptography. See "Hash Quality," below, for details on how CityHash was tested and so on. We provide reference implementations in C++, with a friendly MIT license. CityHash32() returns a 32-bit hash. CityHash64() and similar return a 64-bit hash. CityHash128() and similar return a 128-bit hash and are tuned for strings of at least a few hundred bytes. Depending on your compiler and hardware, it's likely faster than CityHash64() on sufficiently long strings. It's slower than necessary on shorter strings, but we expect that case to be relatively unimportant. CityHashCrc128() and similar are variants of CityHash128() that depend on _mm_crc32_u64(), an intrinsic that compiles to a CRC32 instruction on some CPUs. However, none of the functions we provide are CRCs. CityHashCrc256() is a variant of CityHashCrc128() that also depends on _mm_crc32_u64(). It returns a 256-bit hash. All members of the CityHash family were designed with heavy reliance on previous work by Austin Appleby, Bob Jenkins, and others. For example, CityHash32 has many similarities with Murmur3a. Performance on long strings: 64-bit CPUs ======================================== We are most excited by the performance of CityHash64() and its variants on short strings, but long strings are interesting as well. CityHash is intended to be fast, under the constraint that it hash very well. For CPUs with the CRC32 instruction, CRC is speedy, but CRC wasn't designed as a hash function and shouldn't be used as one. CityHashCrc128() is not a CRC, but it uses the CRC32 machinery. On a single core of a 2.67GHz Intel Xeon X5550, CityHashCrc256 peaks at about 5 to 5.5 bytes/cycle. The other CityHashCrc functions are wrappers around CityHashCrc256 and should have similar performance on long strings. (CityHashCrc256 in v1.0.3 was even faster, but we decided it wasn't as thorough as it should be.) CityHash128 peaks at about 4.3 bytes/cycle. The fastest Murmur variant on that hardware, Murmur3F, peaks at about 2.4 bytes/cycle. We expect the peak speed of CityHash128 to dominate CityHash64, which is aimed more toward short strings or use in hash tables. For long strings, a new function by Bob Jenkins, SpookyHash, is just slightly slower than CityHash128 on Intel x86-64 CPUs, but noticeably faster on AMD x86-64 CPUs. For hashing long strings on AMD CPUs and/or CPUs without the CRC instruction, SpookyHash may be just as good or better than any of the CityHash variants. Performance on short strings: 64-bit CPUs ========================================= For short strings, e.g., most hash table keys, CityHash64 is faster than CityHash128, and probably faster than all the aforementioned functions, depending on the mix of string lengths. Here are a few results from that same hardware, where we (unrealistically) tested a single string length over and over again: Hash Results ------------------------------------------------------------------------------ CityHash64 v1.0.3 7ns for 1 byte, or 6ns for 8 bytes, or 9ns for 64 bytes Murmur2 (64-bit) 6ns for 1 byte, or 6ns for 8 bytes, or 15ns for 64 bytes Murmur3F 14ns for 1 byte, or 15ns for 8 bytes, or 23ns for 64 bytes We don't have CityHash64 benchmarks results for v1.1, but we expect the numbers to be similar. Performance: 32-bit CPUs ======================== CityHash32 is the newest variant of CityHash. It is intended for 32-bit hardware in general but has been mostly tested on x86. Our benchmarks suggest that Murmur3 is the nearest competitor to CityHash32 on x86. We don't know of anything faster that has comparable quality. The speed rankings in our testing: CityHash32 > Murmur3f > Murmur3a (for long strings), and CityHash32 > Murmur3a > Murmur3f (for short strings). Installation ============ We provide reference implementations of several CityHash functions, written in C++. The build system is based on autoconf. It defaults the C++ compiler flags to "-g -O2", which is probably slower than -O3 if you are using gcc. YMMV. On systems with gcc, we generally recommend: ./configure make all check CXXFLAGS="-g -O3" sudo make install Or, if your system has the CRC32 instruction, and you want to build everything: ./configure --enable-sse4.2 make all check CXXFLAGS="-g -O3 -msse4.2" sudo make install Note that our build system doesn't try to determine the appropriate compiler flag for enabling SSE4.2. For gcc it is "-msse4.2". The --enable-sse4.2 flag to the configure script controls whether citycrc.h is installed when you "make install." In general, picking the right compiler flags can be tricky, and may depend on your compiler, your hardware, and even how you plan to use the library. For generic information about how to configure this software, please try: ./configure --help Failing that, please work from city.cc and city*.h, as they contain all the necessary code. Usage ===== The above installation instructions will produce a single library. It will contain CityHash32(), CityHash64(), and CityHash128(), and their variants, and possibly CityHashCrc128(), CityHashCrc128WithSeed(), and CityHashCrc256(). The functions with Crc in the name are declared in citycrc.h; the rest are declared in city.h. Limitations =========== 1) CityHash32 is intended for little-endian 32-bit code, and everything else in the current version of CityHash is intended for little-endian 64-bit CPUs. All functions that don't use the CRC32 instruction should work in little-endian 32-bit or 64-bit code. CityHash should work on big-endian CPUs as well, but we haven't tested that very thoroughly yet. 2) CityHash is fairly complex. As a result of its complexity, it may not perform as expected on some compilers. For example, preliminary reports suggest that some Microsoft compilers compile CityHash to assembly that's 10-20% slower than it could be. Hash Quality ============ We like to test hash functions with SMHasher, among other things. SMHasher isn't perfect, but it seems to find almost any significant flaw. SMHasher is available at http://code.google.com/p/smhasher/ SMHasher is designed to pass a 32-bit seed to the hash functions it tests. No CityHash function is designed to work that way, so we adapt as follows: For our functions that accept a seed, we use the given seed directly (padded with zeroes); for our functions that don't accept a seed, we hash the concatenation of the given seed and the input string. The CityHash functions have the following flaws according to SMHasher: (1) CityHash64: none (2) CityHash64WithSeed: none (3) CityHash64WithSeeds: did not test (4) CityHash128: none (5) CityHash128WithSeed: none (6) CityHashCrc128: none (7) CityHashCrc128WithSeed: none (8) CityHashCrc256: none (9) CityHash32: none Some minor flaws in 32-bit and 64-bit functions are harmless, as we expect the primary use of these functions will be in hash tables. We may have gone slightly overboard in trying to please SMHasher and other similar tests, but we don't want anyone to choose a different hash function because of some minor issue reported by a quality test. For more information ==================== http://code.google.com/p/cityhash/ cityhash-discuss@googlegroups.com Please feel free to send us comments, questions, bug reports, or patches.dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/city-test.cc000066400000000000000000003053041446635226000245370ustar00rootroot00000000000000// Copyright (c) 2011 Google, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include #include #include #include "city_c.h" #ifdef __SSE4_2__ #include "citycrc_c.h" #endif using std::cout; using std::cerr; using std::hex; static const uint64 k0 = 0xc3a5c85c97cb3127ULL; static const uint64 kSeed0 = 1234567; static const uint64 kSeed1 = k0; static const uint128 kSeed128 = {kSeed0, kSeed1}; static const int kDataSize = 1 << 20; static const int kTestSize = 300; static char data[kDataSize]; static int errors = 0; // global error count // Initialize data to pseudorandom values. void setup() { uint64 a = 9; uint64 b = 777; for (int i = 0; i < kDataSize; i++) { a = (a ^ (a >> 41)) * k0 + b; b = (b ^ (b >> 41)) * k0 + i; uint8 u = (uint8)(b >> 37); memcpy(data + i, &u, 1); // uint8 -> char } } #if 1 #define C(y) 0x ## y ## ULL static const uint64 testdata[kTestSize][15] = { {C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766), C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663), C(5b7bc50fd8e8ad92), C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663), C(5b7bc50fd8e8ad92), C(889f555a0f5b2dc0), C(7767800902c8a8ce), C(bcd2a808f4cb4a44), C(e9024dba8f94f2f3)}, {C(75e9dee28ded761d), C(931992c1b14334c5), C(245eeb25ba2c172e), C(1290f0e8a5caa74d), C(ca4c6bf7583f5cda), C(e1d60d51632c536d), C(cbc54a1db641910a), C(1290f0e8a5caa74d), C(ca4c6bf7583f5cda), C(e1d60d51632c536d), C(cbc54a1db641910a), C(9866d68d17c2c08e), C(8d84ba63eb4d020a), C(df0ad99c78cbce44), C(7c98593ef62573ed)}, {C(75de892fdc5ba914), C(f89832e71f764c86), C(39a82df1f278a297), C(b4af8ae673acb930), C(992b7acb203d8885), C(57b533f3f8b94d50), C(bbb69298a5dcf1a1), C(b4af8ae673acb930), C(992b7acb203d8885), C(57b533f3f8b94d50), C(bbb69298a5dcf1a1), C(433495196af9ac4f), C(53445c0896ae1fe6), C(f7b939315f6fb56f), C(ac1b05e5a2e0335e)}, {C(69cfe9fca1cc683a), C(e65f2a81e19b8067), C(20575ea6370a9d14), C(8f52532fc6f005b7), C(4ebe60df371ec129), C(c6ef8a7f8deb8116), C(83df17e3c9bb9a67), C(8f52532fc6f005b7), C(4ebe60df371ec129), C(c6ef8a7f8deb8116), C(83df17e3c9bb9a67), C(6a0aaf51016e19cd), C(fb0d1e89f39dbf6a), C(c73095102872943a), C(405ea97456c28a75)}, {C(675b04c582a34966), C(53624b5ef8cd4f45), C(c412e0931ac8c9b1), C(798637e677c65a3), C(83e3b06adc4cd3ff), C(f3e76e8a7135852f), C(111e66cfbb05366d), C(798637e677c65a3), C(83e3b06adc4cd3ff), C(f3e76e8a7135852f), C(111e66cfbb05366d), C(29c4f84aa48e8682), C(b77a8685750c94d0), C(7cab65571969123f), C(fb1dbd79f68a8519)}, {C(46fa817397ea8b68), C(cc960c1c15ce2d20), C(e5f9f947bafb9e79), C(b342cdf0d7ac4b2a), C(66914d44b373b232), C(261194e76cb43966), C(45a0010190365048), C(b342cdf0d7ac4b2a), C(66914d44b373b232), C(261194e76cb43966), C(45a0010190365048), C(e2586947ca8eac83), C(6650daf2d9677cdc), C(2f9533d8f4951a9), C(a5bdc0f3edc4bd7b)}, {C(406e959cdffadec7), C(e80dc125dca28ed1), C(e5beb146d4b79a21), C(e66d5c1bb441541a), C(d14961bc1fd265a2), C(e4cc669d4fc0577f), C(abf4a51e36da2702), C(e66d5c1bb441541a), C(d14961bc1fd265a2), C(e4cc669d4fc0577f), C(abf4a51e36da2702), C(21236d12df338f75), C(54b8c4a5ad2ae4a4), C(202d50ef9c2d4465), C(5ecc6a128e51a797)}, {C(46663908b4169b95), C(4e7e90b5c426bf1d), C(dc660b58daaf8b2c), C(b298265ebd1bd55f), C(4a5f6838b55c0b08), C(fc003c97aa05d397), C(2fb5adad3380c3bc), C(b298265ebd1bd55f), C(4a5f6838b55c0b08), C(fc003c97aa05d397), C(2fb5adad3380c3bc), C(c46fd01d253b4a0b), C(4c799235c2a33188), C(7e21bc57487a11bf), C(e1392bb1994bd4f2)}, {C(f214b86cffeab596), C(5fccb0b132da564f), C(86e7aa8b4154b883), C(763529c8d4189ea8), C(860d77e7fef74ca3), C(3b1ba41191219b6b), C(722b25dfa6d0a04b), C(763529c8d4189ea8), C(860d77e7fef74ca3), C(3b1ba41191219b6b), C(722b25dfa6d0a04b), C(5f7b463094e22a91), C(75d6f57376b31bd7), C(d253c7f89efec8e6), C(efe56ac880a2b8a3)}, {C(eba670441d1a4f7d), C(eb6b272502d975fa), C(69f8d424d50c083e), C(313d49cb51b8cd2c), C(6e982d8b4658654a), C(dd59629a17e5492d), C(81cb23bdab95e30e), C(313d49cb51b8cd2c), C(6e982d8b4658654a), C(dd59629a17e5492d), C(81cb23bdab95e30e), C(1e6c3e6c454c774f), C(177655172666d5ea), C(9cc67e0d38d80886), C(36a2d64d7bc58d22)}, {C(172c17ff21dbf88d), C(1f5104e320f0c815), C(1e34e9f1fa63bcef), C(3506ae8fae368d2a), C(59fa2b2de5306203), C(67d1119dcfa6007e), C(1f7190c648ad9aef), C(3506ae8fae368d2a), C(59fa2b2de5306203), C(67d1119dcfa6007e), C(1f7190c648ad9aef), C(7e8b1e689137b637), C(cbe373368a31db3c), C(dbc79d82cd49c671), C(641399520c452c99)}, {C(5a0838df8a019b8c), C(73fc859b4952923), C(45e39daf153491bd), C(a9b91459a5fada46), C(de0fbf8800a2da3), C(21800e4b5af9dedb), C(517c3726ae0dbae7), C(a9b91459a5fada46), C(de0fbf8800a2da3), C(21800e4b5af9dedb), C(517c3726ae0dbae7), C(1ccffbd74acf9d66), C(cbb08cf95e7eda99), C(61444f09e2a29587), C(35c0d15745f96455)}, {C(8f42b1fbb2fc0302), C(5ae31626076ab6ca), C(b87f0cb67cb75d28), C(2498586ac2e1fab2), C(e683f9cbea22809a), C(a9728d0b2bbe377c), C(46baf5cae53dc39a), C(2498586ac2e1fab2), C(e683f9cbea22809a), C(a9728d0b2bbe377c), C(46baf5cae53dc39a), C(806f4352c99229e), C(d4643728fc71754a), C(998c1647976bc893), C(d8094fdc2d6bb032)}, {C(72085e82d70dcea9), C(32f502c43349ba16), C(5ebc98c3645a018f), C(c7fa762238fd90ac), C(8d03b5652d615677), C(a3f5226e51d42217), C(46d5010a7cae8c1e), C(c7fa762238fd90ac), C(8d03b5652d615677), C(a3f5226e51d42217), C(46d5010a7cae8c1e), C(4293122580db7f5f), C(3df6042f39c6d487), C(439124809cf5c90e), C(90b704e4f71d0ccf)}, {C(32b75fc2223b5032), C(246fff80eb230868), C(a6fdbc82c9aeecc0), C(c089498074167021), C(ab094a9f9ab81c23), C(4facf3d9466bcb03), C(57aa9c67938cf3eb), C(c089498074167021), C(ab094a9f9ab81c23), C(4facf3d9466bcb03), C(57aa9c67938cf3eb), C(79a769ca1c762117), C(9c8dee60337f87a8), C(dabf1b96535a3abb), C(f87e9fbb590ba446)}, {C(e1dd010487d2d647), C(12352858295d2167), C(acc5e9b6f6b02dbb), C(1c66ceea473413df), C(dc3f70a124b25a40), C(66a6dfe54c441cd8), C(b436dabdaaa37121), C(1c66ceea473413df), C(dc3f70a124b25a40), C(66a6dfe54c441cd8), C(b436dabdaaa37121), C(6d95aa6890f51674), C(42c6c0fc7ab3c107), C(83b9dfe082e76140), C(939cdbd3614d6416)}, {C(2994f9245194a7e2), C(b7cd7249d6db6c0c), C(2170a7d119c5c6c3), C(8505c996b70ee9fc), C(b92bba6b5d778eb7), C(4db4c57f3a7a4aee), C(3cfd441cb222d06f), C(8505c996b70ee9fc), C(b92bba6b5d778eb7), C(4db4c57f3a7a4aee), C(3cfd441cb222d06f), C(4d940313c96ac6bd), C(43762837c9ffac4b), C(480fcf58920722e3), C(4bbd1e1a1d06752f)}, {C(32e2ed6fa03e5b22), C(58baf09d7c71c62b), C(a9c599f3f8f50b5b), C(1660a2c4972d0fa1), C(1a1538d6b50a57c), C(8a5362485bbc9363), C(e8eec3c84fd9f2f8), C(1660a2c4972d0fa1), C(1a1538d6b50a57c), C(8a5362485bbc9363), C(e8eec3c84fd9f2f8), C(2562514461d373da), C(33857675fed52b4), C(e58d2a17057f1943), C(fe7d3f30820e4925)}, {C(37a72b6e89410c9f), C(139fec53b78cee23), C(4fccd8f0da7575c3), C(3a5f04166518ac75), C(f49afe05a44fc090), C(cb01b4713cfda4bd), C(9027bd37ffc0a5de), C(3a5f04166518ac75), C(f49afe05a44fc090), C(cb01b4713cfda4bd), C(9027bd37ffc0a5de), C(e15144d3ad46ec1b), C(736fd99679a5ae78), C(b3d7ed9ed0ddfe57), C(cef60639457867d7)}, {C(10836563cb8ff3a1), C(d36f67e2dfc085f7), C(edc1bb6a3dcba8df), C(bd4f3a0566df3bed), C(81fc8230c163dcbe), C(4168bc8417a8281b), C(7100c9459827c6a6), C(bd4f3a0566df3bed), C(81fc8230c163dcbe), C(4168bc8417a8281b), C(7100c9459827c6a6), C(21cad59eaf79e72f), C(61c8af6fb71469f3), C(b0dfc42ce4f578b), C(33ea34ccea305d4e)}, {C(4dabcb5c1d382e5c), C(9a868c608088b7a4), C(7b2b6c389b943be5), C(c914b925ab69fda0), C(6bafe864647c94d7), C(7a48682dd4afa22), C(40fe01210176ba10), C(c914b925ab69fda0), C(6bafe864647c94d7), C(7a48682dd4afa22), C(40fe01210176ba10), C(88dd28f33ec31388), C(c6db60abf1d45381), C(7b94c447298824d5), C(6b2a5e05ad0b9fc0)}, {C(296afb509046d945), C(c38fe9eb796bd4be), C(d7b17535df110279), C(dd2482b87d1ade07), C(662785d2e3e78ddf), C(eae39994375181bb), C(9994500c077ee1db), C(dd2482b87d1ade07), C(662785d2e3e78ddf), C(eae39994375181bb), C(9994500c077ee1db), C(a275489f8c6bb289), C(30695ea31df1a369), C(1aeeb31802d701b5), C(7799d5a6d5632838)}, {C(f7c0257efde772ea), C(af6af9977ecf7bff), C(1cdff4bd07e8d973), C(fab1f4acd2cd4ab4), C(b4e19ba52b566bd), C(7f1db45725fe2881), C(70276ff8763f8396), C(fab1f4acd2cd4ab4), C(b4e19ba52b566bd), C(7f1db45725fe2881), C(70276ff8763f8396), C(1b0f2b546dddd16b), C(aa066984b5fd5144), C(7c3f9386c596a5a8), C(e5befdb24b665d5f)}, {C(61e021c8da344ba1), C(cf9c720676244755), C(354ffa8e9d3601f6), C(44e40a03093fbd92), C(bda9481cc5b93cae), C(986b589cbc0cf617), C(210f59f074044831), C(44e40a03093fbd92), C(bda9481cc5b93cae), C(986b589cbc0cf617), C(210f59f074044831), C(ac32cbbb6f50245a), C(afa6f712efb22075), C(47289f7af581719f), C(31b6e75d3aa0e54b)}, {C(c0a86ed83908560b), C(440c8b6f97bd1749), C(a99bf2891726ea93), C(ac0c0b84df66df9d), C(3ee2337b437eb264), C(8a341daed9a25f98), C(cc665499aa38c78c), C(ac0c0b84df66df9d), C(3ee2337b437eb264), C(8a341daed9a25f98), C(cc665499aa38c78c), C(af7275299d79a727), C(874fa8434b45d0e), C(ca7b67388950dd33), C(2db5cd3675ec58f7)}, {C(35c9cf87e4accbf3), C(2267eb4d2191b2a3), C(80217695666b2c9), C(cd43a24abbaae6d), C(a88abf0ea1b2a8ff), C(e297ff01427e2a9d), C(935d545695b2b41d), C(cd43a24abbaae6d), C(a88abf0ea1b2a8ff), C(e297ff01427e2a9d), C(935d545695b2b41d), C(6accd4dbcb52e849), C(261295acb662fd49), C(f9d91f1ac269a8a2), C(5e45f39df355e395)}, {C(e74c366b3091e275), C(522e657c5da94b06), C(ca9afa806f1a54ac), C(b545042f67929471), C(90d10e75ed0e75d8), C(3ea60f8f158df77e), C(8863eff3c2d670b7), C(b545042f67929471), C(90d10e75ed0e75d8), C(3ea60f8f158df77e), C(8863eff3c2d670b7), C(5799296e97f144a7), C(1d6e517c12a88271), C(da579e9e1add90ef), C(942fb4cdbc3a4da)}, {C(a3f2ca45089ad1a6), C(13f6270fe56fbce4), C(1f93a534bf03e705), C(aaea14288ae2d90c), C(1be3cd51ef0f15e8), C(e8b47c84d5a4aac1), C(297d27d55b766782), C(aaea14288ae2d90c), C(1be3cd51ef0f15e8), C(e8b47c84d5a4aac1), C(297d27d55b766782), C(e922d1d8bb2afd0), C(b4481c4fa2e7d8d5), C(691e21538af794d5), C(9bd4fb0a53962a72)}, {C(e5181466d8e60e26), C(cf31f3a2d582c4f3), C(d9cee87cb71f75b2), C(4750ca6050a2d726), C(d6e6dd8940256849), C(f3b3749fdab75b0), C(c55d8a0f85ba0ccf), C(4750ca6050a2d726), C(d6e6dd8940256849), C(f3b3749fdab75b0), C(c55d8a0f85ba0ccf), C(47f134f9544c6da6), C(e1cdd9cb74ad764), C(3ce2d096d844941e), C(321fe62f608d2d4e)}, {C(fb528a8dd1e48ad7), C(98c4fd149c8a63dd), C(4abd8fc3377ae1f), C(d7a9304abbb47cc5), C(7f2b9a27aa57f99), C(353ab332d4ef9f18), C(47d56b8d6c8cf578), C(d7a9304abbb47cc5), C(7f2b9a27aa57f99), C(353ab332d4ef9f18), C(47d56b8d6c8cf578), C(df55f58ae09f311f), C(dba9511784fa86e3), C(c43ce0288858a47e), C(62971e94270b78e1)}, {C(da6d2b7ea9d5f9b6), C(57b11153ee3b4cc8), C(7d3bd1256037142f), C(90b16ff331b719b5), C(fc294e7ad39e01e6), C(d2145386bab41623), C(7045a63d44d76011), C(90b16ff331b719b5), C(fc294e7ad39e01e6), C(d2145386bab41623), C(7045a63d44d76011), C(a232222ed0fe2fa4), C(e6c17dff6c323a8a), C(bbcb079be123ac6c), C(4121fe2c5de7d850)}, {C(61d95225bc2293e), C(f6c52cb6be9889a8), C(91a0667a7ed6a113), C(441133d221486a3d), C(fb9c5a40e19515b), C(6c967b6c69367c2d), C(145bd9ef258c4099), C(441133d221486a3d), C(fb9c5a40e19515b), C(6c967b6c69367c2d), C(145bd9ef258c4099), C(a0197657160c686e), C(91ada0871c23f379), C(2fd74fceccb5c80c), C(bf04f24e2dc17913)}, {C(81247c01ab6a9cc1), C(fbccea953e810636), C(ae18965000c31be0), C(15bb46383daec2a5), C(716294063b4ba089), C(f3bd691ce02c3014), C(14ccaad685a20764), C(15bb46383daec2a5), C(716294063b4ba089), C(f3bd691ce02c3014), C(14ccaad685a20764), C(5db25914279d6f24), C(25c451fce3b2ed06), C(e6bacb43ba1ddb9a), C(6d77493a2e6fd76)}, {C(c17f3ebd3257cb8b), C(e9e68c939c118c8d), C(72a5572be35bfc1b), C(f6916c341cb31f2a), C(591da1353ee5f31c), C(f1313c98a836b407), C(e0b8473eada48cd1), C(f6916c341cb31f2a), C(591da1353ee5f31c), C(f1313c98a836b407), C(e0b8473eada48cd1), C(ac5c2fb40b09ba46), C(3a3e8a9344eb6548), C(3bf9349a9d8483a6), C(c30dd0d9b15e92d0)}, {C(9802438969c3043b), C(6cd07575c948dd82), C(83e26b6830ea8640), C(d52f1fa190576961), C(11d182e4f0d419cc), C(5d9ccf1b56617424), C(c8a16debb585e452), C(d52f1fa190576961), C(11d182e4f0d419cc), C(5d9ccf1b56617424), C(c8a16debb585e452), C(2158a752d2686d40), C(b93c1fdf54789e8c), C(3a9a435627b2a30b), C(de6e5e551e7e5ad5)}, {C(3dd8ed248a03d754), C(d8c1fcf001cb62e0), C(87a822141ed64927), C(4bfaf6fd26271f47), C(aefeae8222ad3c77), C(cfb7b24351a60585), C(8678904e9e890b8f), C(4bfaf6fd26271f47), C(aefeae8222ad3c77), C(cfb7b24351a60585), C(8678904e9e890b8f), C(968dd1aa4d7dcf31), C(7ac643b015007a39), C(d1e1bac3d94406ec), C(babfa52474a404fa)}, {C(c5bf48d7d3e9a5a3), C(8f0249b5c5996341), C(c6d2c8a606f45125), C(fd1779db740e2c48), C(1950ef50fefab3f8), C(e4536426a6196809), C(699556c502a01a6a), C(fd1779db740e2c48), C(1950ef50fefab3f8), C(e4536426a6196809), C(699556c502a01a6a), C(2f49d268bb57b946), C(b205baa6c66ebfa5), C(ab91ebe4f48b0da1), C(c7e0718ccc360328)}, {C(bc4a21d00cf52288), C(28df3eb5a533fa87), C(6081bbc2a18dd0d), C(8eed355d219e58b9), C(2d7b9f1a3d645165), C(5758d1aa8d85f7b2), C(9c90c65920041dff), C(8eed355d219e58b9), C(2d7b9f1a3d645165), C(5758d1aa8d85f7b2), C(9c90c65920041dff), C(3c5c4ea46645c7f1), C(346879ecc0e2eb90), C(8434fec461bb5a0f), C(783ccede50ef5ce9)}, {C(172c8674913ff413), C(1815a22400e832bf), C(7e011f9467a06650), C(161be43353a31dd0), C(79a8afddb0642ac3), C(df43af54e3e16709), C(6e12553a75b43f07), C(161be43353a31dd0), C(79a8afddb0642ac3), C(df43af54e3e16709), C(6e12553a75b43f07), C(3ac1b1121e87d023), C(2d47d33df7b9b027), C(e2d3f71f4e817ff5), C(70b3a11ca85f8a39)}, {C(17a361dbdaaa7294), C(c67d368223a3b83c), C(f49cf8d51ab583d2), C(666eb21e2eaa596), C(778f3e1b6650d56), C(3f6be451a668fe2d), C(5452892b0b101388), C(666eb21e2eaa596), C(778f3e1b6650d56), C(3f6be451a668fe2d), C(5452892b0b101388), C(cc867fceaeabdb95), C(f238913c18aaa101), C(f5236b44f324cea1), C(c507cc892ff83dd1)}, {C(5cc268bac4bd55f), C(232717a35d5b2f1), C(38da1393365c961d), C(2d187f89c16f7b62), C(4eb504204fa1be8), C(222bd53d2efe5fa), C(a4dcd6d721ddb187), C(2d187f89c16f7b62), C(4eb504204fa1be8), C(222bd53d2efe5fa), C(a4dcd6d721ddb187), C(d86bbe67666eca70), C(c8bbae99d8e6429f), C(41dac4ceb2cb6b10), C(2f90c331755f6c48)}, {C(db04969cc06547f1), C(fcacc8a75332f120), C(967ccec4ed0c977e), C(ac5d1087e454b6cd), C(c1f8b2e284d28f6c), C(cc3994f4a9312cfa), C(8d61606dbc4e060d), C(ac5d1087e454b6cd), C(c1f8b2e284d28f6c), C(cc3994f4a9312cfa), C(8d61606dbc4e060d), C(17315af3202a1307), C(850775145e01163a), C(96f10e7357f930d2), C(abf27049cf07129)}, {C(25bd8d3ca1b375b2), C(4ad34c2c865816f9), C(9be30ad32f8f28aa), C(7755ea02dbccad6a), C(cb8aaf8886247a4a), C(8f6966ce7ea1b6e6), C(3f2863090fa45a70), C(7755ea02dbccad6a), C(cb8aaf8886247a4a), C(8f6966ce7ea1b6e6), C(3f2863090fa45a70), C(1e46d73019c9fb06), C(af37f39351616f2c), C(657efdfff20ea2ed), C(93bdf4c58ada3ecb)}, {C(166c11fbcbc89fd8), C(cce1af56c48a48aa), C(78908959b8ede084), C(19032925ba2c951a), C(a53ed6e81b67943a), C(edc871a9e8ef4bdf), C(ae66cf46a8371aba), C(19032925ba2c951a), C(a53ed6e81b67943a), C(edc871a9e8ef4bdf), C(ae66cf46a8371aba), C(a37b97790fe75861), C(eda28c8622708b98), C(3f0a23509d3d5c9d), C(5787b0e7976c97cf)}, {C(3565bcc4ca4ce807), C(ec35bfbe575819d5), C(6a1f690d886e0270), C(1ab8c584625f6a04), C(ccfcdafb81b572c4), C(53b04ba39fef5af9), C(64ce81828eefeed4), C(1ab8c584625f6a04), C(ccfcdafb81b572c4), C(53b04ba39fef5af9), C(64ce81828eefeed4), C(131af99997fc662c), C(8d9081192fae833c), C(2828064791cb2eb), C(80554d2e8294065c)}, {C(b7897fd2f274307d), C(6d43a9e5dd95616d), C(31a2218e64d8fce0), C(664e581fc1cf769b), C(415110942fc97022), C(7a5d38fee0bfa763), C(dc87ddb4d7495b6c), C(664e581fc1cf769b), C(415110942fc97022), C(7a5d38fee0bfa763), C(dc87ddb4d7495b6c), C(7c3b66372e82e64b), C(1c89c0ceeeb2dd1), C(dad76d2266214dbd), C(744783486e43cc61)}, {C(aba98113ab0e4a16), C(287f883aede0274d), C(3ecd2a607193ba3b), C(e131f6cc9e885c28), C(b399f98d827e4958), C(6eb90c8ed6c9090c), C(ec89b378612a2b86), C(e131f6cc9e885c28), C(b399f98d827e4958), C(6eb90c8ed6c9090c), C(ec89b378612a2b86), C(cfc0e126e2f860c0), C(a9a8ab5dec95b1c), C(d06747f372f7c733), C(fbd643f943a026d3)}, {C(17f7796e0d4b636c), C(ddba5551d716137b), C(65f9735375df1ada), C(a39e946d02e14ec2), C(1c88cc1d3822a193), C(663f8074a5172bb4), C(8ad2934942e4cb9c), C(a39e946d02e14ec2), C(1c88cc1d3822a193), C(663f8074a5172bb4), C(8ad2934942e4cb9c), C(3da03b033a95f16c), C(54a52f1932a1749d), C(779eeb734199bc25), C(359ce8c8faccc57b)}, {C(33c0128e62122440), C(b23a588c8c37ec2b), C(f2608199ca14c26a), C(acab0139dc4f36df), C(9502b1605ca1345a), C(32174ef1e06a5e9c), C(d824b7869258192b), C(acab0139dc4f36df), C(9502b1605ca1345a), C(32174ef1e06a5e9c), C(d824b7869258192b), C(681d021b52064762), C(30b6c735f80ac371), C(6a12d8d7f78896b3), C(157111657a972144)}, {C(988bc5d290b97aef), C(6754bb647eb47666), C(44b5cf8b5b8106a8), C(a1c5ba961937f723), C(32d6bc7214dfcb9b), C(6863397e0f4c6758), C(e644bcb87e3eef70), C(a1c5ba961937f723), C(32d6bc7214dfcb9b), C(6863397e0f4c6758), C(e644bcb87e3eef70), C(bf25ae22e7aa7c97), C(f5f3177da5756312), C(56a469cb0dbb58cd), C(5233184bb6130470)}, {C(23c8c25c2ab72381), C(d6bc672da4175fba), C(6aef5e6eb4a4eb10), C(3df880c945e68aed), C(5e08a75e956d456f), C(f984f088d1a322d7), C(7d44a1b597b7a05e), C(3df880c945e68aed), C(5e08a75e956d456f), C(f984f088d1a322d7), C(7d44a1b597b7a05e), C(cbd7d157b7fcb020), C(2e2945e90749c2aa), C(a86a13c934d8b1bb), C(fbe3284bb4eab95f)}, {C(450fe4acc4ad3749), C(3111b29565e4f852), C(db570fc2abaf13a9), C(35107d593ba38b22), C(fd8212a125073d88), C(72805d6e015bfacf), C(6b22ae1a29c4b853), C(35107d593ba38b22), C(fd8212a125073d88), C(72805d6e015bfacf), C(6b22ae1a29c4b853), C(df2401f5c3c1b633), C(c72307e054c81c8f), C(3efbfe65bd2922c0), C(b4f632e240b3190c)}, {C(48e1eff032d90c50), C(dee0fe333d962b62), C(c845776990c96775), C(8ea71758346b71c9), C(d84258cab79431fd), C(af566b4975cce10a), C(5c5c7e70a91221d2), C(8ea71758346b71c9), C(d84258cab79431fd), C(af566b4975cce10a), C(5c5c7e70a91221d2), C(c33202c7be49ea6f), C(e8ade53b6cbf4caf), C(102ea04fc82ce320), C(c1f7226614715e5e)}, {C(c048604ba8b6c753), C(21ea6d24b417fdb6), C(4e40a127ad2d6834), C(5234231bf173c51), C(62319525583eaf29), C(87632efa9144cc04), C(1749de70c8189067), C(5234231bf173c51), C(62319525583eaf29), C(87632efa9144cc04), C(1749de70c8189067), C(29672240923e8207), C(11dd247a815f6d0d), C(8d64e16922487ed0), C(9fa6f45d50d83627)}, {C(67ff1cbe469ebf84), C(3a828ac9e5040eb0), C(85bf1ad6b363a14b), C(2fc6c0783390d035), C(ef78307f5be5524e), C(a46925b7a1a77905), C(fea37470f9a51514), C(2fc6c0783390d035), C(ef78307f5be5524e), C(a46925b7a1a77905), C(fea37470f9a51514), C(9d6504cf6d3947ce), C(174cc006b8e96e7), C(d653a06d8a009836), C(7d22b5399326a76c)}, {C(b45c7536bd7a5416), C(e2d17c16c4300d3c), C(b70b641138765ff5), C(a5a859ab7d0ddcfc), C(8730164a0b671151), C(af93810c10348dd0), C(7256010c74f5d573), C(a5a859ab7d0ddcfc), C(8730164a0b671151), C(af93810c10348dd0), C(7256010c74f5d573), C(e22a335be6cd49f3), C(3bc9c8b40c9c397a), C(18da5c08e28d3fb5), C(f58ea5a00404a5c9)}, {C(215c2eaacdb48f6f), C(33b09acf1bfa2880), C(78c4e94ba9f28bf), C(981b7219224443d1), C(1f476fc4344d7bba), C(abad36e07283d3a5), C(831bf61190eaaead), C(981b7219224443d1), C(1f476fc4344d7bba), C(abad36e07283d3a5), C(831bf61190eaaead), C(4c90729f62432254), C(2ffadc94c89f47b3), C(677e790b43d20e9a), C(bb0a1686e7c3ae5f)}, {C(241baf16d80e0fe8), C(b6b3c5b53a3ce1d), C(6ae6b36209eecd70), C(a560b6a4aa3743a4), C(b3e04f202b7a99b), C(3b3b1573f4c97d9f), C(ccad8715a65af186), C(a560b6a4aa3743a4), C(b3e04f202b7a99b), C(3b3b1573f4c97d9f), C(ccad8715a65af186), C(d0c93a838b0c37e7), C(7150aa1be7eb1aad), C(755b1e60b84d8d), C(51916e77b1b05ba9)}, {C(d10a9743b5b1c4d1), C(f16e0e147ff9ccd6), C(fbd20a91b6085ed3), C(43d309eb00b771d5), C(a6d1f26105c0f61b), C(d37ad62406e5c37e), C(75d9b28c717c8cf7), C(43d309eb00b771d5), C(a6d1f26105c0f61b), C(d37ad62406e5c37e), C(75d9b28c717c8cf7), C(8f5f118b425b57cd), C(5d806318613275f3), C(8150848bcf89d009), C(d5531710d53e1462)}, {C(919ef9e209f2edd1), C(684c33fb726a720a), C(540353f94e8033), C(26da1a143e7d4ec4), C(55095eae445aacf4), C(31efad866d075938), C(f9b580cff4445f94), C(26da1a143e7d4ec4), C(55095eae445aacf4), C(31efad866d075938), C(f9b580cff4445f94), C(b1bea6b8716d9c48), C(9ed2a3df4a15dc53), C(11f1be58843eb8e9), C(d9899ecaaef3c77c)}, {C(b5f9519b6c9280b), C(7823a2fe2e103803), C(d379a205a3bd4660), C(466ec55ee4b4302a), C(714f1b9985deeaf0), C(728595f26e633cf7), C(25ecd0738e1bee2b), C(466ec55ee4b4302a), C(714f1b9985deeaf0), C(728595f26e633cf7), C(25ecd0738e1bee2b), C(db51771ad4778278), C(763e5742ac55639e), C(df040e92d38aa785), C(5df997d298499bf1)}, {C(77a75e89679e6757), C(25d31fee616b5dd0), C(d81f2dfd08890060), C(7598df8911dd40a4), C(3b6dda517509b41b), C(7dae29d248dfffae), C(6697c427733135f), C(7598df8911dd40a4), C(3b6dda517509b41b), C(7dae29d248dfffae), C(6697c427733135f), C(834d6c0444c90899), C(c790675b3cd53818), C(28bb4c996ecadf18), C(92c648513e6e6064)}, {C(9d709e1b086aabe2), C(4d6d6a6c543e3fec), C(df73b01acd416e84), C(d54f613658e35418), C(fcc88fd0567afe77), C(d18f2380980db355), C(ec3896137dfbfa8b), C(d54f613658e35418), C(fcc88fd0567afe77), C(d18f2380980db355), C(ec3896137dfbfa8b), C(eb48dbd9a1881600), C(ca7bd7415ab43ca9), C(e6c5a362919e2351), C(2f4e4bd2d5267c21)}, {C(91c89971b3c20a8a), C(87b82b1d55780b5), C(bc47bb80dfdaefcd), C(87e11c0f44454863), C(2df1aedb5871cc4b), C(ba72fd91536382c8), C(52cebef9e6ea865d), C(87e11c0f44454863), C(2df1aedb5871cc4b), C(ba72fd91536382c8), C(52cebef9e6ea865d), C(5befc3fc66bc7fc5), C(b128bbd735a89061), C(f8f500816fa012b3), C(f828626c9612f04)}, {C(16468c55a1b3f2b4), C(40b1e8d6c63c9ff4), C(143adc6fee592576), C(4caf4deeda66a6ee), C(264720f6f35f7840), C(71c3aef9e59e4452), C(97886ca1cb073c55), C(4caf4deeda66a6ee), C(264720f6f35f7840), C(71c3aef9e59e4452), C(97886ca1cb073c55), C(16155fef16fc08e8), C(9d0c1d1d5254139a), C(246513bf2ac95ee2), C(22c8440f59925034)}, {C(1a2bd6641870b0e4), C(e4126e928f4a7314), C(1e9227d52aab00b2), C(d82489179f16d4e8), C(a3c59f65e2913cc5), C(36cbaecdc3532b3b), C(f1b454616cfeca41), C(d82489179f16d4e8), C(a3c59f65e2913cc5), C(36cbaecdc3532b3b), C(f1b454616cfeca41), C(99393e31e3eefc16), C(3ca886eac5754cdf), C(c11776fc3e4756dd), C(ca118f7059198ba)}, {C(1d2f92f23d3e811a), C(e0812edbcd475412), C(92d2d6ad29c05767), C(fd7feb3d2956875e), C(d7192a886b8b01b6), C(16e71dba55f5b85a), C(93dabd3ff22ff144), C(fd7feb3d2956875e), C(d7192a886b8b01b6), C(16e71dba55f5b85a), C(93dabd3ff22ff144), C(14ff0a5444c272c9), C(fb024d3bb8d915c2), C(1bc3229a94cab5fe), C(6f6f1fb3c0dccf09)}, {C(a47c08255da30ca8), C(cf6962b7353f4e68), C(2808051ea18946b1), C(b5b472960ece11ec), C(13935c99b9abbf53), C(3e80d95687f0432c), C(3516ab536053be5), C(b5b472960ece11ec), C(13935c99b9abbf53), C(3e80d95687f0432c), C(3516ab536053be5), C(748ce6a935755e20), C(2961b51d61b0448c), C(864624113aae88d2), C(a143805366f91338)}, {C(efb3b0262c9cd0c), C(1273901e9e7699b3), C(58633f4ad0dcd5bb), C(62e33ba258712d51), C(fa085c15d779c0e), C(2c15d9142308c5ad), C(feb517011f27be9e), C(62e33ba258712d51), C(fa085c15d779c0e), C(2c15d9142308c5ad), C(feb517011f27be9e), C(1b2b049793b9eedb), C(d26be505fabc5a8f), C(adc483e42a5c36c5), C(c81ff37d56d3b00b)}, {C(5029700a7773c3a4), C(d01231e97e300d0f), C(397cdc80f1f0ec58), C(e4041579de57c879), C(bbf513cb7bab5553), C(66ad0373099d5fa0), C(44bb6b21b87f3407), C(e4041579de57c879), C(bbf513cb7bab5553), C(66ad0373099d5fa0), C(44bb6b21b87f3407), C(a8108c43b4daba33), C(c0b5308c311e865e), C(cdd265ada48f6fcf), C(efbc1dae0a95ac0a)}, {C(71c8287225d96c9a), C(eb836740524735c4), C(4777522d0e09846b), C(16fde90d02a1343b), C(ad14e0ed6e165185), C(8df6e0b2f24085dd), C(caa8a47292d50263), C(16fde90d02a1343b), C(ad14e0ed6e165185), C(8df6e0b2f24085dd), C(caa8a47292d50263), C(a020413ba660359d), C(9de401413f7c8a0c), C(20bfb965927a7c85), C(b52573e5f817ae27)}, {C(4e8b9ad9347d7277), C(c0f195eeee7641cf), C(dbd810bee1ad5e50), C(8459801016414808), C(6fbf75735353c2d1), C(6e69aaf2d93ed647), C(85bb5b90167cce5e), C(8459801016414808), C(6fbf75735353c2d1), C(6e69aaf2d93ed647), C(85bb5b90167cce5e), C(39d79ee490d890cc), C(ac9f31f7ec97deb0), C(3bdc1cae4ed46504), C(eb5c63cfaee05622)}, {C(1d5218d6ee2e52ab), C(cb25025c4daeff3b), C(aaf107566f31bf8c), C(aad20d70e231582b), C(eab92d70d9a22e54), C(cc5ab266375580c0), C(85091463e3630dce), C(aad20d70e231582b), C(eab92d70d9a22e54), C(cc5ab266375580c0), C(85091463e3630dce), C(b830b617a4690089), C(9dacf13cd76f13cf), C(d47cc5224265c68f), C(f04690880202b002)}, {C(162360be6c293c8b), C(ff672b4a831953c8), C(dda57487ab6f78b5), C(38a42e0db55a4275), C(585971da56bb56d6), C(cd957009adc1482e), C(d6a96021e427567d), C(38a42e0db55a4275), C(585971da56bb56d6), C(cd957009adc1482e), C(d6a96021e427567d), C(8e2b1a5a63cd96fe), C(426ef8ce033d722d), C(c4d1c3d8acdda5f), C(4e694c9be38769b2)}, {C(31459914f13c8867), C(ef96f4342d3bef53), C(a4e944ee7a1762fc), C(3526d9b950a1d910), C(a58ba01135bca7c0), C(cbad32e86d60a87c), C(adde1962aad3d730), C(3526d9b950a1d910), C(a58ba01135bca7c0), C(cbad32e86d60a87c), C(adde1962aad3d730), C(55faade148929704), C(bfc06376c72a2968), C(97762698b87f84be), C(117483d4828cbaf7)}, {C(6b4e8fca9b3aecff), C(3ea0a33def0a296c), C(901fcb5fe05516f5), C(7c909e8cd5261727), C(c5acb3d5fbdc832e), C(54eff5c782ad3cdd), C(9d54397f3caf5bfa), C(7c909e8cd5261727), C(c5acb3d5fbdc832e), C(54eff5c782ad3cdd), C(9d54397f3caf5bfa), C(6b53ce24c4fc3092), C(2789abfdd4c9a14d), C(94d6a2261637276c), C(648aa4a2a1781f25)}, {C(dd3271a46c7aec5d), C(fb1dcb0683d711c3), C(240332e9ebe5da44), C(479f936b6d496dca), C(dc2dc93d63739d4a), C(27e4151c3870498c), C(3a3a22ba512d13ba), C(479f936b6d496dca), C(dc2dc93d63739d4a), C(27e4151c3870498c), C(3a3a22ba512d13ba), C(5da92832f96d3cde), C(439b9ad48c4e7644), C(d2939279030accd9), C(6829f920e2950dbe)}, {C(109b226238347d6e), C(e27214c32c43b7e7), C(eb71b0afaf0163ef), C(464f1adf4c68577), C(acf3961e1c9d897f), C(985b01ab89b41fe1), C(6972d6237390aac0), C(464f1adf4c68577), C(acf3961e1c9d897f), C(985b01ab89b41fe1), C(6972d6237390aac0), C(122d89898e256a0e), C(ac830561bd8be599), C(5744312574fbf0ad), C(7bff7f480a924ce9)}, {C(cc920608aa94cce4), C(d67efe9e097bce4f), C(5687727c2c9036a9), C(8af42343888843c), C(191433ffcbab7800), C(7eb45fc94f88a71), C(31bc5418ffb88fa8), C(8af42343888843c), C(191433ffcbab7800), C(7eb45fc94f88a71), C(31bc5418ffb88fa8), C(4b53a37d8f446cb7), C(a6a7dfc757a60d28), C(a074be7bacbc013a), C(cc6db5f270de7adc)}, {C(901ff46f22283dbe), C(9dd59794d049a066), C(3c7d9c3b0e77d2c6), C(dc46069eec17bfdf), C(cacb63fe65d9e3e), C(362fb57287d530c6), C(5854a4fbe1762d9), C(dc46069eec17bfdf), C(cacb63fe65d9e3e), C(362fb57287d530c6), C(5854a4fbe1762d9), C(3197427495021efc), C(5fabf34386aa4205), C(ca662891de36212), C(21f603e4d39bca84)}, {C(11b3bdda68b0725d), C(2366bf0aa97a00bd), C(55dc4a4f6bf47e2b), C(69437142dae5a255), C(f2980cc4816965ac), C(dbbe76ba1d9adfcf), C(49c18025c0a8b0b5), C(69437142dae5a255), C(f2980cc4816965ac), C(dbbe76ba1d9adfcf), C(49c18025c0a8b0b5), C(fe25c147c9001731), C(38b99cad0ca30c81), C(c7ff06ac47eb950), C(a10f92885a6b3c02)}, {C(9f5f03e84a40d232), C(1151a9ff99da844), C(d6f2e7c559ac4657), C(5e351e20f30377bf), C(91b3805daf12972c), C(94417fa6452a265e), C(bfa301a26765a7c), C(5e351e20f30377bf), C(91b3805daf12972c), C(94417fa6452a265e), C(bfa301a26765a7c), C(6924e2a053297d13), C(ed4a7904ed30d77e), C(d734abaad66d6eab), C(ce373e6c09e6e8a1)}, {C(39eeff4f60f439be), C(1f7559c118517c70), C(6139d2492237a36b), C(fd39b7642cecf78f), C(104f1af4e9201df5), C(ab1a3cc7eaeab609), C(cee3363f210a3d8b), C(fd39b7642cecf78f), C(104f1af4e9201df5), C(ab1a3cc7eaeab609), C(cee3363f210a3d8b), C(51490f65fe56c884), C(6a8c8322cda993c), C(1f90609a017de1f0), C(9f3acea480a41edf)}, {C(9b9e0126fe4b8b04), C(6a6190d520886c41), C(69640b27c16b3ed8), C(18865ff87619fd8f), C(dec5293e665663d8), C(ea07c345872d3201), C(6fce64da038a17ab), C(18865ff87619fd8f), C(dec5293e665663d8), C(ea07c345872d3201), C(6fce64da038a17ab), C(ad48f3c826c6a83e), C(70a1ff080a4da737), C(ecdac686c7d7719), C(700338424b657470)}, {C(3ec4b8462b36df47), C(ff8de4a1cbdb7e37), C(4ede0449884716ac), C(b5f630ac75a8ce03), C(7cf71ae74fa8566a), C(e068f2b4618df5d), C(369df952ad3fd0b8), C(b5f630ac75a8ce03), C(7cf71ae74fa8566a), C(e068f2b4618df5d), C(369df952ad3fd0b8), C(5e1ba38fea018eb6), C(5ea5edce48e3da30), C(9b3490c941069dcb), C(e17854a44cc2fff)}, {C(5e3fd9298fe7009f), C(d2058a44222d5a1d), C(cc25df39bfeb005c), C(1b0118c5c60a99c7), C(6ae919ef932301b8), C(cde25defa089c2fc), C(c2a3776e3a7716c4), C(1b0118c5c60a99c7), C(6ae919ef932301b8), C(cde25defa089c2fc), C(c2a3776e3a7716c4), C(2557bf65fb26269e), C(b2edabba58f2ae4f), C(264144e9f0e632cb), C(ad6481273c979566)}, {C(7504ecb4727b274e), C(f698cfed6bc11829), C(71b62c425ecd348e), C(2a5e555fd35627db), C(55d5da439c42f3b8), C(a758e451732a1c6f), C(18caa6b46664b484), C(2a5e555fd35627db), C(55d5da439c42f3b8), C(a758e451732a1c6f), C(18caa6b46664b484), C(6ec1c7d1524bbad7), C(1cc3531dc422529d), C(61a6eeb29c0e5110), C(9cc8652016784a6a)}, {C(4bdedc104d5eaed5), C(531c4bb4fd721e5d), C(1d860834e94a219f), C(1944ec723253392b), C(7ea6aa6a2f278ea5), C(5ff786af8113b3d5), C(194832eb9b0b8d0f), C(1944ec723253392b), C(7ea6aa6a2f278ea5), C(5ff786af8113b3d5), C(194832eb9b0b8d0f), C(56ab0396ed73fd38), C(2c88725b3dfbf89d), C(7ff57adf6275c816), C(b32f7630bcdb218)}, {C(da0b4a6fb26a4748), C(8a3165320ae1af74), C(4803664ee3d61d09), C(81d90ddff0d00fdb), C(2c8c7ce1173b5c77), C(18c6b6c8d3f91dfb), C(415d5cbbf7d9f717), C(81d90ddff0d00fdb), C(2c8c7ce1173b5c77), C(18c6b6c8d3f91dfb), C(415d5cbbf7d9f717), C(b683e956f1eb3235), C(43166dde2b64d11f), C(f9689c90f5aad771), C(ca0ebc253c2eec38)}, {C(bad6dd64d1b18672), C(6d4c4b91c68bd23f), C(d8f1507176822db7), C(381068e0f65f708b), C(b4f3762e451b12a6), C(6d61ed2f6d4e741), C(8b3b9df537b91a2c), C(381068e0f65f708b), C(b4f3762e451b12a6), C(6d61ed2f6d4e741), C(8b3b9df537b91a2c), C(b0759e599a91575c), C(9e7adbcc77212239), C(cf0eba98436555fe), C(b1fcc9c42c4cd1e6)}, {C(98da3fe388d5860e), C(14a9fda8b3adb103), C(d85f5f798637994b), C(6e8e8ff107799274), C(24a2ef180891b531), C(c0eaf33a074bcb9d), C(1fa399a82974e17e), C(6e8e8ff107799274), C(24a2ef180891b531), C(c0eaf33a074bcb9d), C(1fa399a82974e17e), C(e7c116bef933725d), C(859908c7d17b93de), C(f6cfa27113af4a72), C(edf41c5d83c721a8)}, {C(ef243a576431d7ac), C(92a32619ecfae0a5), C(fb34d2c062dc803a), C(f5f8b21ec30bd3a0), C(80a442fd5c6482a8), C(4fde11e5ccde5169), C(55671451f661a885), C(f5f8b21ec30bd3a0), C(80a442fd5c6482a8), C(4fde11e5ccde5169), C(55671451f661a885), C(94f27bc2d5d8d63e), C(2156968b87f084dc), C(b591bcae146f6fea), C(f57f4c01e41ac7fe)}, {C(97854de6f22c97b6), C(1292ac07b0f426bb), C(9a099a28b22d3a38), C(caac64f5865d87f3), C(771b9fdbd3aa4bd2), C(88446393c3606c2d), C(bc3d3dcd5b7d6d7f), C(caac64f5865d87f3), C(771b9fdbd3aa4bd2), C(88446393c3606c2d), C(bc3d3dcd5b7d6d7f), C(56e22512b832d3ee), C(bbc677fe5ce0b665), C(f1914b0f070e5c32), C(c10d40362472dcd1)}, {C(d26ce17bfc1851d), C(db30fb632c7da294), C(26cb7b1a465400a5), C(401a0581221957e2), C(fc04e99ae3a283ce), C(fe895303ab2d1e3e), C(35ab7c498403975b), C(401a0581221957e2), C(fc04e99ae3a283ce), C(fe895303ab2d1e3e), C(35ab7c498403975b), C(c6e4c8dc6f52fb11), C(63f0b484c2c7502f), C(93693da3439bdbe9), C(1264dbaaaaf6b7f1)}, {C(97477bac0ba4c7f1), C(788ef8729dca29ac), C(63d88e226d36132c), C(330b7e93663affbd), C(3c59913fcf0d603f), C(e207e6572672fd0a), C(8a5dc17019c8a667), C(330b7e93663affbd), C(3c59913fcf0d603f), C(e207e6572672fd0a), C(8a5dc17019c8a667), C(5c8f47ade659d40), C(6e0838e5a808e9a2), C(8a2d9a0afcd48b19), C(d1c9d5af7b48418d)}, {C(f6bbcba92b11f5c8), C(72cf221cad20f191), C(a04726593764122d), C(77fbb70409d316e2), C(c864432c5208e583), C(d3f593922668c184), C(23307562648bdb54), C(77fbb70409d316e2), C(c864432c5208e583), C(d3f593922668c184), C(23307562648bdb54), C(b03e0b274f848a74), C(c6121e3af71f4281), C(2e48dd2a16ca63ec), C(f4cd44c69ae024df)}, {C(1ac8b67c1c82132), C(7536db9591be9471), C(42f18fbe7141e565), C(20085827a39ff749), C(42e6c504df174606), C(839da16331fea7ac), C(7fd768552b10ffc6), C(20085827a39ff749), C(42e6c504df174606), C(839da16331fea7ac), C(7fd768552b10ffc6), C(d1c53c90fde72640), C(c61ae7cf4e266556), C(127561e440e4c156), C(f329cae8c26af3e1)}, {C(9cd716ca0eee52fa), C(67c1076e1ef11f93), C(927342024f36f5d7), C(d0884af223fd056b), C(bb33aafc7b80b3e4), C(36b722fea81a4c88), C(6e72e3022c0ed97), C(d0884af223fd056b), C(bb33aafc7b80b3e4), C(36b722fea81a4c88), C(6e72e3022c0ed97), C(5db446a3ba66e0ba), C(2e138fb81b28ad9), C(16e8e82995237c85), C(9730dbfb072fbf03)}, {C(1909f39123d9ad44), C(c0bdd71c5641fdb7), C(112e5d19abda9b14), C(984cf3f611546e28), C(d7d9c9c4e7efb5d7), C(b3152c389532b329), C(1c168b512ec5f659), C(984cf3f611546e28), C(d7d9c9c4e7efb5d7), C(b3152c389532b329), C(1c168b512ec5f659), C(eca67cc49e26069a), C(73cb0b224d36d541), C(df8379190ae6c5fe), C(e0f6bde7c4726211)}, {C(1d206f99f535efeb), C(882e15548afc3422), C(c94f203775c8c634), C(24940a3adac420b8), C(5adf73051c52bce0), C(1aa5030247ed3d32), C(e1ae74ab6804c08b), C(24940a3adac420b8), C(5adf73051c52bce0), C(1aa5030247ed3d32), C(e1ae74ab6804c08b), C(95217bf71b0da84c), C(ca9bb91c0126a36e), C(741b9a99ea470974), C(2adc4e34b8670f41)}, {C(b38c3a83042eb802), C(ea134be7c6e0c326), C(81d396c683df4f35), C(2a55645640911e27), C(4fac2eefbd36e26f), C(79ad798fb4c5835c), C(359aa2faec050131), C(2a55645640911e27), C(4fac2eefbd36e26f), C(79ad798fb4c5835c), C(359aa2faec050131), C(5b802dcec21a7157), C(6ecde915b75ede0a), C(f2e653587e89058b), C(a661be80528d3385)}, {C(488d6b45d927161b), C(f5cac66d869a8aaf), C(c326d56c643a214e), C(10a7228693eb083e), C(1054fb19cbacf01c), C(a8f389d24587ebd8), C(afcb783a39926dba), C(10a7228693eb083e), C(1054fb19cbacf01c), C(a8f389d24587ebd8), C(afcb783a39926dba), C(fe83e658532edf8f), C(6fdcf97f147dc4db), C(dc5e487845abef4b), C(137693f4eab77e27)}, {C(3d6aaa43af5d4f86), C(44c7d370910418d8), C(d099515f7c5c4eca), C(39756960441fbe2f), C(fb68e5fedbe3d874), C(3ff380fbdd27b8e), C(f48832fdda648998), C(39756960441fbe2f), C(fb68e5fedbe3d874), C(3ff380fbdd27b8e), C(f48832fdda648998), C(270ddbf2327058c9), C(9eead83a8319d0c4), C(b4c3356e162b086d), C(88f013588f411b7)}, {C(e5c40a6381e43845), C(312a18e66bbceaa3), C(31365186c2059563), C(cba4c10e65410ba0), C(3c250c8b2d72c1b6), C(177e82f415595117), C(8c8dcfb9e73d3f6), C(cba4c10e65410ba0), C(3c250c8b2d72c1b6), C(177e82f415595117), C(8c8dcfb9e73d3f6), C(c017a797e49c0f7), C(ea2b233b2e7d5aea), C(878d204c55a56cb1), C(7b1b62cc0dfdc523)}, {C(86fb323e5a4b710b), C(710c1092c23a79e0), C(bd2c6d3fc949402e), C(951f2078aa4b8099), C(e68b7fefa1cfd190), C(41525a4990ba6d4a), C(c373552ef4b51712), C(951f2078aa4b8099), C(e68b7fefa1cfd190), C(41525a4990ba6d4a), C(c373552ef4b51712), C(73eb44c6122bdf5a), C(58047289a314b013), C(e31d30432521705b), C(6cf856774873faa4)}, {C(7930c09adaf6e62e), C(f230d3311593662c), C(a795b9bf6c37d211), C(b57ec44bc7101b96), C(6cb710e77767a25a), C(2f446152d5e3a6d0), C(cd69172f94543ce3), C(b57ec44bc7101b96), C(6cb710e77767a25a), C(2f446152d5e3a6d0), C(cd69172f94543ce3), C(e6c2483cf425f072), C(2060d5d4379d6d5a), C(86a3c04c2110d893), C(561d3b8a509313c6)}, {C(e505e86f0eff4ecd), C(cf31e1ccb273b9e6), C(d8efb8e9d0fe575), C(ed094f47671e359d), C(d9ebdb047d57611a), C(1c620e4d301037a3), C(df6f401c172f68e8), C(ed094f47671e359d), C(d9ebdb047d57611a), C(1c620e4d301037a3), C(df6f401c172f68e8), C(af0a2c7f72388ec7), C(6d4c4a087fa4564a), C(411b30def69700a), C(67e5c84557a47e01)}, {C(dedccb12011e857), C(d831f899174feda8), C(ee4bcdb5804c582a), C(5d765af4e88f3277), C(d2abe1c63ad4d103), C(342a8ce0bc7af6e4), C(31bfda956f3e5058), C(5d765af4e88f3277), C(d2abe1c63ad4d103), C(342a8ce0bc7af6e4), C(31bfda956f3e5058), C(4c7a1fec9af54bbb), C(84a88f0655899bf4), C(66fb60d0582ac601), C(be0dd1ffe967bd4a)}, {C(4d679bda26f5555f), C(7deb387eb7823c1c), C(a65ef3b4fecd6888), C(a6814d3dc578b9df), C(3372111a3292b691), C(e97589c81d92b513), C(74edd943d1b9b5bf), C(a6814d3dc578b9df), C(3372111a3292b691), C(e97589c81d92b513), C(74edd943d1b9b5bf), C(889e38b0af80bb7a), C(a416349af3c5818b), C(f5f5bb25576221c1), C(3be023fa6912c32e)}, {C(e47cd22995a75a51), C(3686350c2569a162), C(861afcb185b8efd9), C(63672de7951e1853), C(3ca0c763273b99db), C(29e04fa994cccb98), C(b02587d792be5ee8), C(63672de7951e1853), C(3ca0c763273b99db), C(29e04fa994cccb98), C(b02587d792be5ee8), C(c85ada4858f7e4fc), C(3f280ab7d5864460), C(4109822f92f68326), C(2d73f61314a2f630)}, {C(92ba8e12e0204f05), C(4e29321580273802), C(aa83b675ed74a851), C(a16cd2e8b445a3fd), C(f0d4f9fb613c38ef), C(eee7755d444d8f2f), C(b530591eb67ae30d), C(a16cd2e8b445a3fd), C(f0d4f9fb613c38ef), C(eee7755d444d8f2f), C(b530591eb67ae30d), C(6fb3031a6edf8fec), C(65118d08aecf56d8), C(9a2117bbef1faa8), C(97055c5fd310aa93)}, {C(bb3a8427c64f8939), C(b5902af2ec095a04), C(89f1b440667b2a28), C(5386ef0b438d0330), C(d39e03c686f8a2da), C(9555249bb9073d78), C(8c0b3623fdf0b156), C(5386ef0b438d0330), C(d39e03c686f8a2da), C(9555249bb9073d78), C(8c0b3623fdf0b156), C(354fc5d3a5504e5e), C(b2fd7391719aa614), C(13cd4ce3dfe27b3d), C(a2d63a85dc3cae4b)}, {C(998988f7d6dacc43), C(5f2b853d841152db), C(d76321badc5cb978), C(e381f24ee1d9a97d), C(7c5d95b2a3af2e08), C(ca714acc461cdc93), C(1a8ee94bc847aa3e), C(e381f24ee1d9a97d), C(7c5d95b2a3af2e08), C(ca714acc461cdc93), C(1a8ee94bc847aa3e), C(ee59ee4c21a36f47), C(d476e8bba5bf5143), C(22a03cb5900f6ec8), C(19d954e14f35d7a8)}, {C(3f1049221dd72b98), C(8d9200d7a0664c37), C(3925704c83a5f406), C(4cbef49086e62678), C(d77dfecc2819ef19), C(c327e4deaf4c7e72), C(b4d58c73a262a32d), C(4cbef49086e62678), C(d77dfecc2819ef19), C(c327e4deaf4c7e72), C(b4d58c73a262a32d), C(78cd002324861653), C(7c3f3977576efb88), C(d1c9975fd4a4cc26), C(3e3cbc90a9baa442)}, {C(419e4ff78c3e06f3), C(aa8ff514c8a141d7), C(5bb176e21f89f10d), C(becb065dc12d8b4e), C(ebee135492a2018), C(d3f07e65bcd9e13a), C(85c933e85382e9f9), C(becb065dc12d8b4e), C(ebee135492a2018), C(d3f07e65bcd9e13a), C(85c933e85382e9f9), C(2c19ab7c419ebaca), C(982375b2999bdb46), C(652ca1c6325d9296), C(e9c790fa8561940a)}, {C(9ba090af14171317), C(b0445c5232d7be53), C(72cc929d1577ddb8), C(bc944c1b5ba2184d), C(ab3d57e5e60e9714), C(5d8d27e7dd0a365a), C(4dd809e11740af1a), C(bc944c1b5ba2184d), C(ab3d57e5e60e9714), C(5d8d27e7dd0a365a), C(4dd809e11740af1a), C(6f42d856faad44df), C(5118dc58d7eaf56e), C(829bbc076a43004), C(1747fbbfaca6da98)}, {C(6ad739e4ada9a340), C(2c6c4fb3a2e9b614), C(ab58620e94ca8a77), C(aaa144fbe3e6fda2), C(52a9291d1e212bc5), C(2b4c68291f26b570), C(45351ab332855267), C(aaa144fbe3e6fda2), C(52a9291d1e212bc5), C(2b4c68291f26b570), C(45351ab332855267), C(1149f55400bc9799), C(8c6ec1a0c617771f), C(e9966cc03f3bec05), C(3e6889140ccd2646)}, {C(8ecff07fd67e4abd), C(f1b8029b17006ece), C(21d96d5859229a61), C(b8c18d66154ac51), C(5807350371ad7388), C(81f783f4f5ab2b8), C(fa4e659f90744de7), C(b8c18d66154ac51), C(5807350371ad7388), C(81f783f4f5ab2b8), C(fa4e659f90744de7), C(809da4baa51cad2c), C(88d5c11ff5598342), C(7c7125b0681d67d0), C(1b5ba6124bfed8e8)}, {C(497ca8dbfee8b3a7), C(58c708155d70e20e), C(90428a7e349d6949), C(b744f5056e74ca86), C(88aa27b96f3d84a5), C(b4b1ee0470ac3826), C(aeb46264f4e15d4f), C(b744f5056e74ca86), C(88aa27b96f3d84a5), C(b4b1ee0470ac3826), C(aeb46264f4e15d4f), C(14921b1ee856bc55), C(a341d74aaba00a02), C(4f50aa8e3d08a919), C(75a148668ff3869e)}, {C(a929cd66daa65b0a), C(7c0150a2d9ca564d), C(46ddec37e2ec0a6d), C(4323852cc57e4af3), C(1f5f638bbf9d2e5b), C(578fb6ac89a31d9), C(7792536d9ac4bf12), C(4323852cc57e4af3), C(1f5f638bbf9d2e5b), C(578fb6ac89a31d9), C(7792536d9ac4bf12), C(60be62e795ef5798), C(c276cc5b44febefe), C(519ba0b9f6d1be95), C(1fdce3561ed35bb8)}, {C(4107c4156bc8d4bc), C(1cda0c6f3f0f48af), C(cf11a23299cf7181), C(766b71bff7d6f461), C(b004f2c910a6659e), C(4c0eb3848e1a7c8), C(3f90439d05c3563b), C(766b71bff7d6f461), C(b004f2c910a6659e), C(4c0eb3848e1a7c8), C(3f90439d05c3563b), C(4a2a013f4bc2c1d7), C(888779ab0c272548), C(ae0f8462d89a4241), C(c5c85b7c44679abd)}, {C(15b38dc0e40459d1), C(344fedcfc00fff43), C(b9215c5a0fcf17df), C(d178444a236c1f2d), C(5576deee27f3f103), C(943611bb5b1b0736), C(a0fde17cb5c2316d), C(d178444a236c1f2d), C(5576deee27f3f103), C(943611bb5b1b0736), C(a0fde17cb5c2316d), C(feaa1a047f4375f3), C(5435f313e84767e), C(522e4333cd0330c1), C(7e6b609b0ea9e91f)}, {C(e5e5370ed3186f6c), C(4592e75db47ea35d), C(355d452b82250e83), C(7a265e37da616168), C(6a1f06c34bafa27), C(fbae175e7ed22a9c), C(b144e84f6f33c098), C(7a265e37da616168), C(6a1f06c34bafa27), C(fbae175e7ed22a9c), C(b144e84f6f33c098), C(bd444561b0db41fc), C(2072c85731e7b0b0), C(ce1b1fac436b51f3), C(4f5d44f31a3dcdb9)}, {C(ea2785c8f873e28f), C(3e257272f4464f5f), C(9267e7e0cc9c7fb5), C(9fd4d9362494cbbc), C(e562bc615befb1b9), C(8096808d8646cfde), C(c4084a587b9776ec), C(9fd4d9362494cbbc), C(e562bc615befb1b9), C(8096808d8646cfde), C(c4084a587b9776ec), C(a9135db8a850d8e4), C(fffc4f8b1a11f5af), C(c50e9173c2c6fe64), C(a32630581df4ceda)}, {C(e7bf98235fc8a4a8), C(4042ef2aae400e64), C(6538ba9ffe72dd70), C(c84bb7b3881ab070), C(36fe6c51023fbda0), C(d62838514bb87ea4), C(9eeb5e7934373d86), C(c84bb7b3881ab070), C(36fe6c51023fbda0), C(d62838514bb87ea4), C(9eeb5e7934373d86), C(5f8480d0a2750a96), C(40afa38506456ad9), C(e4012b7ef2e0ddea), C(659da200a011836b)}, {C(b94e261a90888396), C(1f468d07e853294c), C(cb2c9b863a5317b9), C(4473c8e2a3458ee0), C(258053945ab4a39a), C(f8d745ca41962817), C(7afb6d40df9b8f71), C(4473c8e2a3458ee0), C(258053945ab4a39a), C(f8d745ca41962817), C(7afb6d40df9b8f71), C(9030c2349604f677), C(f544dcd593087faf), C(77a3b0efe6345d12), C(fff4e398c05817cc)}, {C(4b0226e5f5cdc9c), C(a836ae7303dc4301), C(8505e1b628bac101), C(b5f52041a698da7), C(29864874b5f1936d), C(49b3a0c6d78f98da), C(93a1a8c7d90de296), C(b5f52041a698da7), C(29864874b5f1936d), C(49b3a0c6d78f98da), C(93a1a8c7d90de296), C(ed62288423c17b7f), C(685afa2cfba09660), C(6d9b6f59585452c6), C(e505535c4010efb9)}, {C(e07edbe7325c718c), C(9db1eda964f06827), C(2f245ad774e4cb1b), C(664ec3fad8521859), C(406f082beb9ca29a), C(b6b0fb3a7981c7c8), C(3ebd280b598a9721), C(664ec3fad8521859), C(406f082beb9ca29a), C(b6b0fb3a7981c7c8), C(3ebd280b598a9721), C(d9a6ceb072eab22a), C(d5bc5df5eb2ff6f1), C(488db3cab48daa0b), C(9916f14fa5672f37)}, {C(f4b56421eae4c4e7), C(5da0070cf40937a0), C(aca4a5e01295984a), C(5414e385f5677a6d), C(41ef105f8a682a28), C(4cd2e95ea7f5e7b0), C(775bb1e0d57053b2), C(5414e385f5677a6d), C(41ef105f8a682a28), C(4cd2e95ea7f5e7b0), C(775bb1e0d57053b2), C(8919017805e84b3f), C(15402f44e0e2b259), C(483b1309e1403c87), C(85c7b4232d45b0d9)}, {C(c07fcb8ae7b4e480), C(4ebcad82e0b53976), C(8643c63d6c78a6ce), C(d4bd358fed3e6aa5), C(8a1ba396356197d9), C(7afc2a54733922cc), C(b813bdac4c7c02ef), C(d4bd358fed3e6aa5), C(8a1ba396356197d9), C(7afc2a54733922cc), C(b813bdac4c7c02ef), C(f6c610cf7e7c955), C(dab6a53e1c0780f8), C(837c9ffec33e5d48), C(8cb8c20032af152d)}, {C(3edad9568a9aaab), C(23891bbaeb3a17bc), C(4eb7238738b0c51a), C(db0c32f76f5b7fc1), C(5e41b711f0abd1a0), C(bcb758f01ded0a11), C(7d15f7d87955e28b), C(db0c32f76f5b7fc1), C(5e41b711f0abd1a0), C(bcb758f01ded0a11), C(7d15f7d87955e28b), C(cd2dc1f0b05939b), C(9fd6d680462e4c47), C(95d5846e993bc8ff), C(f0b3cafc2697b8a8)}, {C(fcabde8700de91e8), C(63784d19c60bf366), C(8f3af9a056b1a1c8), C(32d3a29cf49e2dc9), C(3079c0b0c2269bd0), C(ed76ba44f04e7b82), C(6eee76a90b83035f), C(32d3a29cf49e2dc9), C(3079c0b0c2269bd0), C(ed76ba44f04e7b82), C(6eee76a90b83035f), C(4a9286f545bbc09), C(bd36525be4dd1b51), C(5f7a9117228fdee5), C(543c96a08f03151c)}, {C(362fc5ba93e8eb31), C(7549ae99fa609d61), C(47e4cf524e37178f), C(a54eaa5d7f3a7227), C(9d26922965d54727), C(27d22acb31a194d4), C(e9b8e68771db0da6), C(a54eaa5d7f3a7227), C(9d26922965d54727), C(27d22acb31a194d4), C(e9b8e68771db0da6), C(16fd0e006209abe8), C(81d3f72987a6a81a), C(74e96e4044817bc7), C(924ca5f08572fef9)}, {C(e323b1c5b55a4dfb), C(719993d7d1ad77fb), C(555ca6c6166e989c), C(ea37f61c0c2f6d53), C(9b0c2174f14a01f5), C(7bbe6921e26293f3), C(2ab6c72235b6c98a), C(ea37f61c0c2f6d53), C(9b0c2174f14a01f5), C(7bbe6921e26293f3), C(2ab6c72235b6c98a), C(2c6e7668f37f6d23), C(3e8edb057a57c2dd), C(2595fc79768c8b34), C(ffc541f5efed9c43)}, {C(9461913a153530ef), C(83fc6d9ed7d1285a), C(73df90bdc50807cf), C(a32c192f6e3c3f66), C(8f10077b8a902d00), C(61a227f2faac29b4), C(1a71466fc005a61d), C(a32c192f6e3c3f66), C(8f10077b8a902d00), C(61a227f2faac29b4), C(1a71466fc005a61d), C(12545812f3d01a92), C(aece72f823ade07d), C(52634cdd5f9e5260), C(cb48f56805c08e98)}, {C(ec2332acc6df0c41), C(59f5ee17e20a8263), C(1087d756afcd8e7b), C(a82a7bb790678fc9), C(d197682c421e4373), C(dd78d25c7f0f935a), C(9850cb6fbfee520f), C(a82a7bb790678fc9), C(d197682c421e4373), C(dd78d25c7f0f935a), C(9850cb6fbfee520f), C(2590847398688a46), C(ad266f08713ca5fe), C(25b978be91e830b5), C(2996c8f2b4c8f231)}, {C(aae00b3a289bc82), C(4f6d69f5a5a5b659), C(3ff5abc145614e3), C(33322363b5f45216), C(7e83f1fe4189e843), C(df384b2adfc35b03), C(396ce7790a5ada53), C(33322363b5f45216), C(7e83f1fe4189e843), C(df384b2adfc35b03), C(396ce7790a5ada53), C(c3286e44108b8d36), C(6db8716c498d703f), C(d1db09466f37f4e7), C(56c98e7f68a41388)}, {C(4c842e732fcd25f), C(e7dd7b953cf9c2b2), C(911ee248a76ae3), C(33c6690937582317), C(fe6d61a77985d7bb), C(97b153d04a115535), C(d3fde02e42cfe6df), C(33c6690937582317), C(fe6d61a77985d7bb), C(97b153d04a115535), C(d3fde02e42cfe6df), C(d1c7d1efa52a016), C(1d6ed137f4634c), C(1a260ec505097081), C(8d1e70861a1c7db6)}, {C(40e23ca5817a91f3), C(353e2935809b7ad1), C(f7820021b86391bb), C(f3d41b3d4717eb83), C(2670d457dde68842), C(19707a6732c49278), C(5d0f05a83569ba26), C(f3d41b3d4717eb83), C(2670d457dde68842), C(19707a6732c49278), C(5d0f05a83569ba26), C(6fe5bc84e528816a), C(94df3dca91a29ace), C(420196ed097e8b6f), C(7c52da0e1f043ad6)}, {C(2564527fad710b8d), C(2bdcca8d57f890f), C(81f7bfcd9ea5a532), C(dd70e407984cfa80), C(66996d6066db6e1a), C(36a812bc418b97c9), C(18ea2c63da57f36e), C(dd70e407984cfa80), C(66996d6066db6e1a), C(36a812bc418b97c9), C(18ea2c63da57f36e), C(937fd7ad09be1a8f), C(163b12cab35d5d15), C(3606c3e441335cce), C(949f6ea5bb241ae8)}, {C(6bf70df9d15a2bf6), C(81cad17764b8e0dd), C(58b349a9ba22a7ef), C(9432536dd9f65229), C(192dc54522da3e3d), C(274c6019e0227ca9), C(160abc932a4e4f35), C(9432536dd9f65229), C(192dc54522da3e3d), C(274c6019e0227ca9), C(160abc932a4e4f35), C(1204f2fb5aa79dc6), C(2536edaf890f0760), C(6f2b561f44ff46b4), C(8c7b3e95baa8d984)}, {C(45e6f446eb6bbcf5), C(98ab0ef06f1a7d84), C(85ae96bacca50de6), C(b9aa5bead3352801), C(8a6d9e02a19a4229), C(c352f5b6d5ee1d9d), C(ce562bdb0cfa84fb), C(b9aa5bead3352801), C(8a6d9e02a19a4229), C(c352f5b6d5ee1d9d), C(ce562bdb0cfa84fb), C(d47b768a85283981), C(1fe72557be57a11b), C(95d8afe4af087d51), C(2f59c4e383f30045)}, {C(620d3fe4b8849c9e), C(975a15812a429ec2), C(437c453593dcaf13), C(8d8e7c63385df78e), C(16d55add72a5e25e), C(aa6321421dd87eb5), C(6f27f62e785f0203), C(8d8e7c63385df78e), C(16d55add72a5e25e), C(aa6321421dd87eb5), C(6f27f62e785f0203), C(829030a61078206e), C(ae1f30fcfa445cc8), C(f61f21c9df4ef68d), C(1e5b1945f858dc4c)}, {C(535aa7340b3c168f), C(bed5d3c3cd87d48a), C(266d40ae10f0cbc1), C(ce218d5b44f7825a), C(2ae0c64765800d3a), C(f22dc1ae0728fc01), C(48a171bc666d227f), C(ce218d5b44f7825a), C(2ae0c64765800d3a), C(f22dc1ae0728fc01), C(48a171bc666d227f), C(e7367aff24203c97), C(da39d2be1db3a58d), C(85ce86523003933a), C(dfd4ef2ae83f138a)}, {C(dd3e761d4eada300), C(893d7e4c3bea5bb6), C(cc6d6783bf43eea), C(eb8eed7c391f0044), C(b58961c3abf80753), C(3d75ea687191521), C(389be7bbd8e478f3), C(eb8eed7c391f0044), C(b58961c3abf80753), C(3d75ea687191521), C(389be7bbd8e478f3), C(917070a07441ee47), C(d78efa8cd65b313), C(a8a16f4c1c08c8a1), C(b69cb8ee549eb113)}, {C(4ac1902ccde06545), C(2c44aeb0983a7a07), C(b566035215b309f9), C(64c136fe9404a7b3), C(99f3d8c98a399d5e), C(6319c7cb14180185), C(fbacdbd277d33f4c), C(64c136fe9404a7b3), C(99f3d8c98a399d5e), C(6319c7cb14180185), C(fbacdbd277d33f4c), C(a96a5626c2adda86), C(39ea72fd2ad133ed), C(b5583f2f736df73e), C(ef2c63619782b7ba)}, {C(aee339a23bb00a5e), C(cbb402255318f919), C(9922948e99aa0781), C(df367034233fedc4), C(dcbe14db816586e5), C(f4b1cb814adf21d3), C(f4690695102fa00a), C(df367034233fedc4), C(dcbe14db816586e5), C(f4b1cb814adf21d3), C(f4690695102fa00a), C(6b4f01dd6b76dafc), C(b79388676b50da5d), C(cb64f8bde5ed3393), C(9b422781f13219d3)}, {C(627599e91148df4f), C(3e2d01e8baab062b), C(2daab20edb245251), C(9a958bc3a895a223), C(331058dd6c5d2064), C(46c4d962072094fa), C(e6207c19160e58eb), C(9a958bc3a895a223), C(331058dd6c5d2064), C(46c4d962072094fa), C(e6207c19160e58eb), C(5655e4dbf7272728), C(67b217b1f56c747d), C(3ac0be79691b9a0d), C(9d0954dd0b57073)}, {C(cfb04cf00cfed6b3), C(5fe75fc559af22fa), C(c440a935d72cdc40), C(3ab0d0691b251b8b), C(47181a443504a819), C(9bcaf1253f99f499), C(8ee002b89c1b6b3f), C(3ab0d0691b251b8b), C(47181a443504a819), C(9bcaf1253f99f499), C(8ee002b89c1b6b3f), C(55dfe8eedcd1ec5e), C(1bf50f0bbad796a5), C(9044369a042d7fd6), C(d423df3e3738ba8f)}, {C(942631c47a26889), C(427962c82d8a6e00), C(224071a6592537ff), C(d3e96f4fb479401), C(68b3f2ec11de9368), C(cb51b01083acad4f), C(500cec4564d62aeb), C(d3e96f4fb479401), C(68b3f2ec11de9368), C(cb51b01083acad4f), C(500cec4564d62aeb), C(4ce547491e732887), C(9423883a9a11df4c), C(1a0fc7a14214360), C(9e837914505da6ed)}, {C(4c9eb4e09726b47e), C(fd927483a2b38cf3), C(6d7e56407d1ba870), C(9f5dc7db69fa1e29), C(f42fff56934533d5), C(92d768c230a53918), C(f3360ff11642136c), C(9f5dc7db69fa1e29), C(f42fff56934533d5), C(92d768c230a53918), C(f3360ff11642136c), C(9e989932eb86d1b5), C(449a77f69a8a9d65), C(efabaf8a7789ed9a), C(2798eb4c50c826fd)}, {C(cf7f208ef20e887a), C(f4ce4edeadcaf1a1), C(7ee15226eaf4a74d), C(17ab41ab2ae0705d), C(9dd56694aa2dcd4e), C(dd4fa2add9baced2), C(7ad99099c9e199a3), C(17ab41ab2ae0705d), C(9dd56694aa2dcd4e), C(dd4fa2add9baced2), C(7ad99099c9e199a3), C(a59112144accef0e), C(5838df47e38d251d), C(8750fe45760331e5), C(4b2ce14732e0312a)}, {C(a8dc4687bcf27f4), C(c4aadd7802553f15), C(5401eb9912be5269), C(5c2a2b5b0657a928), C(1e1968ebb38fcb99), C(a082d0e067c4a59c), C(18b616495ad9bf5d), C(5c2a2b5b0657a928), C(1e1968ebb38fcb99), C(a082d0e067c4a59c), C(18b616495ad9bf5d), C(18c5dc6c78a7f9ed), C(b3cc94fe34b68aa1), C(3b77e91292be38cc), C(61d1786ec5097971)}, {C(daed638536ed19df), C(1a762ea5d7ac6f7e), C(48a1cc07a798b84f), C(7f15bdaf50d550f9), C(4c1d48aa621a037e), C(2b1d7a389d497ee0), C(81c6775d46f4b517), C(7f15bdaf50d550f9), C(4c1d48aa621a037e), C(2b1d7a389d497ee0), C(81c6775d46f4b517), C(35296005cbba3ebe), C(db1642f825b53532), C(3e07588a9fd829a4), C(60f13b5446bc7638)}, {C(90a04b11ee1e4af3), C(ab09a35f8f2dff95), C(d7cbe82231ae1e83), C(3262e9017bb788c4), C(1612017731c997bc), C(e789d66134aff5e1), C(275642fd17048af1), C(3262e9017bb788c4), C(1612017731c997bc), C(e789d66134aff5e1), C(275642fd17048af1), C(99255b68d0b46b51), C(74a6f1ad4b2bb296), C(4164222761af840e), C(54d59bf6211a8fe6)}, {C(511f29e1b732617d), C(551cb47a9a83d769), C(df6f56fbda20e7a), C(f27583a930221d44), C(d7d2c46de69b2ed8), C(add24ddd2be4a850), C(5cf2f688dbb93585), C(f27583a930221d44), C(d7d2c46de69b2ed8), C(add24ddd2be4a850), C(5cf2f688dbb93585), C(a7f8e42d5dd4aa00), C(72dc11fd76b4dea9), C(8886f194e6f8e3ff), C(7e8ead04a0e0b1ef)}, {C(95567f03939e651f), C(62a426f09d81d884), C(15cb96e36a8e712c), C(1a2f43bdeaea9c28), C(bca2fd840831291f), C(83446d4a1f7dcc1a), C(449a211df83b6187), C(1a2f43bdeaea9c28), C(bca2fd840831291f), C(83446d4a1f7dcc1a), C(449a211df83b6187), C(553ce97832b2f695), C(3110a2ba303db75), C(b91d6d399a02f453), C(3cb148561e0ef2bb)}, {C(248a32ad10e76bc3), C(dac39c8b036985e9), C(79d38c4af2958b56), C(cc954b4e56275f54), C(700cd864e04e8aaa), C(d6ba03cbff7cc34b), C(da297d7891c9c046), C(cc954b4e56275f54), C(700cd864e04e8aaa), C(d6ba03cbff7cc34b), C(da297d7891c9c046), C(c05d2be8f8ee8114), C(7f4541cbe2ec0025), C(8f0a7a70af6ea926), C(3837ddce693781b5)}, {C(f9f05a2a892242eb), C(de00b6b2e0998460), C(f1f4bd817041497a), C(3deac49eb42a1e26), C(642f77f7c57e84b7), C(2f2c231222651e8b), C(380202ec06bdc29e), C(3deac49eb42a1e26), C(642f77f7c57e84b7), C(2f2c231222651e8b), C(380202ec06bdc29e), C(59abc4ff54765e66), C(8561ea1dddd1f742), C(9ca1f94b0d3f3875), C(b7fa93c3a9fa4ec4)}, {C(3a015cea8c3f5bdf), C(5583521b852fc3ac), C(53d5cd66029a1014), C(ac2eeca7bb04412a), C(daba45cb16ccff2b), C(ddd90b51209e414), C(d90e74ee28cb6271), C(ac2eeca7bb04412a), C(daba45cb16ccff2b), C(ddd90b51209e414), C(d90e74ee28cb6271), C(117027648ca9db68), C(29c1dba39bbcf072), C(787f6bb010a34cd9), C(e099f487e09b847)}, {C(670e43506aa1f71b), C(1cd7929573e54c05), C(cbb00a0aaba5f20a), C(f779909e3d5688d1), C(88211b9117678271), C(59f44f73759a8bc6), C(ef14f73c405123b4), C(f779909e3d5688d1), C(88211b9117678271), C(59f44f73759a8bc6), C(ef14f73c405123b4), C(78775601f11186f), C(fc4641d676fbeed9), C(669ca96b5a2ae5b), C(67b5f0d072025f8d)}, {C(977bb79b58bbd984), C(26d45cfcfb0e9756), C(df8885db518d5f6a), C(6a1d2876488bed06), C(ae35d83c3afb5769), C(33667427d99f9f4e), C(d84c31c17495e3ba), C(6a1d2876488bed06), C(ae35d83c3afb5769), C(33667427d99f9f4e), C(d84c31c17495e3ba), C(31357cded7495ffc), C(295e2eefcd383a2e), C(25063ef4a24c29ae), C(88c694170fcbf0b7)}, {C(e6264fbccd93a530), C(c92f420494e99a7d), C(c14001a298cf976), C(5c8685fee2e4ce55), C(228c49268d6a4345), C(3b04ee2861baec6d), C(7334878a00e96e72), C(5c8685fee2e4ce55), C(228c49268d6a4345), C(3b04ee2861baec6d), C(7334878a00e96e72), C(7317164b2ce711bb), C(e645447e363e8ca1), C(d326d129ad7b4e7f), C(58b9b76d5c2eb272)}, {C(54e4d0cab7ec5c27), C(31ca61d2262a9acc), C(30bd3a50d8082ff6), C(46b3b963bf7e2847), C(b319d04e16ad10b0), C(76c8dd82e6f5a0eb), C(2070363cefb488bc), C(46b3b963bf7e2847), C(b319d04e16ad10b0), C(76c8dd82e6f5a0eb), C(2070363cefb488bc), C(6f9dbacb2bdc556d), C(88a5fb0b293c1e22), C(cb131d9b9abd84b7), C(21db6f0e147a0040)}, {C(882a598e98cf5416), C(36c8dca4a80d9788), C(c386480f07591cfe), C(5b517bcf2005fd9c), C(b9b8f8e5f90e7025), C(2a833e6199e21708), C(bcb7549de5fda812), C(5b517bcf2005fd9c), C(b9b8f8e5f90e7025), C(2a833e6199e21708), C(bcb7549de5fda812), C(44fc96a3cafa1c34), C(fb7724d4899ec7c7), C(4662e3b87df93e13), C(bcf22545acbcfd4e)}, {C(7c37a5376c056d55), C(e0cce8936a06b6f6), C(d32f933fdbec4c7d), C(7ac50423e2be4703), C(546d4b42340d6dc7), C(624f56ee027f12bf), C(5f7f65d1e90c30f9), C(7ac50423e2be4703), C(546d4b42340d6dc7), C(624f56ee027f12bf), C(5f7f65d1e90c30f9), C(d6f15c19625d2621), C(c7afd12394f24b50), C(2c6adde5d249bcd0), C(6c857e6aa07b9fd2)}, {C(21c5e9616f24be97), C(ba3536c86e4b6fe9), C(6d3a65cfe3a9ae06), C(2113903ebd760a31), C(e561f76a5eac8beb), C(86b5b3e76392e166), C(68c8004ccc53e049), C(2113903ebd760a31), C(e561f76a5eac8beb), C(86b5b3e76392e166), C(68c8004ccc53e049), C(b51a28fe4251dd79), C(fd9c2d4d2a84c3c7), C(5bf2ec8a470d2553), C(135a52cdc76241c9)}, {C(a6eaefe74fa7d62b), C(cb34669c751b10eb), C(80da952ad8abd5f3), C(3368262b0e172d82), C(1d51f6c982476285), C(4497675ac57228a9), C(2a71766a71d0b83f), C(3368262b0e172d82), C(1d51f6c982476285), C(4497675ac57228a9), C(2a71766a71d0b83f), C(79ad94d1e9c1dedd), C(cbf1a1c9f23bfa40), C(3ebf24e068cd638b), C(be8e63472edfb462)}, {C(764af88ed4b0b828), C(36946775f20457ce), C(d4bc88ac8281c22e), C(3b2104d68dd9ac02), C(2eca14fcdc0892d0), C(7913b0c09329cd47), C(9373f458938688c8), C(3b2104d68dd9ac02), C(2eca14fcdc0892d0), C(7913b0c09329cd47), C(9373f458938688c8), C(b4448f52a5bf9425), C(9f8c8b90b61ed532), C(78f6774f48e72961), C(e47c00bf9c1206f4)}, {C(5f55a694fb173ea3), C(7db02b80ef5a918b), C(d87ff079f476ca3a), C(1d11117374e0da3), C(744bfbde42106439), C(93a99fab10bb1789), C(246ba292a85d8d7c), C(1d11117374e0da3), C(744bfbde42106439), C(93a99fab10bb1789), C(246ba292a85d8d7c), C(e5bd7838e9edd53a), C(d9c0b104c79d9019), C(ee3dcc7a8e565de5), C(619c9e0a9cf3596d)}, {C(86d086738b0a7701), C(d2402313a4280dda), C(b327aa1a25278366), C(49efdde5d1f98163), C(cbcffcee90f22824), C(951aec1daeb79bab), C(7055e2c70d2eeb4c), C(49efdde5d1f98163), C(cbcffcee90f22824), C(951aec1daeb79bab), C(7055e2c70d2eeb4c), C(1fc0de9399bacb96), C(dab7bbe67901959e), C(375805eccf683ef0), C(bbb6f465c4bae04e)}, {C(acfc8be97115847b), C(c8f0d887bf8d9d1), C(e698fbc6d39bf837), C(61fd1d6b13c1ea77), C(527ed97ff4ae24f0), C(af51a9ebb322c0), C(14f7c25058864825), C(61fd1d6b13c1ea77), C(527ed97ff4ae24f0), C(af51a9ebb322c0), C(14f7c25058864825), C(f40b2bbeaf9f021d), C(80d827160dfdc2d2), C(77baea2e3650486e), C(5de2d256740a1a97)}, {C(dc5ad3c016024d4), C(a0235e954da1a152), C(6daa8a4ed194cc43), C(185e650afc8d39f8), C(adba03a4d40de998), C(9975c776b499b26f), C(9770c59368a43a2), C(185e650afc8d39f8), C(adba03a4d40de998), C(9975c776b499b26f), C(9770c59368a43a2), C(d2776f0cf0e4f66c), C(38eaaabfb743f7f6), C(c066f03d959b3f07), C(9d91c2d52240d546)}, {C(a0e91182f03277f7), C(15c6ebef7376556), C(516f887657ab5a), C(f95050524c7f4b84), C(460dcebbaaa09ae3), C(a9f7a9f0b1b2a961), C(5f8dc5e198e34539), C(f95050524c7f4b84), C(460dcebbaaa09ae3), C(a9f7a9f0b1b2a961), C(5f8dc5e198e34539), C(9c49227ffcff07cb), C(a29388e9fcb794c8), C(475867910d110cba), C(8c9a5cee480b5bac)}, {C(767f1dbd1dba673b), C(1e466a3848a5b01e), C(483eadef1347cd6e), C(a67645c72f54fe24), C(c7a5562c69bd796b), C(e14201a35b55e4a6), C(b3a6d89f19d8f774), C(a67645c72f54fe24), C(c7a5562c69bd796b), C(e14201a35b55e4a6), C(b3a6d89f19d8f774), C(bb4d607ac22bebe5), C(792030edeaa924e0), C(138730dcb60f7e32), C(699d9dcc326c72dc)}, {C(a5e30221500dcd53), C(3a1058d71c9fad93), C(510520710c6444e8), C(a6a5e60c2c1d0108), C(45c8ea4e14bf8c6b), C(213a7235416b86df), C(c186072f80d56ad3), C(a6a5e60c2c1d0108), C(45c8ea4e14bf8c6b), C(213a7235416b86df), C(c186072f80d56ad3), C(2e7be098db59d832), C(d5fa382f3717a0ee), C(b168b26921d243d), C(61601a60c2addfbb)}, {C(ebaed82e48e18ce4), C(cfe6836b65ebe7c7), C(504d9d388684d449), C(bd9c744ee9e3308e), C(faefbb8d296b65d4), C(eba051fe2404c25f), C(250c8510b8931f87), C(bd9c744ee9e3308e), C(faefbb8d296b65d4), C(eba051fe2404c25f), C(250c8510b8931f87), C(3c4a49150dc5676f), C(6c28793c565345c4), C(9df6dd8829a6d8fb), C(760d3a023fab72e7)}, {C(ffa50913362b118d), C(626d52251a8ec3e0), C(76ce4b9dde2e8c5e), C(fc57418d92e52355), C(6b46c559e67a063), C(3f5c269e10690c5c), C(6870de8d49e65349), C(fc57418d92e52355), C(6b46c559e67a063), C(3f5c269e10690c5c), C(6870de8d49e65349), C(88737e5c672de296), C(ca71fca5f4c4f1ce), C(42fca3fa7f60e031), C(4a70246d0d4c2bd8)}, {C(256186bcda057f54), C(fb059b012049fd8e), C(304e07418b5f739b), C(3e166f9fac2eec0b), C(82bc11707ec4a7a4), C(e29acd3851ce36b6), C(9765ca9323d30046), C(3e166f9fac2eec0b), C(82bc11707ec4a7a4), C(e29acd3851ce36b6), C(9765ca9323d30046), C(dab63e7790017f7c), C(b9559988bff0f170), C(48d9ef8aea13eee8), C(e31e47857c511ec2)}, {C(382b15315e84f28b), C(f9a2578b79590b72), C(708936af6d4450e8), C(76a9d4843df75c1c), C(2c33447da3f2c70a), C(5e4dcf2eaeace0d6), C(2ae1727aa7220634), C(76a9d4843df75c1c), C(2c33447da3f2c70a), C(5e4dcf2eaeace0d6), C(2ae1727aa7220634), C(a122f6b52e1130ba), C(a17ae9a21f345e91), C(ff67313f1d0906a9), C(bb16dc0acd6ebecc)}, {C(9983a9cc5576d967), C(29e37689a173109f), C(c526073a91f2808c), C(fe9a9d4a799cf817), C(7ca841999012c0d1), C(8b3abfa4bd2aa28e), C(4ed49274526602eb), C(fe9a9d4a799cf817), C(7ca841999012c0d1), C(8b3abfa4bd2aa28e), C(4ed49274526602eb), C(40995df99063fe23), C(7f51b7ceded05144), C(743c89732b265bf2), C(10c8e1fd835713fd)}, {C(c2c58a843f733bdb), C(516c47c97b4ba886), C(abc3cae0339517db), C(be29af0dad5c9d27), C(70f802599d97fe08), C(23af3f67d941e52b), C(a031edd8b3a008fb), C(be29af0dad5c9d27), C(70f802599d97fe08), C(23af3f67d941e52b), C(a031edd8b3a008fb), C(43431336b198f8fd), C(7c4b60284e1c2245), C(51ee580ddabae1b3), C(ca99bd13845d8f7f)}, {C(648ff27fabf93521), C(d7fba33cbc153035), C(3dbcdcf87ad06c9e), C(52ddbdc9dfd26990), C(d46784cd2aeabb28), C(bd3a15e5e4eb7177), C(b5d7632e19a2cd), C(52ddbdc9dfd26990), C(d46784cd2aeabb28), C(bd3a15e5e4eb7177), C(b5d7632e19a2cd), C(8007450fa355dc04), C(41ca59f64588bb5c), C(66f2ca6b7487499d), C(8098716530db9bea)}, {C(99be55475dcb3461), C(d94ffa462f6ba8dc), C(dbab2b456bdf13bb), C(f28f496e15914b2d), C(1171ce20f49cc87d), C(1b5f514bc1b377a9), C(8a02cb12ec4d6397), C(f28f496e15914b2d), C(1171ce20f49cc87d), C(1b5f514bc1b377a9), C(8a02cb12ec4d6397), C(1c6540740c128d79), C(d085b67114969f41), C(af8c1988085306f3), C(4681f415d9ce8038)}, {C(e16fbb9303dd6d92), C(4d92b99dd164db74), C(3f98f2c9da4f5ce3), C(c65b38c5a47eeed0), C(5c5301c8ee3923a6), C(51bf9f9eddec630e), C(b1cbf1a68be455c2), C(c65b38c5a47eeed0), C(5c5301c8ee3923a6), C(51bf9f9eddec630e), C(b1cbf1a68be455c2), C(c356f5f98499bdb8), C(d897df1ad63fc1d4), C(9bf2a3a69982e93a), C(a2380d43e271bcc8)}, {C(4a57a4899834e4c0), C(836c4df2aac32257), C(cdb66b29e3e12147), C(c734232cbda1eb4c), C(30a3cffff6b9dda0), C(d199313e17cca1ed), C(594d99e4c1360d82), C(c734232cbda1eb4c), C(30a3cffff6b9dda0), C(d199313e17cca1ed), C(594d99e4c1360d82), C(ccc37662829a65b7), C(cae30ff4d2343ce9), C(54da907f7aade4fa), C(5d6e4a0272958922)}, {C(f658958cdf49f149), C(de8e4a622b7a16b), C(a227ebf448c80415), C(3de9e38b3a369785), C(84d160d688c573a9), C(8f562593add0ad54), C(4446b762cc34e6bf), C(3de9e38b3a369785), C(84d160d688c573a9), C(8f562593add0ad54), C(4446b762cc34e6bf), C(2f795f1594c7d598), C(29e05bd1e0dceaff), C(a9a88f2962b49589), C(4b9c86c141ac120b)}, {C(ae1befc65d3ea04d), C(cfd9bc0388c8fd00), C(522f2e1f6cdb31af), C(585447ebe078801a), C(14a31676ec4a2cbd), C(b274e7e6af86a5e1), C(2d487019570bedce), C(585447ebe078801a), C(14a31676ec4a2cbd), C(b274e7e6af86a5e1), C(2d487019570bedce), C(ea1dc9ef3c7b2fcc), C(bde99d4af2f4ee8c), C(64e4c43cd7c43442), C(9b5262ee2eed2f99)}, {C(2fc8f9fc5946296d), C(6a2b94c6765ebfa2), C(f4108b8c79662fd8), C(3a48de4a1e994623), C(6318e6e1ff7bc092), C(84aee2ea26a048fb), C(cf3c393fdad7b184), C(3a48de4a1e994623), C(6318e6e1ff7bc092), C(84aee2ea26a048fb), C(cf3c393fdad7b184), C(28b265bd8985a71e), C(bd3d97dbd76d89a5), C(b04ba1623c0937d), C(b6de821229693515)}, {C(efdb4dc26e84dce4), C(9ce45b6172dffee8), C(c15ad8c8bcaced19), C(f10cc2bcf0475411), C(1126f457c160d8f5), C(34c67f6ea249d5cc), C(3ab7633f4557083), C(f10cc2bcf0475411), C(1126f457c160d8f5), C(34c67f6ea249d5cc), C(3ab7633f4557083), C(3b2e4d8611a03bd7), C(3103d6e63d71c3c9), C(43a56a0b93bb9d53), C(50aa3ae25803c403)}, {C(e84a123b3e1b0c91), C(735cc1d493c5e524), C(287030af8f4ac951), C(fb46abaf4713dda0), C(e8835b9a08cf8cb2), C(3b85a40e6bee4cce), C(eea02a3930757200), C(fb46abaf4713dda0), C(e8835b9a08cf8cb2), C(3b85a40e6bee4cce), C(eea02a3930757200), C(fe7057d5fb18ee87), C(723d258b36eada2a), C(67641393692a716c), C(c8539a48dae2e539)}, {C(686c22d2863c48a6), C(1ee6804e3ddde627), C(8d66184dd34ddac8), C(35ac1bc76c11976), C(fed58f898503280d), C(ab6fcb01c630071e), C(edabf3ec7663c3c9), C(35ac1bc76c11976), C(fed58f898503280d), C(ab6fcb01c630071e), C(edabf3ec7663c3c9), C(591ec5025592b76e), C(918a77179b072163), C(25421d9db4c81e1a), C(96f1b3be51f0b548)}, {C(2c5c1c9fa0ecfde0), C(266a71b430afaec3), C(53ab2d731bd8184a), C(5722f16b15e7f206), C(35bb5922c0946610), C(b8d72c08f927f2aa), C(65f2c378cb9e8c51), C(5722f16b15e7f206), C(35bb5922c0946610), C(b8d72c08f927f2aa), C(65f2c378cb9e8c51), C(cd42fec772c2d221), C(10ccd5d7bacffdd9), C(a75ecb52192f60e2), C(a648f5fe45e5c164)}, {C(7a0ac8dd441c9a9d), C(4a4315964b7377f0), C(24092991c8f27459), C(9c6868d561691eb6), C(78b7016996f98828), C(651e072f06c9e7b7), C(fed953d1251ae90), C(9c6868d561691eb6), C(78b7016996f98828), C(651e072f06c9e7b7), C(fed953d1251ae90), C(7a4d19fdd89e368c), C(d8224d83b6b9a753), C(3a93520a455ee9c9), C(159942bea42b999c)}, {C(c6f9a31dfc91537c), C(b3a250ae029272f8), C(d065fc76d79ec222), C(d2baa99749c71d52), C(5f90a2cfc2a3f637), C(79e4aca7c8bb0998), C(981633149c85c0ba), C(d2baa99749c71d52), C(5f90a2cfc2a3f637), C(79e4aca7c8bb0998), C(981633149c85c0ba), C(5ded415df904b2ee), C(d37d1fc032ebca94), C(ed5b024594967bf7), C(ed7ae636d467e961)}, {C(2d12010eaf7d8d3d), C(eaec74ccd9b76590), C(541338571d45608b), C(e97454e4191065f3), C(afb357655f2a5d1c), C(521ac1614653c130), C(c8a8cac96aa7f32c), C(e97454e4191065f3), C(afb357655f2a5d1c), C(521ac1614653c130), C(c8a8cac96aa7f32c), C(196d7f3f386dfd29), C(1dcd2da5227325cc), C(10e3b9fa712d3405), C(fdf7864ede0856c0)}, {C(f46de22b2d79a5bd), C(e3e198ba766c0a29), C(828d8c137216b797), C(bafdb732c8a29420), C(2ed0b9f4548a9ac3), C(f1ed2d5417d8d1f7), C(451462f90354d097), C(bafdb732c8a29420), C(2ed0b9f4548a9ac3), C(f1ed2d5417d8d1f7), C(451462f90354d097), C(bdd091094408851a), C(c4c1731c1ea46c2c), C(615a2348d60409a8), C(fbc2f058d5539bcc)}, {C(2ce2f3e89fa141fe), C(ac588fe6ab2b719), C(59b848c80739487d), C(423722957b566d10), C(ae4be02664998dc6), C(64017aacfa69ef80), C(28076dddbf65a40a), C(423722957b566d10), C(ae4be02664998dc6), C(64017aacfa69ef80), C(28076dddbf65a40a), C(873bc41acb810f94), C(ac0edafb574b7c0d), C(937d5d5fd95330bf), C(4ea91171e208bd7e)}, {C(8aa75419d95555dd), C(bdb046419d0bf1b0), C(aadf49f217b153da), C(c3cbbe7eb0f5e126), C(fd1809c329311bf6), C(9c26cc255714d79d), C(67093aeb89f5d8c8), C(c3cbbe7eb0f5e126), C(fd1809c329311bf6), C(9c26cc255714d79d), C(67093aeb89f5d8c8), C(265954c61009eaf7), C(a5703e8073eaf83f), C(855382b1aed9c128), C(a6652d5a53d4a008)}, {C(1fbf19dd9207e6aa), C(722834f3c5e43cb7), C(e3c13578c5a69744), C(db9120bc83472135), C(f3d9f715e669cfd5), C(63facc852f487dda), C(9f08fd85a3a78111), C(db9120bc83472135), C(f3d9f715e669cfd5), C(63facc852f487dda), C(9f08fd85a3a78111), C(6c1e5c694b51b7ca), C(bbceb2e47d44f6a1), C(2eb472efe06f8330), C(1844408e2bb87ee)}, {C(6f11f9c1131f1182), C(6f90740debc7bad2), C(8d6e4e2d46ee614b), C(403e3793f0805ac3), C(6278da3d8667a055), C(98eceadb4f237978), C(4daa96284c847b0), C(403e3793f0805ac3), C(6278da3d8667a055), C(98eceadb4f237978), C(4daa96284c847b0), C(ab119ac9f803d770), C(ab893fe847208376), C(f9d9968ae4472ac3), C(b149ff3b35874201)}, {C(92e896d8bfdebdb5), C(2d5c691a0acaeba7), C(377d7f86b7cb2f8b), C(b8a0738135dde772), C(57fb6c9033fc5f35), C(20e628f266e63e1), C(1ad6647eaaa153a3), C(b8a0738135dde772), C(57fb6c9033fc5f35), C(20e628f266e63e1), C(1ad6647eaaa153a3), C(10005c85a89e601a), C(cc9088ed03a78e4a), C(c8d3049b8c0d26a1), C(26e8c0e936cf8cce)}, {C(369ba54df3c534d1), C(972c7d2be5f62834), C(112c8d0cfcc8b1e), C(bcddd22a14192678), C(446cf170a4f05e72), C(c9e992c7a79ce219), C(fa4762e60a93cf84), C(bcddd22a14192678), C(446cf170a4f05e72), C(c9e992c7a79ce219), C(fa4762e60a93cf84), C(b2e11a375a352f), C(a70467d0fd624cf1), C(776b638246febf88), C(e7d1033f7faa39b5)}, {C(bcc4229e083e940e), C(7a42ebe9e8f526b5), C(bb8d1f389b0769ee), C(ae6790e9fe24c57a), C(659a16feab53eb5), C(6fd4cfade750bf16), C(31b1acd328815c81), C(ae6790e9fe24c57a), C(659a16feab53eb5), C(6fd4cfade750bf16), C(31b1acd328815c81), C(8a711090a6ccfd44), C(363240c31681b80e), C(ad791f19de0b07e9), C(d512217d21c7c370)}, {C(17c648f416fb15ca), C(fe4d070d14d71a1d), C(ff22eac66f7eb0d3), C(fa4c10f92facc6c7), C(94cad9e4daecfd58), C(6ffcf829a275d7ef), C(2a35d2436894d549), C(fa4c10f92facc6c7), C(94cad9e4daecfd58), C(6ffcf829a275d7ef), C(2a35d2436894d549), C(c9ea25549513f5a), C(93f7cf06df2d0206), C(ef0da319d38fe57c), C(f715dc84df4f4a75)}, {C(8b752dfa2f9fa592), C(ca95e87b662fe94d), C(34da3aadfa49936d), C(bf1696df6e61f235), C(9724fac2c03e3859), C(d9fd1463b07a8b61), C(f8e397251053d8ca), C(bf1696df6e61f235), C(9724fac2c03e3859), C(d9fd1463b07a8b61), C(f8e397251053d8ca), C(c6d26d868c9e858e), C(2f4a1cb842ed6105), C(6cc48927bd59d1c9), C(469e836d0b7901e1)}, {C(3edda5262a7869bf), C(a15eab8c522050c9), C(ba0853c48707207b), C(4d751c1a836dcda3), C(9747a6e96f1dd82c), C(3c986fc5c9dc9755), C(a9d04f3a92844ecd), C(4d751c1a836dcda3), C(9747a6e96f1dd82c), C(3c986fc5c9dc9755), C(a9d04f3a92844ecd), C(2da9c6cede185e36), C(fae575ef03f987d6), C(b4a6a620b2bee11a), C(8acba91c5813c424)}, {C(b5776f9ceaf0dba2), C(546eee4cee927b0a), C(ce70d774c7b1cf77), C(7f707785c2d807d7), C(1ea8247d40cdfae9), C(4945806eac060028), C(1a14948790321c37), C(7f707785c2d807d7), C(1ea8247d40cdfae9), C(4945806eac060028), C(1a14948790321c37), C(ba3327bf0a6ab79e), C(54e2939592862de8), C(b7d4651234fa11c7), C(d122970552454def)}, {C(313161f3ce61ec83), C(c6c5acb78303987d), C(f00761c6c6e44cee), C(ea660b39d2528951), C(e84537f81a44826a), C(b850bbb69593c26d), C(22499793145e1209), C(ea660b39d2528951), C(e84537f81a44826a), C(b850bbb69593c26d), C(22499793145e1209), C(4c61b993560bbd58), C(636d296abe771743), C(f1861b17b8bc3146), C(cd5fca4649d30f8a)}, {C(6e23080c57f4bcb), C(5f4dad6078644535), C(f1591bc445804407), C(46ca76959d0d4824), C(200b16bb4031e6a5), C(3d0e4718ed5363d2), C(4c8cfcc96382106f), C(46ca76959d0d4824), C(200b16bb4031e6a5), C(3d0e4718ed5363d2), C(4c8cfcc96382106f), C(8d6258d795b8097b), C(23ae7cd1cab4b141), C(cbe74e8fd420afa), C(d553da4575629c63)}, {C(a194c120f440fd48), C(ac0d985eef446947), C(5df9fa7d97244438), C(fce2269035535eba), C(2d9b4b2010a90960), C(2b0952b893dd72f0), C(9a51e8462c1111de), C(fce2269035535eba), C(2d9b4b2010a90960), C(2b0952b893dd72f0), C(9a51e8462c1111de), C(8682b5e0624432a4), C(de8500edda7c67a9), C(4821b171f562c5a2), C(ecb17dea1002e2df)}, {C(3c78f67ee87b62fe), C(274c83c73f20f662), C(25a94c36d3763332), C(7e053f1b873bed61), C(d1c343547cd9c816), C(4deee69b90a52394), C(14038f0f3128ca46), C(7e053f1b873bed61), C(d1c343547cd9c816), C(4deee69b90a52394), C(14038f0f3128ca46), C(ebbf836e38c70747), C(c3c1077b9a7598d0), C(e73c720a27b07ba7), C(ec57f8a9a75af4d9)}, {C(b7d2aee81871e3ac), C(872ac6546cc94ff2), C(a1b0d2f507ad2d8f), C(bdd983653b339252), C(c02783d47ab815f8), C(36c5dc27d64d776c), C(5193988eea7df808), C(bdd983653b339252), C(c02783d47ab815f8), C(36c5dc27d64d776c), C(5193988eea7df808), C(8d8cca9c605cdb4a), C(334904fd32a1f934), C(dbfc15742057a47f), C(f3f92db42ec0cba1)}, {C(41ec0382933e8f72), C(bd5e52d651bf3a41), C(cbf51a6873d4b29e), C(1c8c650bfed2c546), C(9c9085c070350c27), C(e82305be3bded854), C(cf56326bab3d685d), C(1c8c650bfed2c546), C(9c9085c070350c27), C(e82305be3bded854), C(cf56326bab3d685d), C(f94db129adc6cecc), C(1f80871ec4b35deb), C(c0dc1a4c74d63d0), C(d3cac509f998c174)}, {C(7fe4e777602797f0), C(626e62f39f7c575d), C(d15d6185215fee2f), C(f82ef80641514b70), C(e2702de53389d34e), C(9950592b7f2da8d8), C(d6b960bf3503f893), C(f82ef80641514b70), C(e2702de53389d34e), C(9950592b7f2da8d8), C(d6b960bf3503f893), C(95de69e4f131a9b), C(ee6f56eeff9cdefa), C(28f4f86c2b856b72), C(b73d2decaac56b5b)}, {C(aa71127fd91bd68a), C(960f6304500f8069), C(5cfa9758933beba8), C(dcbbdeb1f56b0ac5), C(45164c603d084ce4), C(85693f4ef7e34314), C(e3a3e3a5ec1f6252), C(dcbbdeb1f56b0ac5), C(45164c603d084ce4), C(85693f4ef7e34314), C(e3a3e3a5ec1f6252), C(91f4711c59532bab), C(5e5a61d26f97200b), C(ffa65a1a41da5883), C(5f0e712235371eef)}, {C(677b53782a8af152), C(90d76ef694361f72), C(fa2cb9714617a9e0), C(72c8667cc1e45aa9), C(3a0aa035bbcd1ef6), C(588e89b034fde91b), C(f62e4e1d81c1687), C(72c8667cc1e45aa9), C(3a0aa035bbcd1ef6), C(588e89b034fde91b), C(f62e4e1d81c1687), C(1ea81508efa11e09), C(1cf493a4dcd49aad), C(8217d0fbe8226130), C(607b979c0eb297dd)}, {C(8f97bb03473c860f), C(e23e420f9a32e4a2), C(3432c97895fea7cf), C(69cc85dac0991c6c), C(4a6c529f94e9c36a), C(e5865f8da8c887df), C(27e8c77da38582e0), C(69cc85dac0991c6c), C(4a6c529f94e9c36a), C(e5865f8da8c887df), C(27e8c77da38582e0), C(8e60596b4e327dbc), C(955cf21baa1ddb18), C(c24a8eb9360370aa), C(70d75fd116c2cab1)}, {C(fe50ea9f58e4de6f), C(f0a085b814230ce7), C(89407f0548f90e9d), C(6c595ea139648eba), C(efe867c726ab2974), C(26f48ecc1c3821cf), C(55c63c1b3d0f1549), C(6c595ea139648eba), C(efe867c726ab2974), C(26f48ecc1c3821cf), C(55c63c1b3d0f1549), C(552e5f78e1d87a69), C(c9bfe2747a4eedf0), C(d5230acb6ef95a1), C(1e812f3c0d9962bd)}, {C(56eb0fcb9852bd27), C(c817b9a578c7b12), C(45427842795bfa84), C(8dccc5f52a65030c), C(f89ffa1f4fab979), C(7d94da4a61305982), C(1ba6839d59f1a07a), C(8dccc5f52a65030c), C(f89ffa1f4fab979), C(7d94da4a61305982), C(1ba6839d59f1a07a), C(e0162ec1f40d583e), C(6abf0b85552c7c33), C(f14bb021a875867d), C(c12a569c8bfe3ba7)}, {C(6be2903d8f07af90), C(26aaf7b795987ae8), C(44a19337cb53fdeb), C(f0e14afc59e29a3a), C(a4d0084172a98c0d), C(275998a345d04f0f), C(db73704d81680e8d), C(f0e14afc59e29a3a), C(a4d0084172a98c0d), C(275998a345d04f0f), C(db73704d81680e8d), C(351388cf7529b1b1), C(a3155d0237571da5), C(355231b516da2890), C(263c5a3d498c1cc)}, {C(58668066da6bfc4), C(a4ea2eb7212df3dd), C(481f64f7ca220524), C(11b3b649b1cea339), C(57f4ad5b54d71118), C(feeb30bec803ab49), C(6ed9bcc1973d9bf9), C(11b3b649b1cea339), C(57f4ad5b54d71118), C(feeb30bec803ab49), C(6ed9bcc1973d9bf9), C(bf2859d9964a70c8), C(d31ab162ca25f24e), C(70349336ff55d5d5), C(9a2fa97115ef4409)}, {C(2d04d1fbab341106), C(efe0c5b2878b444c), C(882a2a889b5e8e71), C(18cc96be09e5455), C(1ad58fd26919e409), C(76593521c4a0006b), C(f1361f348fa7cbfb), C(18cc96be09e5455), C(1ad58fd26919e409), C(76593521c4a0006b), C(f1361f348fa7cbfb), C(205bc68e660b0560), C(74360e11f9fc367e), C(a88b7b0fa86caf), C(a982d749b30d4e4c)}, {C(d366b37bcd83805b), C(a6d16fea50466886), C(cb76dfa8eaf74d70), C(389c44e423749aa), C(a30d802bec4e5430), C(9ac1279f92bea800), C(686ef471c2624025), C(389c44e423749aa), C(a30d802bec4e5430), C(9ac1279f92bea800), C(686ef471c2624025), C(2c21a72f8e3a3423), C(df5ab83f0918646a), C(cd876e0cb4df80fa), C(5abbb92679b3ea36)}, {C(bbb9bc819ab65946), C(25e0c756c95803e2), C(82a73a1e1cc9bf6a), C(671b931b702519a3), C(61609e7dc0dd9488), C(9cb329b8cab5420), C(3c64f8ea340096ca), C(671b931b702519a3), C(61609e7dc0dd9488), C(9cb329b8cab5420), C(3c64f8ea340096ca), C(1690afe3befd3afb), C(4d3c18a846602740), C(a6783133a31dd64d), C(ecf4665e6bc76729)}, {C(8e994eac99bbc61), C(84de870b6f3c114e), C(150efc95ce7b0cd2), C(4c5d48abf41185e3), C(86049a83c7cdcc70), C(ad828ff609277b93), C(f60fe028d582ccc7), C(4c5d48abf41185e3), C(86049a83c7cdcc70), C(ad828ff609277b93), C(f60fe028d582ccc7), C(464e0b174da0cbd4), C(eadf1df69041b06e), C(48cb9c96a9df1cdc), C(b7e5ee62809223a1)}, {C(364cabf6585e2f7d), C(3be1cc452509807e), C(1236ce85788680d4), C(4cea77c54fc3583a), C(9a2a64766fd77614), C(63e6c9254b5dc4db), C(26af12ba3bf5988e), C(4cea77c54fc3583a), C(9a2a64766fd77614), C(63e6c9254b5dc4db), C(26af12ba3bf5988e), C(4a821aca3ffa26a1), C(99aa9aacbb3d08e3), C(619ac77b52e8a823), C(68c745a1ce4b7adb)}, {C(e878e2200893d775), C(76b1e0a25867a803), C(9c14d6d91f5ae2c5), C(ac0ffd8d64e242ed), C(e1673ee2dd997587), C(8cdf3e9369d61003), C(c37c9a5258b98eba), C(ac0ffd8d64e242ed), C(e1673ee2dd997587), C(8cdf3e9369d61003), C(c37c9a5258b98eba), C(f252b2e7b67dd012), C(47fc1eb088858f28), C(59c42e4af1353223), C(e05b6c61c19eb26e)}, {C(6f6a014b9a861926), C(269e13a120277867), C(37fc8a181e78711b), C(33dd054c41f3aef2), C(4fc8ab1a2ef3da7b), C(597178c3756a06dc), C(748f8aadc540116f), C(33dd054c41f3aef2), C(4fc8ab1a2ef3da7b), C(597178c3756a06dc), C(748f8aadc540116f), C(78e3be34de99461e), C(28b7b60d90dddab4), C(e47475fa9327a619), C(88b17629e6265924)}, {C(da52b64212e8149b), C(121e713c1692086f), C(f3d63cfa03850a02), C(f0d82bafec3c564c), C(37dece35b549a1ce), C(5fb28f6078c4a2bd), C(b69990b7d9405710), C(f0d82bafec3c564c), C(37dece35b549a1ce), C(5fb28f6078c4a2bd), C(b69990b7d9405710), C(3af5223132071100), C(56d5bb35f3bb5d2a), C(fcad4a4d5d3a1bc7), C(f17bf3d8853724d0)}, {C(1100f797ce53a629), C(f528c6614a1a30c2), C(30e49fb56bec67fa), C(f991664844003cf5), C(d54f5f6c8c7cf835), C(ca9cc4437c591ef3), C(d5871c77cf8fb424), C(f991664844003cf5), C(d54f5f6c8c7cf835), C(ca9cc4437c591ef3), C(d5871c77cf8fb424), C(5cf90f1e617b750c), C(1648f825ab986232), C(936cf225126a60), C(90fa5311d6f2445c)}, {C(4f00655b76e9cfda), C(9dc5c707772ed283), C(b0f885f1e01927ec), C(6e4d6843289dfb47), C(357b41c6e5fd561f), C(491e386bacb6df3c), C(86be1b64ecd9945c), C(6e4d6843289dfb47), C(357b41c6e5fd561f), C(491e386bacb6df3c), C(86be1b64ecd9945c), C(be9547e3cfd85fae), C(f9e26ac346b430a8), C(38508b84b0e68cff), C(a28d49dbd5562703)}, {C(d970198b6ca854db), C(92e3d1786ae556a0), C(99a165d7f0d85cf1), C(6548910c5f668397), C(a5c8d20873e7de65), C(5b7c4ecfb8e38e81), C(6aa50a5531dad63e), C(6548910c5f668397), C(a5c8d20873e7de65), C(5b7c4ecfb8e38e81), C(6aa50a5531dad63e), C(ab903d724449e003), C(ea3cc836c28fef88), C(4b250d6c7200949d), C(13a110654fa916c0)}, {C(76c850754f28803), C(a4bffed2982cb821), C(6710e352247caf63), C(d9cbf5b9c31d964e), C(25c8f890178b97ae), C(e7c46064676cde9f), C(d8bb5eeb49c06336), C(d9cbf5b9c31d964e), C(25c8f890178b97ae), C(e7c46064676cde9f), C(d8bb5eeb49c06336), C(962b35ae89d5f4c1), C(c49083801ac2c21), C(2db46ddec36ff33b), C(da48992ab8da284)}, {C(9c98da9763f0d691), C(f5437139a3d40401), C(6f493c26c42f91e2), C(e857e4ab2d124d5), C(6417bb2f363f36da), C(adc36c9c92193bb1), C(d35bd456172df3df), C(e857e4ab2d124d5), C(6417bb2f363f36da), C(adc36c9c92193bb1), C(d35bd456172df3df), C(577da94064d3a3d6), C(23f13d7532ea496a), C(6e09392d80b8e85b), C(2e05ff6f23663892)}, {C(22f8f6869a5f325), C(a0e7a96180772c26), C(cb71ea6825fa3b77), C(39d3dec4e718e903), C(900c9fbdf1ae2428), C(305301da2584818), C(c6831f674e1fdb1f), C(39d3dec4e718e903), C(900c9fbdf1ae2428), C(305301da2584818), C(c6831f674e1fdb1f), C(8ad0e38ffe71babf), C(554ac85a8a837e64), C(9900c582cf401356), C(169f646b01ed7762)}, {C(9ae7575fc14256bb), C(ab9c5a397fabc1b3), C(1d3f582aaa724b2e), C(94412f598ef156), C(15bf1a588f25b327), C(5756646bd68ce022), C(f062a7d29be259a5), C(94412f598ef156), C(15bf1a588f25b327), C(5756646bd68ce022), C(f062a7d29be259a5), C(aa99c683cfb60b26), C(9e3b7d4b17f91273), C(301d3f5422dd34cf), C(53d3769127253551)}, {C(540040e79752b619), C(670327e237c88cb3), C(50962f261bcc31d9), C(9a8ea2b68b2847ec), C(bc24ab7d4cbbda31), C(df5aff1cd42a9b57), C(db47d368295f4628), C(9a8ea2b68b2847ec), C(bc24ab7d4cbbda31), C(df5aff1cd42a9b57), C(db47d368295f4628), C(9a66c221d1bf3f3), C(7ae74ee1281de8ee), C(a4e173e2c787621f), C(5b51062d10ae472)}, {C(34cbf85722d897b1), C(6208cb2a0fff4eba), C(e926cbc7e86f544e), C(883706c4321efee0), C(8fd5d3d84c7827e4), C(a5c80e455a7ccaaa), C(3515f41164654591), C(883706c4321efee0), C(8fd5d3d84c7827e4), C(a5c80e455a7ccaaa), C(3515f41164654591), C(2c08bfc75dbfd261), C(6e9eadf14f8c965e), C(18783f5770cd19a3), C(a6c7f2f1aa7b59ea)}, {C(46afa66366bf5989), C(aa0d424ac649008b), C(97a9108b3cd9c5c9), C(6ca08e09227a9630), C(8b11f73a8e5b80eb), C(2391bb535dc7ce02), C(e43e2529cf36f4b9), C(6ca08e09227a9630), C(8b11f73a8e5b80eb), C(2391bb535dc7ce02), C(e43e2529cf36f4b9), C(c9bd6d82b7a73d9d), C(b2ed9bae888447ac), C(bd22bb13af0cd06d), C(62781441785b355b)}, {C(e15074b077c6e560), C(7c8f2173fcc34afa), C(8aad55bc3bd38370), C(d407ecdbfb7cb138), C(642442eff44578af), C(d3e9fdaf71a5b79e), C(c87c53eda46aa860), C(d407ecdbfb7cb138), C(642442eff44578af), C(d3e9fdaf71a5b79e), C(c87c53eda46aa860), C(8462310a2c76ff51), C(1bc17a2e0976665e), C(6ec446b13b4d79cf), C(388c7a904b4264c1)}, {C(9740b2b2d6d06c6), C(e738265f9de8dafc), C(fdc947c1fca8be9e), C(d6936b41687c1e3d), C(a1a2deb673345994), C(91501e58b17168bd), C(b8edee2b0b708dfc), C(d6936b41687c1e3d), C(a1a2deb673345994), C(91501e58b17168bd), C(b8edee2b0b708dfc), C(ddf4b43dafd17445), C(44015d050a04ce5c), C(1019fd9ab82c4655), C(c803aea0957bcdd1)}, {C(f1431889f2db1bff), C(85257aa1dc6bd0d0), C(1abbdea0edda5be4), C(775aa89d278f26c3), C(a542d20265e3ef09), C(933bdcac58a33090), C(c43614862666ca42), C(775aa89d278f26c3), C(a542d20265e3ef09), C(933bdcac58a33090), C(c43614862666ca42), C(4c5e54d481a9748d), C(65ce3cd0db838b26), C(9ccbb4005c7f09d2), C(e6dda9555dde899a)}, {C(e2dd273a8d28c52d), C(8cd95915fdcfd96b), C(67c0f5b1025f0699), C(cbc94668d48df4d9), C(7e3d656e49d632d1), C(8329e30cac7a61d4), C(38e6cd1e2034e668), C(cbc94668d48df4d9), C(7e3d656e49d632d1), C(8329e30cac7a61d4), C(38e6cd1e2034e668), C(41e0bce03ed9394b), C(7be48d0158b9834a), C(9ea8d5d1a976b18b), C(606c424c33617e7a)}, {C(e0f79029834cc6ac), C(f2b1dcb87cc5e94c), C(4210bc221fe5e70a), C(fd4a4301d4e2ac67), C(8f84358d25b2999b), C(6c4b7d8a5a22ccbb), C(25df606bb23c9d40), C(fd4a4301d4e2ac67), C(8f84358d25b2999b), C(6c4b7d8a5a22ccbb), C(25df606bb23c9d40), C(915298b0eaadf85b), C(5ec23cc4c6a74e62), C(d640a4ff99763439), C(1603753fb34ad427)}, {C(9dc0a29830bcbec1), C(ec4a01dbd52d96a0), C(cd49c657eff87b05), C(ea487fe948c399e1), C(f5de9b2e59192609), C(4604d9b3248b3a5), C(1929878a22c86a1d), C(ea487fe948c399e1), C(f5de9b2e59192609), C(4604d9b3248b3a5), C(1929878a22c86a1d), C(3cf6cd7c19dfa1ef), C(46e404ee4af2d726), C(613ab0588a5527b5), C(73e39385ced7e684)}, {C(d10b70dde60270a6), C(be0f3b256e23422a), C(6c601297a3739826), C(e327ffc477cd2467), C(ebebba63911f32b2), C(2c2c5c24cf4970a2), C(a3cd2c192c1b8bf), C(e327ffc477cd2467), C(ebebba63911f32b2), C(2c2c5c24cf4970a2), C(a3cd2c192c1b8bf), C(94cb02c94aaf250b), C(30ca38d5e3dac579), C(d68598a91dc597b5), C(162b050e8de2d92)}, {C(58d2459f094d075c), C(b4df247528d23251), C(355283f2128a9e71), C(d046198e4df506c2), C(c61bb9705786ae53), C(b360200380d10da8), C(59942bf009ee7bc), C(d046198e4df506c2), C(c61bb9705786ae53), C(b360200380d10da8), C(59942bf009ee7bc), C(95806d027f8d245e), C(32df87487ed9d0f4), C(e2c5bc224ce97a98), C(9a47c1e33cfb1cc5)}, {C(68c600cdd42d9f65), C(bdf0c331f039ff25), C(1354ac1d98944023), C(b5cdfc0b06fd1bd9), C(71f0ce33b183efab), C(d8ae4f9d4b949755), C(877da19d6424f6b3), C(b5cdfc0b06fd1bd9), C(71f0ce33b183efab), C(d8ae4f9d4b949755), C(877da19d6424f6b3), C(f7cc5cbf76bc6006), C(c93078f44b98efdb), C(3d482142c727e8bc), C(8e23f92e0616d711)}, {C(9fc0bd876cb975da), C(80f41015045d1ade), C(5cbf601fc55c809a), C(7d9c567075001705), C(a2fafeed0df46d5d), C(a70b82990031da8f), C(8611c76abf697e56), C(7d9c567075001705), C(a2fafeed0df46d5d), C(a70b82990031da8f), C(8611c76abf697e56), C(806911617e1ee53), C(1ce82ae909fba503), C(52df85fea9e404bd), C(dbd184e5d9a11a3e)}, {C(7b3e8c267146c361), C(c6ad095af345b726), C(af702ddc731948bd), C(7ca4c883bded44b5), C(c90beb31ee9b699a), C(2cdb4aba3d59b8a3), C(df0d4fa685e938f0), C(7ca4c883bded44b5), C(c90beb31ee9b699a), C(2cdb4aba3d59b8a3), C(df0d4fa685e938f0), C(cc0e568e91aaa382), C(70ca583a464dbea), C(b7a5859b44710e1a), C(ad141467fdf9a83a)}, {C(6c49c6b3c9dd340f), C(897c41d89af37bd1), C(52df69e0e2c68a8d), C(eec4be1f65531a50), C(bf23d928f20f1b50), C(c642009b9c593940), C(c5e59e6ca9e96f85), C(eec4be1f65531a50), C(bf23d928f20f1b50), C(c642009b9c593940), C(c5e59e6ca9e96f85), C(7fbd53343e7da499), C(dd87e7b88afbd251), C(92696e7683b9f322), C(60ff51ef02c24652)}, {C(47324327a4cf1732), C(6044753d211e1dd5), C(1ecae46d75192d3b), C(b6d6315a902807e3), C(ccc8312c1b488e5d), C(b933a7b48a338ec), C(9d6753cd83422074), C(b6d6315a902807e3), C(ccc8312c1b488e5d), C(b933a7b48a338ec), C(9d6753cd83422074), C(5714bd5c0efdc7a8), C(221585e2c88068ca), C(303342b25678904), C(8c174a03e69a76e)}, {C(1e984ef53c5f6aae), C(99ea10dac804298b), C(a3f8c241100fb14d), C(259eb3c63a9c9be6), C(f8991532947c7037), C(a16d20b3fc29cfee), C(493c2e91a775af8c), C(259eb3c63a9c9be6), C(f8991532947c7037), C(a16d20b3fc29cfee), C(493c2e91a775af8c), C(275fccf4acb08abc), C(d13fb6ea3eeaf070), C(505283e5b702b9ea), C(64c092f9f8df1901)}, {C(b88f5c9b8b854cc6), C(54fc5d39825b446), C(a12fc1546eac665d), C(ab90eb7fa58b280c), C(dda26598356aa599), C(64191d63f2586e52), C(cada0075c34e8b02), C(ab90eb7fa58b280c), C(dda26598356aa599), C(64191d63f2586e52), C(cada0075c34e8b02), C(e7de6532b691d87c), C(a28fec86e368624), C(796c280eebd0241a), C(acfcecb641fdbeee)}, {C(9fcb3fdb09e7a63a), C(7a115c9ded150112), C(e9ba629108852f37), C(9b03c7c218c192a), C(93c1dd563f46308e), C(f9553625917ea800), C(e0a52f8a5024c59), C(9b03c7c218c192a), C(93c1dd563f46308e), C(f9553625917ea800), C(e0a52f8a5024c59), C(2bb3a9e8b053e490), C(8b97936723cd8ff6), C(bf3f835246d02722), C(c8e033da88ecd724)}, {C(d58438d62089243), C(d8c19375b228e9d3), C(13042546ed96e790), C(4a42ef343514138c), C(549e62449e225cf1), C(dd8260e2808f68e8), C(69580fc81fcf281b), C(4a42ef343514138c), C(549e62449e225cf1), C(dd8260e2808f68e8), C(69580fc81fcf281b), C(fc0e30d682e87289), C(f44b784248d6107b), C(df25119527fdf209), C(cc265612588171a8)}, {C(7ea73b6b74c8cd0b), C(e07188dd9b5bf3ca), C(6ef62ff2dd008ed4), C(acd94b3038342152), C(1b0ed99c9b7ba297), C(b794a93f4c895939), C(97a60cd93021206d), C(acd94b3038342152), C(1b0ed99c9b7ba297), C(b794a93f4c895939), C(97a60cd93021206d), C(9e0c0e6da5001b07), C(5f5b817de5d2a391), C(35b8a8702acdd533), C(3bbcfef344f455)}, {C(e42ffdf6278bb21), C(59df3e5ca582ff9d), C(f3108785599dbde9), C(f78e8a2d4aba6a1d), C(700473fb0d8380fc), C(d0a0d68061ac74b2), C(11650612fa426e5a), C(f78e8a2d4aba6a1d), C(700473fb0d8380fc), C(d0a0d68061ac74b2), C(11650612fa426e5a), C(e39ceb5b2955710c), C(f559ff201f8cebaa), C(1fbc182809e829a0), C(295c7fc82fa6fb5b)}, {C(9ad37fcd49fe4aa0), C(76d40da71930f708), C(bea08b630f731623), C(797292108901a81f), C(3b94127b18fae49c), C(688247179f144f1b), C(48a507a1625d13d7), C(797292108901a81f), C(3b94127b18fae49c), C(688247179f144f1b), C(48a507a1625d13d7), C(452322aaad817005), C(51d730d973e13d44), C(c883eb30176652ea), C(8d338fd678b2404d)}, {C(27b7ff391136696e), C(60db94a18593438c), C(b5e46d79c4dafbad), C(ad56fd25a6f15289), C(68a0ec7c0179df80), C(a0aacfc36620957), C(87a0762a09e2e1c1), C(ad56fd25a6f15289), C(68a0ec7c0179df80), C(a0aacfc36620957), C(87a0762a09e2e1c1), C(d50ace99460f0be3), C(7f1fe5653ae0d999), C(3870899d9d6c22c), C(df5f952dd90d5a09)}, {C(76bd077e42692ddf), C(c14b60958c2c7a85), C(fd9f3b0b3b1e2738), C(273d2c51a8e65e71), C(ac531423f670bf34), C(7f40c6bfb8c5758a), C(5fde65b433a10b02), C(273d2c51a8e65e71), C(ac531423f670bf34), C(7f40c6bfb8c5758a), C(5fde65b433a10b02), C(dbda6c4252b0a75c), C(5d4cfd8f937b23d9), C(3895f478e1c29c9d), C(e3e7c1fd1199aec6)}, {C(81c672225442e053), C(927c3f6c8964050e), C(cb59f8f2bb36fac5), C(298f3583326fd942), C(b85602a9a2e2f97c), C(65c849bfa3191459), C(bf21329dfb496c0d), C(298f3583326fd942), C(b85602a9a2e2f97c), C(65c849bfa3191459), C(bf21329dfb496c0d), C(ea7b7b44c596aa18), C(c18bfb6e9a36d59c), C(1b55f03e8a38cc0a), C(b6a94cd47bbf847f)}, {C(37b9e308747448ca), C(513f39f5545b1bd), C(145b32114ca00f9c), C(cce24b9910eb0489), C(af4ac64668ac57d9), C(ea0e44c13a9a5d5e), C(b224fb0c680455f4), C(cce24b9910eb0489), C(af4ac64668ac57d9), C(ea0e44c13a9a5d5e), C(b224fb0c680455f4), C(a7714bbba8699be7), C(fecad6e0e0092204), C(c1ce8bd5ac247eb4), C(3993aef5c07cdca2)}, {C(dab71695950a51d4), C(9e98e4dfa07566fe), C(fab3587513b84ec0), C(2409f60f0854f305), C(b17f6e6c8ff1894c), C(62fa048551dc7ad6), C(d99f4fe2799bad72), C(2409f60f0854f305), C(b17f6e6c8ff1894c), C(62fa048551dc7ad6), C(d99f4fe2799bad72), C(4a38e7f2f4a669d3), C(53173510ca91f0e3), C(cc9096c0df860b0), C(52ed637026a4a0d5)}, {C(28630288285c747b), C(a165a5bf51aaec95), C(927d211f27370016), C(727c782893d30c22), C(742706852989c247), C(c546494c3bb5e7e2), C(1fb2a5d1570f5dc0), C(727c782893d30c22), C(742706852989c247), C(c546494c3bb5e7e2), C(1fb2a5d1570f5dc0), C(71e498804df91b76), C(4a6a5aa6f7e5621), C(871a63730d13a544), C(63f77c8f371cc2f8)}, {C(4b591ad5160b6c1b), C(e8f85ddd5a1143f7), C(377e18171476d64), C(829481773cce2cb1), C(c9d9fb4e25e4d243), C(c1fff894f0cf713b), C(69edd73ec20984b0), C(829481773cce2cb1), C(c9d9fb4e25e4d243), C(c1fff894f0cf713b), C(69edd73ec20984b0), C(7fb1132262925f4a), C(a292e214fe56794f), C(915bfee68e16f46f), C(98bcc857bb6d31e7)}, {C(7e02f7a5a97dd3df), C(9724a88ac8c30809), C(d8dee12589eeaf36), C(c61f8fa31ad1885b), C(3e3744e04485ff9a), C(939335b37f34c7a2), C(faa5de308dbbbc39), C(c61f8fa31ad1885b), C(3e3744e04485ff9a), C(939335b37f34c7a2), C(faa5de308dbbbc39), C(f5996b1be7837a75), C(4fcb12d267f5af4f), C(39be67b8cd132169), C(5c39e3819198b8a1)}, {C(ff66660873521fb2), C(d82841f7e714ce03), C(c830d273f005e378), C(66990c8c54782228), C(4f28bea83dda97c), C(6a24c64698688de0), C(69721141111da99b), C(66990c8c54782228), C(4f28bea83dda97c), C(6a24c64698688de0), C(69721141111da99b), C(d5c771fade83931b), C(8094ed75e6feb396), C(7a79d4de8efd1a2c), C(5f9e50167693e363)}, {C(ef3c4dd60fa37412), C(e8d2898c86d11327), C(8c883d860aafacfe), C(a4ace72ba19d6de5), C(4cae26627dfc5511), C(38e496de9f677b05), C(558770996e1906d6), C(a4ace72ba19d6de5), C(4cae26627dfc5511), C(38e496de9f677b05), C(558770996e1906d6), C(40df30e332ceca69), C(8f106cbd94166c42), C(332b6ab4f4c1014e), C(7c0bc3092ad850e5)}, {C(a7b07bcb1a1333ba), C(9d007956720914c3), C(4751f60ef2b15545), C(77ac4dcee10c9023), C(e90235108fa20e56), C(1d3ea38535215800), C(5ed1ccfff26bc64), C(77ac4dcee10c9023), C(e90235108fa20e56), C(1d3ea38535215800), C(5ed1ccfff26bc64), C(789a1c352bf5c61e), C(860a119056da8252), C(a6c268a238699086), C(4d70f5cccf4ef2eb)}, {C(89858fc94ee25469), C(f72193b78aeaa896), C(7dba382760727c27), C(846b72f372f1685a), C(f708db2fead5433c), C(c04e121770ee5dc), C(4619793b67d0daa4), C(846b72f372f1685a), C(f708db2fead5433c), C(c04e121770ee5dc), C(4619793b67d0daa4), C(79f80506f152285f), C(5300074926fccd56), C(7fbbff6cc418fce6), C(b908f77c676b32e4)}, {C(e6344d83aafdca2e), C(6e147816e6ebf87), C(8508c38680732caf), C(f4ce36d3a375c981), C(9d67e5572f8d7bf4), C(900d63d9ec79e477), C(5251c85ab52839a3), C(f4ce36d3a375c981), C(9d67e5572f8d7bf4), C(900d63d9ec79e477), C(5251c85ab52839a3), C(92ec4b3952e38027), C(40b2dc421a518cbf), C(661ea97b2331a070), C(8d428a4a9485179b)}, {C(3ddbb400198d3d4d), C(fe73de3ada21af5c), C(cd7df833dacd8da3), C(162be779eea87bf8), C(7d62d36edf759e6d), C(dc20f528362e37b2), C(1a902edfe4a5824e), C(162be779eea87bf8), C(7d62d36edf759e6d), C(dc20f528362e37b2), C(1a902edfe4a5824e), C(e6a258d30fa817ba), C(c5d73adf6fb196fd), C(475b7a6286a207fb), C(d35f96363e8eba95)}, {C(79d4c20cf83a7732), C(651ea0a6ab059bcd), C(94631144f363cdef), C(894a0ee0c1f87a22), C(4e682573f8b38f25), C(89803fc082816289), C(71613963a02d90e1), C(894a0ee0c1f87a22), C(4e682573f8b38f25), C(89803fc082816289), C(71613963a02d90e1), C(4c6cc0e5a737c910), C(a3765b5da16bccd9), C(8bf483c4d735ec96), C(7fd7c8ba1934afec)}, {C(5aaf0d7b669173b5), C(19661ca108694547), C(5d03d681639d71fe), C(7c422f4a12fd1a66), C(aa561203e7413665), C(e99d8d202a04d573), C(6090357ec6f1f1), C(7c422f4a12fd1a66), C(aa561203e7413665), C(e99d8d202a04d573), C(6090357ec6f1f1), C(dbfe89f01f0162e), C(49aa89da4f1e389b), C(7119a6f4514efb22), C(56593f6b4e7318d9)}, {C(35d6cc883840170c), C(444694c4f8928732), C(98500f14b8741c6), C(5021ac9480077dd), C(44c2ebc11cfb9837), C(e5d310c4b5c1d9fd), C(a577102c33ac773c), C(5021ac9480077dd), C(44c2ebc11cfb9837), C(e5d310c4b5c1d9fd), C(a577102c33ac773c), C(a00d2efd2effa3cf), C(c2c33ffcda749df6), C(d172099d3b6f2986), C(f308fe33fcd23338)}, {C(b07eead7a57ff2fe), C(c1ffe295ca7dbf47), C(ef137b125cfa8851), C(8f8eec5cde7a490a), C(79916d20a405760b), C(3c30188c6d38c43c), C(b17e3c3ff7685e8d), C(8f8eec5cde7a490a), C(79916d20a405760b), C(3c30188c6d38c43c), C(b17e3c3ff7685e8d), C(ac8aa3cd0790c4c9), C(78ca60d8bf10f670), C(26f522be4fbc1184), C(55bc7688083326d4)}, {C(20fba36c76380b18), C(95c39353c2a3477d), C(4f362902cf9117ad), C(89816ec851e3f405), C(65258396f932858d), C(b7dcaf3cc57a0017), C(b368f482afc90506), C(89816ec851e3f405), C(65258396f932858d), C(b7dcaf3cc57a0017), C(b368f482afc90506), C(88f08c74465015f1), C(94ebaf209d59099d), C(c1b7ff7304b0a87), C(56bf8235257d4435)}, {C(c7e9e0c45afeab41), C(999d95f41d9ee841), C(55ef15ac11ea010), C(cc951b8eab5885d), C(956c702c88ac056b), C(de355f324a37e3c0), C(ed09057eb60bd463), C(cc951b8eab5885d), C(956c702c88ac056b), C(de355f324a37e3c0), C(ed09057eb60bd463), C(1f44b6d04a43d088), C(53631822a26ba96d), C(90305fc2d21f8d28), C(60693a9a6093351a)}, {C(69a8e59c1577145d), C(cb04a6e309ebc626), C(9b3326a5b250e9b1), C(d805f665265fd867), C(82b2b019652c19c6), C(f0df7738353c82a6), C(6a9acf124383ca5f), C(d805f665265fd867), C(82b2b019652c19c6), C(f0df7738353c82a6), C(6a9acf124383ca5f), C(6838374508a7a99f), C(7b6719db8d3e40af), C(1a22666cf0dcb7cf), C(989a9cf7f46b434d)}, {C(6638191337226509), C(42b55e08e4894870), C(a7696f5fbd51878e), C(433bbdd27481d85d), C(ee32136b5a47bbec), C(769a77f346d82f4e), C(38b91b1cb7e34be), C(433bbdd27481d85d), C(ee32136b5a47bbec), C(769a77f346d82f4e), C(38b91b1cb7e34be), C(cb10fd95c0e43875), C(ce9744efd6f11427), C(946b32bddada6a13), C(35d544690b99e3b6)}, {C(c44e8c33ff6c5e13), C(1f128a22aab3007f), C(6a8b41bf04cd593), C(1b9b0deaf126522a), C(cc51d382baedc2eb), C(8df8831bb2e75daa), C(de4e7a4b5de99588), C(1b9b0deaf126522a), C(cc51d382baedc2eb), C(8df8831bb2e75daa), C(de4e7a4b5de99588), C(55a2707103a9f968), C(e0063f4e1649702d), C(7e82f5b440e74043), C(649b44a27f00219d)}, {C(68125009158bded7), C(563a9a62753fc088), C(b97a9873a352cf6a), C(237d1de15ae56127), C(b96445f758ba57d), C(b842628a9f9938eb), C(70313d232dc2cd0d), C(237d1de15ae56127), C(b96445f758ba57d), C(b842628a9f9938eb), C(70313d232dc2cd0d), C(8bfe1f78cb40ad5b), C(a5bde811d49f56e1), C(1acd0cf913ded507), C(820b3049fa5e6786)}, {C(e0dd644db35a62d6), C(292889772752ab42), C(b80433749dbb8793), C(7032fe67035f95db), C(d8076d1fda17eb8d), C(115ca1775560f946), C(92da1e16f396bf61), C(7032fe67035f95db), C(d8076d1fda17eb8d), C(115ca1775560f946), C(92da1e16f396bf61), C(17c8bc7f6d23a639), C(fb28a2afa4d562a9), C(6c59c95fa2450d5f), C(fe0d41d5ebfbce2a)}, {C(21ce9eab220aaf87), C(27d20caec922d708), C(610c51f976cb1d30), C(6052f97a1e02d2ba), C(836eea7ce63dea17), C(e1f8efb81b443b45), C(ddbdbbe717570246), C(6052f97a1e02d2ba), C(836eea7ce63dea17), C(e1f8efb81b443b45), C(ddbdbbe717570246), C(69551045b0e56f60), C(625a435960ba7466), C(9cdb004e8b11405c), C(d6284db99a3b16af)}, {C(83b54046fdca7c1e), C(e3709e9153c01626), C(f306b5edc2682490), C(88f14b0b554fba02), C(a0ec13fac0a24d0), C(f468ebbc03b05f47), C(a9cc417c8dad17f0), C(88f14b0b554fba02), C(a0ec13fac0a24d0), C(f468ebbc03b05f47), C(a9cc417c8dad17f0), C(4c1ababa96d42275), C(c112895a2b751f17), C(5dd7d9fa55927aa9), C(ca09db548d91cd46)}, {C(dd3b2ce7dabb22fb), C(64888c62a5cb46ee), C(f004e8b4b2a97362), C(31831cf3efc20c84), C(901ba53808e677ae), C(4b36895c097d0683), C(7d93ad993f9179aa), C(31831cf3efc20c84), C(901ba53808e677ae), C(4b36895c097d0683), C(7d93ad993f9179aa), C(a4c5ea29ae78ba6b), C(9cf637af6d607193), C(5731bd261d5b3adc), C(d59a9e4f796984f3)}, {C(9ee08fc7a86b0ea6), C(5c8d17dff5768e66), C(18859672bafd1661), C(d3815c5f595e513e), C(44b3bdbdc0fe061f), C(f5f43b2a73ad2df5), C(7c0e6434c8d7553c), C(d3815c5f595e513e), C(44b3bdbdc0fe061f), C(f5f43b2a73ad2df5), C(7c0e6434c8d7553c), C(8c05859060821002), C(73629a0d275008ce), C(860c012879e6f00f), C(d48735a120d2c37c)}, {C(4e2a10f1c409dfa5), C(6e684591f5da86bd), C(ff8c9305d447cadb), C(c43ae49df25b1c86), C(d4f42115cee1ac8), C(a0e6a714471b975c), C(a40089dec5fe07b0), C(c43ae49df25b1c86), C(d4f42115cee1ac8), C(a0e6a714471b975c), C(a40089dec5fe07b0), C(18c3d8f967915e10), C(739c747dbe05adfb), C(4b0397b596e16230), C(3c57d7e1de9e58d1)}, {C(bdf3383d7216ee3c), C(eed3a37e4784d324), C(247cff656d081ba0), C(76059e4cb25d4700), C(e0af815fe1fa70ed), C(5a6ccb4f36c5b3df), C(391a274cd5f5182d), C(76059e4cb25d4700), C(e0af815fe1fa70ed), C(5a6ccb4f36c5b3df), C(391a274cd5f5182d), C(ff1579baa6a2b511), C(c385fc5062e8a728), C(e940749739a37c78), C(a093523a5b5edee5)}, {C(a22e8f6681f0267d), C(61e79bc120729914), C(86ec13c84c1600d3), C(1614811d59dcab44), C(d1ddcca9a2675c33), C(f3c551d5fa617763), C(5c78d4181402e98c), C(1614811d59dcab44), C(d1ddcca9a2675c33), C(f3c551d5fa617763), C(5c78d4181402e98c), C(b43b4a9caa6f5d4c), C(f112829bca2df8f3), C(87e5c85db80d06c3), C(8eb4bac85453409)}, {C(6997121cae0ce362), C(ba3594cbcc299a07), C(7e4b71c7de25a5e4), C(16ad89e66db557ba), C(a43c401140ffc77d), C(3780a8b3fd91e68), C(48190678248a06b5), C(16ad89e66db557ba), C(a43c401140ffc77d), C(3780a8b3fd91e68), C(48190678248a06b5), C(d10deb97b651ad42), C(3a69f3f29046a24f), C(f7179735f2c6dab4), C(ac82965ad3b67a02)}, {C(9bfc2c3e050a3c27), C(dc434110e1059ff3), C(5426055da178decd), C(cb44d00207e16f99), C(9d9e99afedc8107f), C(56907c4fb7b3bc01), C(bcff1472bb01f85a), C(cb44d00207e16f99), C(9d9e99afedc8107f), C(56907c4fb7b3bc01), C(bcff1472bb01f85a), C(516f800f74ad0985), C(f93193ade9614da4), C(9f4a7845355b75b7), C(423c17045824dea5)}, {C(a3f37e415aedf14), C(8d21c92bfa0dc545), C(a2715ebb07deaf80), C(98ce1ff2b3f99f0f), C(162acfd3b47c20bf), C(62b9a25fd39dc6c0), C(c165c3c95c878dfe), C(98ce1ff2b3f99f0f), C(162acfd3b47c20bf), C(62b9a25fd39dc6c0), C(c165c3c95c878dfe), C(2b9a7e1f055bd27c), C(e91c8099cafaa75d), C(37e38d64ef0263b), C(a46e89f47a1a70d5)}, {C(cef3c748045e7618), C(41dd44faef4ca301), C(6add718a88f383c6), C(1197eca317e70a93), C(61f9497e6cc4a33), C(22e7178d1e57af73), C(5df95da0ff1c6435), C(1197eca317e70a93), C(61f9497e6cc4a33), C(22e7178d1e57af73), C(5df95da0ff1c6435), C(934327643705e56c), C(11eb0eec553137c9), C(1e6b9b57ac5283ec), C(6934785db184b2e4)}, {C(fe2b841766a4d212), C(42cf817e58fe998c), C(29f7f493ba9cbe6c), C(2a9231d98b441827), C(fca55e769df78f6c), C(da87ea680eb14df4), C(e0b77394b0fd2bcc), C(2a9231d98b441827), C(fca55e769df78f6c), C(da87ea680eb14df4), C(e0b77394b0fd2bcc), C(f36a2a3c73ab371a), C(d52659d36d93b71), C(3d3b7d2d2fafbb14), C(b4b7b317d9266711)}, {C(d6131e688593a181), C(5b658b282688ccd3), C(b9f7c066beed1204), C(e9dd79bad89f6b19), C(b420092bae6aaf41), C(515f9bbd06069d77), C(80664957a02cbc29), C(e9dd79bad89f6b19), C(b420092bae6aaf41), C(515f9bbd06069d77), C(80664957a02cbc29), C(f9dc7a744a56d9b3), C(7eb2bdcd6667f383), C(c5914296fbdaf9d1), C(af0d5a8fec374fc4)}, {C(91288884ebfcf145), C(3dffd892d36403af), C(7c4789db82755080), C(634acbe037edec27), C(878a97fab822d804), C(fcb042af908f0577), C(4cbafc318bb90a2e), C(634acbe037edec27), C(878a97fab822d804), C(fcb042af908f0577), C(4cbafc318bb90a2e), C(68a96d589d5e5654), C(a752cb250bca1bc0), C(8f228f406024aa7e), C(fc5408cf22a080b5)}, {C(754c7e98ae3495ea), C(2030124a22512c19), C(ec241579c626c39d), C(e682b5c87fa8e41b), C(6cfa4baff26337ac), C(4d66358112f09b2a), C(58889d3f50ffa99c), C(33fc6ffd1ffb8676), C(36db7617b765f6e2), C(8df41c03c514a9dc), C(6707cc39a809bb74), C(3f27d7bb79e31984), C(a39dc6ac6cb0b0a8), C(33fc6ffd1ffb8676), C(36db7617b765f6e2)}, }; void Check(uint64 expected, uint64 actual) { if (expected != actual) { cerr << "ERROR: expected 0x" << hex << expected << ", but got 0x" << actual << "\n"; ++errors; } } void Test(const uint64* expected, int offset, int len) { const uint128 u = CityHash128(data + offset, len); const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); Check(expected[0], CityHash64(data + offset, len)); Check(expected[1], CityHash64WithSeed(data + offset, len, kSeed0)); Check(expected[2], CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1)); Check(expected[3], Uint128Low64(u)); Check(expected[4], Uint128High64(u)); Check(expected[5], Uint128Low64(v)); Check(expected[6], Uint128High64(v)); #ifdef __SSE4_2__ const uint128 y = CityHashCrc128(data + offset, len); const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); uint64 crc256_results[4]; CityHashCrc256(data + offset, len, crc256_results); Check(expected[7], Uint128Low64(y)); Check(expected[8], Uint128High64(y)); Check(expected[9], Uint128Low64(z)); Check(expected[10], Uint128High64(z)); for (int i = 0; i < 4; i++) { Check(expected[11 + i], crc256_results[i]); } #endif } #else #define Test(a, b, c) Dump((b), (c)) void Dump(int offset, int len) { const uint128 u = CityHash128(data + offset, len); const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); const uint128 y = CityHashCrc128(data + offset, len); const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); uint64 crc256_results[4]; CityHashCrc256(data + offset, len, crc256_results); cout << hex << "{C(" << CityHash64(data + offset, len) << "), " << "C(" << CityHash64WithSeed(data + offset, len, kSeed0) << "), " << "C(" << CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1) << "), " << "C(" << Uint128Low64(u) << "), " << "C(" << Uint128High64(u) << "), " << "C(" << Uint128Low64(v) << "), " << "C(" << Uint128High64(v) << "),\n" << "C(" << Uint128Low64(y) << "), " << "C(" << Uint128High64(y) << "), " << "C(" << Uint128Low64(z) << "), " << "C(" << Uint128High64(z) << "),\n"; for (int i = 0; i < 4; i++) { cout << hex << "C(" << crc256_results[i] << (i == 3 ? ")},\n" : "), "); } } #endif int main(int argc, char** argv) { setup(); int i = 0; for ( ; i < kTestSize - 1; i++) { Test(testdata[i], i * i, i); } Test(testdata[i], 0, kDataSize); return errors > 0; } dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/city_c.c000066400000000000000000000425131446635226000237210ustar00rootroot00000000000000/* Copyright (c) 2011 Google, Inc. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining a copy */ /* of this software and associated documentation files (the "Software"), to deal */ /* in the Software without restriction, including without limitation the rights */ /* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ /* copies of the Software, and to permit persons to whom the Software is */ /* furnished to do so, subject to the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be included in */ /* all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ /* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ /* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ /* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ /* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */ /* THE SOFTWARE. */ /* */ /* CityHash, by Geoff Pike and Jyrki Alakuijala */ /* */ /* This file provides CityHash64() and related functions. */ /* */ /* It's probably possible to create even faster hash functions by */ /* writing a program that systematically explores some of the space of */ /* possible hash functions, by using SIMD instructions, or by */ /* compromising on hash quality. */ #include "city_c.h" #include #if defined(__sparc) || defined(__sparc__) \ || defined(_POWER) || defined(__powerpc__) \ || defined(__ppc__) || defined(__hpux) || defined(__hppa) \ || defined(_MIPSEB) || defined(_POWER) \ || defined(__s390__) # define WORDS_BIGENDIAN #elif defined(__i386__) || defined(__alpha__) \ || defined(__ia64) || defined(__ia64__) \ || defined(_M_IX86) || defined(_M_IA64) \ || defined(_M_ALPHA) || defined(__amd64) \ || defined(__amd64__) || defined(_M_AMD64) \ || defined(__x86_64) || defined(__x86_64__) \ || defined(_M_X64) || defined(__bfin__) # define WORDS_LITTLEENDIAN #endif #if !defined(WORDS_BIGENDIAN) # define uint32_in_expected_order(x) (x) # define uint64_in_expected_order(x) (x) #else # if defined _MSC_VER # include # define bswap_32(x) _byteswap_ulong(x) # define bswap_64(x) _byteswap_uint64(x) # elif defined(__APPLE__) /* Mac OS X / Darwin features */ # include # define bswap_32(x) OSSwapInt32(x) # define bswap_64(x) OSSwapInt64(x) # else # include # endif # define uint32_in_expected_order(x) (bswap_32(x)) # define uint64_in_expected_order(x) (bswap_64(x)) #endif /* WORDS_BIGENDIAN */ #if !defined inline # ifdef _MSC_VER # define inline __inline # endif #endif #if !defined LIKELY # if defined __GNUC__ && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))/*GCC 2.96 above */ # define LIKELY(x) (__builtin_expect(!!(x), 1)) # else # define LIKELY(x) (x) # endif #endif #define UNSAFE_SWAP(type, a, b) do { type tmp; tmp = (a); (a) = (b); (b) = tmp; } while (0) static inline uint128 UInt128(uint64 low, uint64 high) { uint128 val; val.first = low; val.second = high; return val; } static inline uint64 UNALIGNED_LOAD64(const char *p) { uint64 result; memcpy(&result, p, sizeof(result)); return result; } static inline uint32 UNALIGNED_LOAD32(const char *p) { uint32 result; memcpy(&result, p, sizeof(result)); return result; } static uint64 Hash64Pairto64(uint64 u, uint64 v) { /* Murmur-inspired hashing. */ static const uint64 kMul = 0x9ddfea08eb382d69ULL; uint64 a, b; a = (u ^ v) * kMul; a ^= (a >> 47); b = (v ^ a) * kMul; b ^= (b >> 47); b *= kMul; return b; } static inline uint64 Fetch64(const char *p) { return uint64_in_expected_order(UNALIGNED_LOAD64(p)); } static inline uint32 Fetch32(const char *p) { return uint32_in_expected_order(UNALIGNED_LOAD32(p)); } /* Some primes between 2^63 and 2^64 for various uses. */ static const uint64 k0 = 0xc3a5c85c97cb3127ULL; static const uint64 k1 = 0xb492b66fbe98f273ULL; static const uint64 k2 = 0x9ae16a3b2f90404fULL; static const uint64 k3 = 0xc949d7c7509e6557ULL; /* Bitwise right rotate. Normally this will compile to a single */ /* instruction, especially if the shift is a manifest constant. */ static inline uint64 Rotate(uint64 val, int shift) { /* Avoid shifting by 64: doing so yields an undefined result. */ return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); } /* Equivalent to Rotate(), but requires the second arg to be non-zero. */ /* On x86-64, and probably others, it's possible for this to compile */ /* to a single instruction if both args are already in registers. */ static inline uint64 RotateByAtLeast1(uint64 val, int shift) { return (val >> shift) | (val << (64 - shift)); } static inline uint64 ShiftMix(uint64 val) { return val ^ (val >> 47); } static inline uint64 HashLen16(uint64 u, uint64 v) { /*return Hash128to64(uint128(u, v)); */ return Hash64Pairto64(u, v); } static uint64 HashLen0to16(const char *s, size_t len) { if (len > 8) { uint64 a = Fetch64(s); uint64 b = Fetch64(s + len - 8); return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b; } if (len >= 4) { uint64 a = Fetch32(s); return HashLen16(len + (a << 3), Fetch32(s + len - 4)); } if (len > 0) { uint8 a = s[0]; uint8 b = s[len >> 1]; uint8 c = s[len - 1]; uint32 y = (uint32)a + ((uint32)b << 8); uint32 z = len + ((uint32)c << 2); return ShiftMix(y * k2 ^ z * k3) * k2; } return k2; } /* This probably works well for 16-byte strings as well, but it may be overkill */ /* in that case. */ static uint64 HashLen17to32(const char *s, size_t len) { uint64 a = Fetch64(s) * k1; uint64 b = Fetch64(s + 8); uint64 c = Fetch64(s + len - 8) * k2; uint64 d = Fetch64(s + len - 16) * k0; return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d, a + Rotate(b ^ k3, 20) - c + len); } /* Return a 16-byte hash for 48 bytes. Quick and dirty. */ /* Callers do best to use "random-looking" values for a and b. */ static uint128 WeakHashLen32WithSeeds6(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { uint64 c; a += w; b = Rotate(b + a + z, 21); c = a; a += x; a += y; b += Rotate(a, 44); return UInt128(a + z, b + c); } /* Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. */ static uint128 WeakHashLen32WithSeeds3(const char *s, uint64 a, uint64 b) { return WeakHashLen32WithSeeds6(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a, b); } /* Return an 8-byte hash for 33 to 64 bytes. */ static uint64 HashLen33to64(const char *s, size_t len) { uint64 z = Fetch64(s + 24); uint64 a = Fetch64(s) + (len + Fetch64(s + len - 16)) * k0; uint64 b = Rotate(a + z, 52); uint64 c = Rotate(a, 37); uint64 vf, vs, wf, ws, r; a += Fetch64(s + 8); c += Rotate(a, 7); a += Fetch64(s + 16); vf = a + z; vs = b + Rotate(a, 31) + c; a = Fetch64(s + 16) + Fetch64(s + len - 32); z = Fetch64(s + len - 8); b = Rotate(a + z, 52); c = Rotate(a, 37); a += Fetch64(s + len - 24); c += Rotate(a, 7); a += Fetch64(s + len - 16); wf = a + z; ws = b + Rotate(a, 31) + c; r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0); return ShiftMix(r * k0 + vs) * k2; } uint64 CityHash64(const char *s, size_t len) { if (len <= 32) { if (len <= 16) return HashLen0to16(s, len); else return HashLen17to32(s, len); } else if (len <= 64) { return HashLen33to64(s, len); } do { /* For strings over 64 bytes we hash the end first, and then as we */ /* loop we keep 56 bytes of state: v, w, x, y, and z. */ uint64 x = Fetch64(s + len - 40); uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); uint128 v = WeakHashLen32WithSeeds3(s + len - 64, len, z); uint128 w = WeakHashLen32WithSeeds3(s + len - 32, y + k1, x); x = x * k1 + Fetch64(s); /* Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. */ len = (len - 1) & ~(size_t)63; do { x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; x ^= w.second; y += v.first + Fetch64(s + 40); z = Rotate(z + w.first, 33) * k1; v = WeakHashLen32WithSeeds3(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds3(s + 32, z + w.second, y + Fetch64(s + 16)); UNSAFE_SWAP(uint64, z, x); s += 64; len -= 64; } while (len != 0); return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, HashLen16(v.second, w.second) + x); } while (0); } uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { return CityHash64WithSeeds(s, len, k2, seed); } uint64 CityHash64WithSeeds(const char *s, size_t len, uint64 seed0, uint64 seed1) { return HashLen16(CityHash64(s, len) - seed0, seed1); } /* A subroutine for CityHash128(). Returns a decent 128-bit hash for strings */ /* of any length representable in signed long. Based on City and Murmur. */ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { uint64 a = Uint128Low64(seed); uint64 b = Uint128High64(seed); uint64 c = 0; uint64 d = 0; signed long l = len - 16; if (l <= 0) { /* len <= 16 */ a = ShiftMix(a * k1) * k1; c = b * k1 + HashLen0to16(s, len); d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); } else { /* len > 16 */ c = HashLen16(Fetch64(s + len - 8) + k1, a); d = HashLen16(b + len, c + Fetch64(s + len - 16)); a += d; do { a ^= ShiftMix(Fetch64(s) * k1) * k1; a *= k1; b ^= a; c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; c *= k1; d ^= c; s += 16; l -= 16; } while (l > 0); } a = HashLen16(a, c); b = HashLen16(d, b); return UInt128(a ^ b, HashLen16(b, a)); } uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { if (len < 128) return CityMurmur(s, len, seed); do { /* We expect len >= 128 to be the common case. Keep 56 bytes of state: */ /* v, w, x, y, and z. */ uint128 v, w; uint64 x = Uint128Low64(seed); uint64 y = Uint128High64(seed); uint64 z = len * k1; size_t tail_done; v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); w.first = Rotate(y + z, 35) * k1 + x; w.second = Rotate(x + Fetch64(s + 88), 53) * k1; /* This is the same inner loop as CityHash64(), manually unrolled. */ do { x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; x ^= w.second; y += v.first + Fetch64(s + 40); z = Rotate(z + w.first, 33) * k1; v = WeakHashLen32WithSeeds3(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds3(s + 32, z + w.second, y + Fetch64(s + 16)); UNSAFE_SWAP(uint64, z, x); s += 64; x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; x ^= w.second; y += v.first + Fetch64(s + 40); z = Rotate(z + w.first, 33) * k1; v = WeakHashLen32WithSeeds3(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds3(s + 32, z + w.second, y + Fetch64(s + 16)); UNSAFE_SWAP(uint64, z, x); s += 64; len -= 128; } while (LIKELY(len >= 128)); x += Rotate(v.first + z, 49) * k0; z += Rotate(w.first, 37) * k0; /* If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. */ for (tail_done = 0; tail_done < len;) { tail_done += 32; y = Rotate(x + y, 42) * k0 + v.second; w.first += Fetch64(s + len - tail_done + 16); x = x * k0 + w.first; z += w.second + Fetch64(s + len - tail_done); w.second += v.first; v = WeakHashLen32WithSeeds3(s + len - tail_done, v.first + z, v.second); } /* At this point our 56 bytes of state should contain more than */ /* enough information for a strong 128-bit hash. We use two */ /* different 56-byte-to-8-byte hashes to get a 16-byte final result. */ x = HashLen16(x, v.first); y = HashLen16(y + z, w.first); return UInt128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second)); } while (0); } uint128 CityHash128(const char *s, size_t len) { if (len >= 16) return CityHash128WithSeed(s + 16, len - 16, UInt128(Fetch64(s) ^ k3, Fetch64(s + 8))); else if (len >= 8) return CityHash128WithSeed(NULL, 0, UInt128(Fetch64(s) ^ (len * k0), Fetch64(s + len - 8) ^ k1)); else return CityHash128WithSeed(s, len, UInt128(k0, k1)); } #ifdef __SSE4_2__ # include "citycrc_c.h" # include /* Requires len >= 240. */ static void CityHashCrc256Long(const char *s, size_t len, uint32 seed, uint64 *result) { uint64 a = Fetch64(s + 56) + k0; uint64 b = Fetch64(s + 96) + k0; uint64 c = result[0] = HashLen16(b, len); uint64 d = result[1] = Fetch64(s + 120) * k0 + len; uint64 e = Fetch64(s + 184) + seed; uint64 f = seed; uint64 g = 0; uint64 h = 0; uint64 i = 0; uint64 j = 0; uint64 t = c + d; /* 240 bytes of input per iter. */ size_t iters = len / 240; len -= iters * 240; do { # define CHUNK(multiplier, z) \ { \ uint64 old_a = a; \ a = Rotate(b, 41 ^ z) * multiplier + Fetch64(s); \ b = Rotate(c, 27 ^ z) * multiplier + Fetch64(s + 8); \ c = Rotate(d, 41 ^ z) * multiplier + Fetch64(s + 16); \ d = Rotate(e, 33 ^ z) * multiplier + Fetch64(s + 24); \ e = Rotate(t, 25 ^ z) * multiplier + Fetch64(s + 32); \ t = old_a; \ } \ f = _mm_crc32_u64(f, a); \ g = _mm_crc32_u64(g, b); \ h = _mm_crc32_u64(h, c); \ i = _mm_crc32_u64(i, d); \ j = _mm_crc32_u64(j, e); \ s += 40 CHUNK(1, 1); CHUNK(k0, 0); CHUNK(1, 1); CHUNK(k0, 0); CHUNK(1, 1); CHUNK(k0, 0); } while (--iters > 0); while (len >= 40) { CHUNK(k0, 0); len -= 40; } if (len > 0) { s = s + len - 40; CHUNK(k0, 0); } j += i << 32; a = HashLen16(a, j); h += g << 32; b += h; c = HashLen16(c, f) + i; d = HashLen16(d, e + result[0]); j += e; i += HashLen16(h, t); e = HashLen16(a, d) + j; f = HashLen16(b, c) + a; g = HashLen16(j, i) + c; result[0] = e + f + g + h; a = ShiftMix((a + g) * k0) * k0 + b; result[1] += a + result[0]; a = ShiftMix(a * k0) * k0 + c; result[2] = a + result[1]; a = ShiftMix((a + e) * k0) * k0; result[3] = a + result[2]; } /* Requires len < 240. */ static inline void CityHashCrc256Short(const char *s, size_t len, uint64 *result) { char buf[240]; memcpy(buf, s, len); memset(buf + len, 0, 240 - len); CityHashCrc256Long(buf, 240, ~(uint32)len, result); } void CityHashCrc256(const char *s, size_t len, uint64 *result) { if (LIKELY(len >= 240)) CityHashCrc256Long(s, len, 0, result); else CityHashCrc256Short(s, len, result); } uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { if (len <= 900) { return CityHash128WithSeed(s, len, seed); } else { uint64 result[4], u, v; CityHashCrc256(s, len, result); u = Uint128High64(seed) + result[0]; v = Uint128Low64(seed) + result[1]; return UInt128(HashLen16(u, v + result[2]), HashLen16(Rotate(v, 32), u * k0 + result[3])); } } uint128 CityHashCrc128(const char *s, size_t len) { if (len <= 900) { return CityHash128(s, len); } else { uint64 result[4]; CityHashCrc256(s, len, result); return UInt128(result[2], result[3]); } } #endif dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/city_c.h000066400000000000000000000070301446635226000237210ustar00rootroot00000000000000/* Copyright (c) 2011 Google, Inc. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining a copy */ /* of this software and associated documentation files (the "Software"), to deal */ /* in the Software without restriction, including without limitation the rights */ /* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ /* copies of the Software, and to permit persons to whom the Software is */ /* furnished to do so, subject to the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be included in */ /* all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ /* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ /* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ /* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ /* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */ /* THE SOFTWARE. */ /* */ /* CityHash, by Geoff Pike and Jyrki Alakuijala */ /* */ /* This file provides a few functions for hashing strings. On x86-64 */ /* hardware in 2011, CityHash64() is faster than other high-quality */ /* hash functions, such as Murmur. This is largely due to higher */ /* instruction-level parallelism. CityHash64() and CityHash128() also perform */ /* well on hash-quality tests. */ /* */ /* CityHash128() is optimized for relatively long strings and returns */ /* a 128-bit hash. For strings more than about 2000 bytes it can be */ /* faster than CityHash64(). */ /* */ /* Functions in the CityHash family are not suitable for cryptography. */ /* */ /* WARNING: This code has not been tested on big-endian platforms! */ /* It is known to work well on little-endian platforms that have a small penalty */ /* for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. */ /* */ /* By the way, for some hash functions, given strings a and b, the hash */ /* of a+b is easily derived from the hashes of a and b. This property */ /* doesn't hold for any hash functions in this file. */ #ifndef CITY_HASH_H_ # define CITY_HASH_H_ # include # ifdef _MSC_VER typedef unsigned char uint8; typedef unsigned int uint32; typedef unsigned long long uint64; # else # include typedef uint8_t uint8; typedef uint32_t uint32; typedef uint64_t uint64; # endif # ifdef __cplusplus extern "C" { # endif # pragma pack(1) typedef struct { uint64 first, second; } uint128; # pragma pack() # define Uint128Low64(x) ((x).first) # define Uint128High64(x) ((x).second) /* Hash function for a byte array. */ uint64 CityHash64(const char *buf, size_t len); /* Hash function for a byte array. For convenience, a 64-bit seed is also */ /* hashed into the result. */ uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed); /* Hash function for a byte array. For convenience, two seeds are also */ /* hashed into the result. */ uint64 CityHash64WithSeeds(const char *buf, size_t len, uint64 seed0, uint64 seed1); /* Hash function for a byte array. */ uint128 CityHash128(const char *s, size_t len); /* Hash function for a byte array. For convenience, a 128-bit seed is also */ /* hashed into the result. */ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed); # ifdef __cplusplus } # endif #endif /* CITY_HASH_H_ */ dlt-daemon-2.18.10/src/core_dump_handler/cityhash_c/citycrc_c.h000066400000000000000000000037741446635226000244240ustar00rootroot00000000000000/* Copyright (c) 2011 Google, Inc. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining a copy */ /* of this software and associated documentation files (the "Software"), to deal */ /* in the Software without restriction, including without limitation the rights */ /* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ /* copies of the Software, and to permit persons to whom the Software is */ /* furnished to do so, subject to the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be included in */ /* all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ /* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ /* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ /* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ /* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */ /* THE SOFTWARE. */ /* */ /* CityHash, by Geoff Pike and Jyrki Alakuijala */ /* */ /* This file declares the subset of the CityHash functions that require */ /* _mm_crc32_u64(). See the CityHash README for details. */ /* */ /* Functions in the CityHash family are not suitable for cryptography. */ #ifndef CITY_HASH_CRC_H_ # define CITY_HASH_CRC_H_ # include "city_c.h" # ifdef __cplusplus extern "C" { # endif /* Hash function for a byte array. */ uint128 CityHashCrc128(const char *s, size_t len); /* Hash function for a byte array. For convenience, a 128-bit seed is also */ /* hashed into the result. */ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed); /* Hash function for a byte array. Sets result[0] ... result[3]. */ void CityHashCrc256(const char *s, size_t len, uint64 *result); # ifdef __cplusplus } # endif #endif /* CITY_HASH_CRC_H_ */ dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh.c000066400000000000000000000315071446635226000217330ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh.c */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dlt_cdh.h" #include /* Unusual characters in a windows filename are replaced */ #define UNUSUAL_CHARS ":/\\!*" #define REPLACEMENT_CHAR '_' #define COREDUMP_FILESYSTEM "/var" #define COREDUMP_FILESYSTEM_MIN_SIZE_MB 40 #define COREDUMP_HANDLER_PRIORITY -19 void core_locks(const proc_info_t *p_proc, int action); /* =================================================================== ** Method : init_proc_info(...) ** ** Description : initialises all members of process info structure to defined values ** ** Parameters : INPUT p_proc ** OUTPUT pointer to initialised crashed process info structure ** ** Returns : nothing ** ===================================================================*/ void init_proc_info(proc_info_t *p_proc) { memset(p_proc->name, 0, sizeof(p_proc->name)); memset(p_proc->threadname, 0, sizeof(p_proc->threadname)); p_proc->pid = 0; p_proc->timestamp = 0; p_proc->signal = 0; p_proc->can_create_coredump = 1; memset(&p_proc->streamer, 0, sizeof(p_proc->streamer)); memset(&p_proc->m_Ehdr, 0, sizeof(p_proc->m_Ehdr)); p_proc->m_pPhdr = NULL; p_proc->m_Nhdr = NULL; p_proc->m_note_page_size = 0; memset(&p_proc->m_registers, 0, sizeof(p_proc->m_registers)); p_proc->m_crashed_pid = 0; p_proc->m_crashid_phase1 = 0; memset(p_proc->m_crashid, 0, sizeof(p_proc->m_crashid)); } /* =================================================================== ** Method : read_args(...) ** ** Description : reads command line arguments ** ** Parameters : INPUT argc ** INPUT argv ** OUTPUT pointer to crashed process info structure ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t read_args(int argc, char **argv, proc_info_t *proc) { if (argc < 5) { syslog(LOG_ERR, "Usage: cdh timestamp pid signal procname"); return CDH_NOK; } init_proc_info(proc); if (sscanf(argv[1], "%u", &proc->timestamp) != 1) { syslog(LOG_ERR, "Unable to read timestamp argument <%s>. Closing", argv[1]); return CDH_NOK; } if (sscanf(argv[2], "%d", &proc->pid) != 1) { syslog(LOG_ERR, "Unable to read pid argument <%s>. Closing", argv[2]); return CDH_NOK; } if (sscanf(argv[3], "%d", &proc->signal) != 1) { syslog(LOG_ERR, "Unable to read signal argument <%s>. Closing", argv[3]); return CDH_NOK; } /* save the thread name given by the kernel */ strncpy(proc->threadname, argv[4], sizeof(proc->threadname) - 1); /* initialize the binary name with threadname... in case we cannot read it from /proc */ strncpy(proc->name, argv[4], sizeof(proc->name) - 1); return CDH_OK; } /* =================================================================== ** Method : remove_unusual_chars(...) ** ** Description : modify the input string to change UNUSUALS_CHARS to ** REPLACEMENT_CHAR ** Parameters : INPUT/OUTPUT string to be modified ** ** Returns : nothing ** ===================================================================*/ void remove_unusual_chars(char *p_string) { unsigned int l_char_index = 0; for (l_char_index = 0; l_char_index < sizeof(UNUSUAL_CHARS) - 1; l_char_index++) { char *l_str_pointer = p_string; do { l_str_pointer = strchr(l_str_pointer, UNUSUAL_CHARS[l_char_index]); if (l_str_pointer != NULL) { *l_str_pointer = REPLACEMENT_CHAR; l_str_pointer++; } } while (l_str_pointer != NULL); } } /* =================================================================== ** Method : check_disk_space(...) ** ** Description : check if there is sufficient disk space to write a coredump ** Parameters : INPUT/OUTPUT string to be modified ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t check_disk_space() { struct statvfs stat; unsigned long free_size = 0; if (statvfs(COREDUMP_FILESYSTEM, &stat) < 0) { syslog(LOG_ERR, "ERR cannot stat disk space on %s: %s", COREDUMP_FILESYSTEM, strerror(errno)); return CDH_NOK; } /* free space: size of block * number of free blocks (>>20 => MB) */ free_size = (stat.f_bsize * stat.f_bavail) >> 20; if (free_size < COREDUMP_FILESYSTEM_MIN_SIZE_MB) { syslog(LOG_WARNING, "ERR insufficient disk space for coredump: %ld MB.", free_size); return CDH_NOK; } syslog(LOG_INFO, "INFO disk space for coredump: %ld MB.", free_size); return CDH_OK; } void clean_core_tmp_dir() { DIR *d = NULL; struct dirent *dir = NULL; if ((d = opendir(CORE_TMP_DIRECTORY)) != NULL) { char lockfilepath[CORE_MAX_FILENAME_LENGTH]; while ((dir = readdir(d)) != NULL) { struct stat unused_stat; /* check if lock file exists */ snprintf(lockfilepath, sizeof(lockfilepath), "%s/%s", CORE_LOCK_DIRECTORY, dir->d_name); if (stat(lockfilepath, &unused_stat) != 0) { /* No lock file found for this coredump => from previous LC => delete */ char filepath[CORE_MAX_FILENAME_LENGTH] = { 0 }; snprintf(filepath, sizeof(filepath), "%s/%s", CORE_TMP_DIRECTORY, dir->d_name); syslog(LOG_INFO, "Cleaning %s: delete file %s", CORE_TMP_DIRECTORY, filepath); unlink(filepath); } } closedir(d); } } /* =================================================================== ** Method : check_core_directory(...) ** ** Description : checks the availability of core dumps directory. ** if not available, there is an installation issue. ** ** Parameters : ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t check_and_create_directory(const char *p_dirname, int create_silently) { int l_need_create = 0; int l_need_delete = 0; struct stat l_stat; if (lstat(p_dirname, &l_stat) < 0) { l_need_create = 1; } else if (!S_ISDIR(l_stat.st_mode)) { l_need_delete = 1; l_need_create = 1; } if (l_need_delete > 0) { syslog(LOG_WARNING, "WARN core directory '%s' is not a directory => removing it", p_dirname); if (unlink(p_dirname) == -1) { syslog(LOG_ERR, "ERR core directory '%s' cannot be unlinked: %s", p_dirname, strerror(errno)); return CDH_NOK; } } if (l_need_create > 0) { if (create_silently == 0) syslog(LOG_WARNING, "WARN core directory '%s' does not exist => creation", p_dirname); if (mkdir(p_dirname, 0666) == -1) { syslog(LOG_ERR, "ERR core directory '%s' cannot be created: %s", p_dirname, strerror(errno)); return CDH_NOK; } } return CDH_OK; } /* =================================================================== ** Method : check_core_directory(...) ** ** Description : checks the availability of core dumps directory. ** if not available, there is an installation issue. ** ** Parameters : ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t check_core_directory() { if (check_and_create_directory(CORE_DIRECTORY, 0) < 0) return CDH_NOK; if (check_and_create_directory(CORE_TMP_DIRECTORY, 0) < 0) return CDH_NOK; if (check_and_create_directory(CORE_LOCK_DIRECTORY, 1) < 0) return CDH_NOK; clean_core_tmp_dir(); return CDH_OK; } /* =================================================================== ** Method : move_to_core_directory(...) ** ** Description : move the coredump and context files ** from temporary dir to final core directory ** ** Parameters : ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t move_to_core_directory(proc_info_t *p_proc) { char l_src_filename[CORE_MAX_FILENAME_LENGTH] = { 0 }; char l_dst_filename[CORE_MAX_FILENAME_LENGTH] = { 0 }; char *patterns[] = { CORE_FILE_PATTERN, CONTEXT_FILE_PATTERN }; unsigned int pattern_num = 0; if (p_proc == NULL) return CDH_NOK; for (pattern_num = 0; pattern_num < sizeof(patterns) / sizeof(char *); pattern_num++) { /* Don't move coredump if it cannot be created */ if ((p_proc->can_create_coredump == 0) && (pattern_num == 0)) continue; snprintf(l_src_filename, sizeof(l_src_filename), patterns[pattern_num], CORE_TMP_DIRECTORY, p_proc->timestamp, p_proc->name, p_proc->pid); snprintf(l_dst_filename, sizeof(l_dst_filename), patterns[pattern_num], CORE_DIRECTORY, p_proc->timestamp, p_proc->name, p_proc->pid); syslog(LOG_INFO, "Moving coredump from %s to %s", l_src_filename, l_dst_filename); if (rename(l_src_filename, l_dst_filename) < 0) syslog(LOG_ERR, "Moving failed: %s", strerror(errno)); } return CDH_OK; } /* =================================================================== ** Method : main(...) ** ** Description : ** ** Parameters : argc, argv ** ** Returns : ** ===================================================================*/ int main(int argc, char *argv[]) { proc_info_t l_proc_info; /* char l_exec_name[CORE_MAX_FILENAME_LENGTH] = {0}; */ openlog("CoredumpHandler", 0, LOG_DAEMON); if (read_args(argc, argv, &l_proc_info) < 0) exit(-1); if (get_exec_name(l_proc_info.pid, l_proc_info.name, sizeof(l_proc_info.name)) != 0) syslog(LOG_ERR, "Failed to get executable name"); syslog(LOG_NOTICE, "Handling coredump procname:%s pid:%d timest:%d signal:%d", l_proc_info.name, l_proc_info.pid, l_proc_info.timestamp, l_proc_info.signal); /* Increase priority of the coredump handler */ if (nice(COREDUMP_HANDLER_PRIORITY) != COREDUMP_HANDLER_PRIORITY) syslog(LOG_WARNING, "Failed to change CDH priority"); if (check_disk_space() < 0) /*return CDH_NOK; */ l_proc_info.can_create_coredump = 0; if (check_core_directory() < 0) /*return CDH_NOK; */ l_proc_info.can_create_coredump = 0; remove_unusual_chars(l_proc_info.name); core_locks(&l_proc_info, 1); write_proc_context(&l_proc_info); treat_coredump(&l_proc_info); move_to_core_directory(&l_proc_info); core_locks(&l_proc_info, 0); treat_crash_data(&l_proc_info); closelog(); return CDH_OK; } void core_locks(const proc_info_t *p_proc, int action) { char l_lockfilepath[CORE_MAX_FILENAME_LENGTH] = { 0 }; char *patterns[] = { CORE_FILE_PATTERN, CONTEXT_FILE_PATTERN }; unsigned int pattern_num = 0; int fd_lockfile = -1; if (p_proc == NULL) return; for (pattern_num = 0; pattern_num < sizeof(patterns) / sizeof(char *); pattern_num++) { snprintf(l_lockfilepath, sizeof(l_lockfilepath), patterns[pattern_num], CORE_LOCK_DIRECTORY, p_proc->timestamp, p_proc->name, p_proc->pid); switch (action) { case 0: { unlink(l_lockfilepath); break; } case 1: { if ((fd_lockfile = open(l_lockfilepath, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) { if (write(fd_lockfile, "1", 1) < 0) syslog(LOG_WARNING, "Failed to write lockfile %d: %s", fd_lockfile, strerror(errno)); close(fd_lockfile); } else { syslog(LOG_WARNING, "Failed to open lockfile %s: %s", l_lockfilepath, strerror(errno)); } break; } default: break; } } } dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh.h000066400000000000000000000047331446635226000217410ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh.h */ #ifndef DLT_CDH_H #define DLT_CDH_H #include #include #include #include #include #include "dlt_cdh_streamer.h" #define CORE_DIRECTORY "/var/core" #define CORE_TMP_DIRECTORY "/var/core_tmp" #define CORE_LOCK_DIRECTORY "/tmp/.core_locks" #define CORE_MAX_FILENAME_LENGTH 255 #define MAX_PROC_NAME_LENGTH 32 #define CRASH_ID_LEN 8 #define CRASHID_FILE "/tmp/.crashid" /* the file where the white screen app will read the crashid */ #define CORE_FILE_PATTERN "%s/core.%d.%s.%d.gz" #define CONTEXT_FILE_PATTERN "%s/context.%d.%s.%d.txt" #define ELF_Ehdr Elf32_Ehdr #define ELF_Phdr Elf32_Phdr #define ELF_Shdr Elf32_Shdr #define ELF_Nhdr Elf32_Nhdr typedef struct { uint64_t pc; uint64_t ip; uint64_t lr; } cdh_registers_t; typedef struct { char name[MAX_PROC_NAME_LENGTH]; char threadname[MAX_PROC_NAME_LENGTH]; pid_t pid; uint32_t timestamp; int signal; int can_create_coredump; file_streamer_t streamer; /* coredump content, for crash id generation */ ELF_Ehdr m_Ehdr; ELF_Phdr *m_pPhdr; char *m_Nhdr; /* buffer with all NOTE pages */ unsigned int m_note_page_size; cdh_registers_t m_registers; pid_t m_crashed_pid; uint64_t m_crashid_phase1; unsigned char m_crashid[CRASH_ID_LEN]; } proc_info_t; cdh_status_t get_exec_name(unsigned int p_pid_str, char *p_exec_name, int p_exec_name_maxsize); cdh_status_t write_proc_context(const proc_info_t *); cdh_status_t treat_coredump(proc_info_t *p_proc); cdh_status_t treat_crash_data(proc_info_t *p_proc); cdh_status_t move_to_core_directory(proc_info_t *p_proc); cdh_status_t check_core_directory(); #endif /* #ifndef DLT_CDH_H */ dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_context.c000066400000000000000000000257411446635226000235020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_context.c */ #include #include #include #include #include #include #include #include "dlt_cdh.h" /* Global buffer for file reading */ char g_buffer[4096]; /* =================================================================== ** Method : get_exec_name(...) ** ** Description : read executable filename ** ** Parameters : INPUT p_pid_str pid of the process ** OUTPUT p_exec_name executable name ** INPUT p_exec_name_maxsize size of p_exec_name buffer ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t get_exec_name(unsigned int p_pid, char *p_exec_name, int p_exec_name_maxsize) { char l_exe_link[CORE_MAX_FILENAME_LENGTH] = { 0 }; char *l_name_ptr = NULL; memset(l_exe_link, 0, sizeof(l_exe_link)); snprintf(l_exe_link, sizeof(l_exe_link) - 1, "/proc/%d/exe", p_pid); if (readlink(l_exe_link, g_buffer, p_exec_name_maxsize) < 0) return CDH_NOK; if ((l_name_ptr = strrchr(g_buffer, '/')) == NULL) return CDH_NOK; memset(p_exec_name, 0, p_exec_name_maxsize); strncpy(p_exec_name, l_name_ptr + 1, p_exec_name_maxsize - 1); return CDH_OK; } /* =================================================================== ** Method : dump_file_to(...) ** ** Description : dump the content of file p_src_filename to the file descriptor p_fout ** ** Parameters : INPUT p_src_filename ** INPUT p_fout ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t dump_file_to(const char *p_src_filename, FILE *p_fout) { FILE *l_fin = NULL; int bytes_read = 0; if (p_fout == NULL) return CDH_NOK; fprintf(p_fout, "\n==== Dumping file <%s> ====\n", p_src_filename); if ((l_fin = fopen(p_src_filename, "rt")) == NULL) { syslog(LOG_ERR, "ERR opening info file '%s' for dumping [%s]", p_src_filename, strerror(errno)); fprintf(p_fout, "**error**\n"); return CDH_NOK; } while ((bytes_read = fread(g_buffer, 1, sizeof(g_buffer), l_fin)) != 0) { int i = 0; /* changes all "\0" in the file to a "\n" */ /* (needed for example for /proc//cmdline, to keep all arguments) */ for (i = 0; i < bytes_read; i++) if (g_buffer[i] == '\000') g_buffer[i] = '\n'; fwrite(g_buffer, 1, bytes_read, p_fout); if (ferror(p_fout)) { syslog(LOG_ERR, "Writing in context file failed [%s]", strerror(errno)); fclose(p_fout); fclose(l_fin); return CDH_NOK; } } if (ferror(l_fin)) { syslog(LOG_ERR, "reading '%s' failed [%s]", p_src_filename, strerror(errno)); fclose(l_fin); return CDH_NOK; } fclose(l_fin); fprintf(p_fout, "\n"); return CDH_OK; } /************************************************************************************************** / */ /* "ls -l" implementation for /proc//fd (at least) */ /* Taken from coreutils sources, lib/filemode.c */ /* */ /* Return a character indicating the type of file described by * file mode BITS: * '-' regular file * 'b' block special file * 'c' character special file * 'C' high performance ("contiguous data") file * 'd' directory * 'D' door * 'l' symbolic link * 'm' multiplexed file (7th edition Unix; obsolete) * 'n' network special file (HP-UX) * 'p' fifo (named pipe) * 'P' port * 's' socket * 'w' whiteout (4.4BSD) * '?' some other file type */ static char ftypelet(mode_t bits) { /* These are the most common, so test for them first. */ if (S_ISREG(bits)) return '-'; if (S_ISDIR(bits)) return 'd'; /* Other letters standardized by POSIX 1003.1-2004. */ if (S_ISBLK(bits)) return 'b'; if (S_ISCHR(bits)) return 'c'; if (S_ISLNK(bits)) return 'l'; if (S_ISFIFO(bits)) return 'p'; /* Other file types (though not letters) standardized by POSIX. */ if (S_ISSOCK(bits)) return 's'; /* Nonstandard file types. * if (S_ISCTG (bits)) * return 'C'; * if (S_ISDOOR (bits)) * return 'D'; * if (S_ISMPB (bits) || S_ISMPC (bits)) * return 'm'; * if (S_ISNWK (bits)) * return 'n'; * if (S_ISPORT (bits)) * return 'P'; * if (S_ISWHT (bits)) * return 'w'; */ return '?'; } void strmode(mode_t mode, char *str) { if (str == NULL) return; str[0] = ftypelet(mode); str[1] = mode & S_IRUSR ? 'r' : '-'; str[2] = mode & S_IWUSR ? 'w' : '-'; str[3] = (mode & S_ISUID ? (mode & S_IXUSR ? 's' : 'S') : (mode & S_IXUSR ? 'x' : '-')); str[4] = mode & S_IRGRP ? 'r' : '-'; str[5] = mode & S_IWGRP ? 'w' : '-'; str[6] = (mode & S_ISGID ? (mode & S_IXGRP ? 's' : 'S') : (mode & S_IXGRP ? 'x' : '-')); str[7] = mode & S_IROTH ? 'r' : '-'; str[8] = mode & S_IWOTH ? 'w' : '-'; str[9] = (mode & S_ISVTX ? (mode & S_IXOTH ? 't' : 'T') : (mode & S_IXOTH ? 'x' : '-')); str[10] = ' '; str[11] = '\0'; } /* =================================================================== ** Method : list_dircontent_to(...) ** ** Description : list the filenames in p_dirname directory to the file descriptor p_fout ** ** Parameters : INPUT p_dirname ** INPUT p_fout ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t list_dircontent_to(const char *p_dirname, FILE *p_fout) { DIR *l_dd = NULL; /* directory descriptor */ struct dirent *l_entity = NULL; if ((l_dd = opendir(p_dirname)) == NULL) { syslog(LOG_ERR, "ERR reading info dir '%s' failed [%s]", p_dirname, strerror(errno)); return CDH_NOK; } fprintf(p_fout, "==== Listing directory <%s> ====\n", p_dirname); while ((l_entity = readdir(l_dd)) != NULL) { char l_fullpath[CORE_MAX_FILENAME_LENGTH] = { 0 }; char l_linkpath[CORE_MAX_FILENAME_LENGTH] = { 0 }; char l_modebuf[12] = { 0 }; struct stat l_stat; ssize_t l_size = 0; if (!strcmp(l_entity->d_name, ".") || !strcmp(l_entity->d_name, "..")) continue; snprintf(l_fullpath, sizeof(l_fullpath), "%s/%s", p_dirname, l_entity->d_name); if (lstat(l_fullpath, &l_stat) < 0) { syslog(LOG_ERR, "ERR lstat on '%s' failed. [%s]", l_fullpath, strerror(errno)); continue; } strmode(l_stat.st_mode, l_modebuf); fprintf(p_fout, "%s %ld %d %d %ld %4s", l_modebuf, l_stat.st_nlink, l_stat.st_uid, l_stat.st_gid, l_stat.st_size, l_entity->d_name); switch (l_stat.st_mode & S_IFMT) { case S_IFBLK: fprintf(p_fout, " [block device]\n"); break; case S_IFCHR: fprintf(p_fout, " [character device]\n"); break; case S_IFDIR: fprintf(p_fout, " [directory]\n"); break; case S_IFIFO: fprintf(p_fout, " [FIFO/pipe]\n"); break; case S_IFLNK: l_size = readlink(l_fullpath, l_linkpath, sizeof(l_linkpath)); l_linkpath[l_size] = 0; fprintf(p_fout, " -> %s\n", l_linkpath); break; case S_IFREG: fprintf(p_fout, " [regular file]\n"); break; case S_IFSOCK: fprintf(p_fout, " [socket]\n"); break; default: fprintf(p_fout, " [unknown?]\n"); break; } } /* while ( (l_entity = readdir(l_dd)) != NULL ) */ fprintf(p_fout, "===========================\n"); closedir(l_dd); return CDH_OK; } /************************************************************************************************** / */ /* END of "ls -l" implementation for /proc//fd (at least) */ /************************************************************************************************** / */ /* =================================================================== ** Method : write_proc_context(...) ** ** Description : write the context data of the crashed process ** (context data coming mainly from /proc) ** ** Parameters : INPUT p_proc crashed process info ** ** Returns : 0 if success, else -1 ** ===================================================================*/ cdh_status_t write_proc_context(const proc_info_t *p_proc) { FILE *l_fout = NULL; char l_procfile[256] = { 0 }; char l_outfilename[CORE_MAX_FILENAME_LENGTH] = { 0 }; if (p_proc == NULL) return CDH_NOK; snprintf(l_outfilename, sizeof(l_outfilename), CONTEXT_FILE_PATTERN, CORE_TMP_DIRECTORY, p_proc->timestamp, p_proc->name, p_proc->pid); if ((l_fout = fopen(l_outfilename, "w+t")) == NULL) { syslog(LOG_ERR, "ERR Cannot open context file '%s' [%s]", l_outfilename, strerror(errno)); return CDH_NOK; } #define PROC_FILENAME(x) do { \ snprintf(l_procfile, sizeof(l_procfile), "/proc/%d/"x, \ p_proc->pid); \ } while (0) fprintf(l_fout, "ProcName:%s\n", p_proc->name); fprintf(l_fout, "ThreadName:%s\n", p_proc->threadname); fprintf(l_fout, "PID:%d\n", p_proc->pid); fprintf(l_fout, "signal:%d\n", p_proc->signal); PROC_FILENAME("cmdline"); dump_file_to(l_procfile, l_fout); PROC_FILENAME("cgroup"); dump_file_to(l_procfile, l_fout); PROC_FILENAME("stack"); dump_file_to(l_procfile, l_fout); dump_file_to("/proc/loadavg", l_fout); dump_file_to("/etc/sysrel", l_fout); dump_file_to("/proc/version", l_fout); PROC_FILENAME("environ"); dump_file_to(l_procfile, l_fout); PROC_FILENAME("status"); dump_file_to(l_procfile, l_fout); PROC_FILENAME("sched"); dump_file_to(l_procfile, l_fout); PROC_FILENAME("maps"); dump_file_to(l_procfile, l_fout); PROC_FILENAME("fd"); list_dircontent_to(l_procfile, l_fout); #undef PROC_FILENAME fflush(l_fout); return CDH_OK; } dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_coredump.c000066400000000000000000000120001446635226000236140ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_coredump.c */ #include #include #include #include #include #include #include #include #include #include "dlt_cdh.h" cdh_status_t read_elf_headers(proc_info_t *p_proc) { int phnum = 0; /* Read ELF header */ stream_read(&p_proc->streamer, &p_proc->m_Ehdr, sizeof(p_proc->m_Ehdr)); /* Read until PROG position */ stream_move_to_offest(&p_proc->streamer, p_proc->m_Ehdr.e_phoff); /* Read and store all program headers */ p_proc->m_pPhdr = (ELF_Phdr *)malloc(sizeof(ELF_Phdr) * p_proc->m_Ehdr.e_phnum); if (p_proc->m_pPhdr == NULL) { syslog(LOG_ERR, "Cannot allocate Phdr memory (%d headers)", p_proc->m_Ehdr.e_phnum); return CDH_NOK; } for (phnum = 0; phnum < p_proc->m_Ehdr.e_phnum; phnum++) /* Read Programm header */ stream_read(&p_proc->streamer, &p_proc->m_pPhdr[phnum], sizeof(ELF_Phdr)); return CDH_OK; } int getNotePageIndex(proc_info_t *p_proc) { int i = 0; /* Search PT_NOTE section */ for (i = 0; i < p_proc->m_Ehdr.e_phnum; i++) { syslog(LOG_INFO, "==Note section prog_note:%d type:0x%X offset:0x%X size:0x%X (%dbytes)", i, p_proc->m_pPhdr[i].p_type, p_proc->m_pPhdr[i].p_offset, p_proc->m_pPhdr[i].p_filesz, p_proc->m_pPhdr[i].p_filesz); if (p_proc->m_pPhdr[i].p_type == PT_NOTE) break; } return i == p_proc->m_Ehdr.e_phnum ? CDH_NOK : i; } cdh_status_t read_notes(proc_info_t *p_proc) { int prog_note = getNotePageIndex(p_proc); /* p_proc->m_note_page_size = 0; */ p_proc->m_Nhdr = NULL; /* note page not found, abort */ if (prog_note < 0) { syslog(LOG_ERR, "Cannot find note header page index"); return CDH_NOK; } /* Move to NOTE header position */ if (stream_move_to_offest(&p_proc->streamer, p_proc->m_pPhdr[prog_note].p_offset) != CDH_OK) { syslog(LOG_ERR, "Cannot move to note header"); return CDH_NOK; } if ((p_proc->m_Nhdr = (char *)malloc(p_proc->m_pPhdr[prog_note].p_filesz)) == NULL) { syslog(LOG_ERR, "Cannot allocate Nhdr memory (note size %d bytes)", p_proc->m_pPhdr[prog_note].p_filesz); return CDH_NOK; } if (stream_read(&p_proc->streamer, p_proc->m_Nhdr, p_proc->m_pPhdr[prog_note].p_filesz) != CDH_OK) { syslog(LOG_ERR, "Cannot read note header"); return CDH_NOK; } p_proc->m_note_page_size = p_proc->m_pPhdr[prog_note].p_filesz; return CDH_OK; } cdh_status_t init_coredump(proc_info_t *p_proc) { if (p_proc == NULL) return CDH_NOK; if (p_proc->can_create_coredump) { char l_dst_filename[CORE_MAX_FILENAME_LENGTH]; snprintf(l_dst_filename, sizeof(l_dst_filename), CORE_FILE_PATTERN, CORE_TMP_DIRECTORY, p_proc->timestamp, p_proc->name, p_proc->pid); stream_init(&p_proc->streamer, 0, l_dst_filename); } else { stream_init(&p_proc->streamer, 0, NULL); } return CDH_OK; } cdh_status_t close_coredump(proc_info_t *p_proc) { stream_close(&p_proc->streamer); return CDH_OK; } cdh_status_t treat_coredump(proc_info_t *p_proc) { cdh_status_t ret = CDH_OK; /* open src and dest files, allocate read buffer */ if (init_coredump(p_proc) != CDH_OK) { syslog(LOG_ERR, "cannot init coredump system"); ret = CDH_NOK; goto finished; } if (read_elf_headers(p_proc) == CDH_OK) { /* TODO: No NOTES here leads to crash elsewhere!!! dlt_cdh_crashid.c: around line 76 */ if (read_notes(p_proc) != CDH_OK) { syslog(LOG_ERR, "cannot read NOTES"); ret = CDH_NOK; goto finished; } } else if (read_elf_headers(p_proc) != CDH_OK) { syslog(LOG_ERR, "cannot read ELF header"); ret = CDH_NOK; goto finished; } finished: /* In all cases, we try to finish to read/compress the coredump until the end */ if (stream_finish(&p_proc->streamer) != CDH_OK) syslog(LOG_ERR, "cannot finish coredump compression"); /* In all cases, let's close the files */ if (close_coredump(p_proc) != CDH_OK) syslog(LOG_ERR, "cannot close coredump system"); return ret; } dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_cpuinfo.h000066400000000000000000000015661446635226000234650ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_cpuinfo.h */ #ifndef DLT_CDH_CPUINFO_H #define DLT_CDH_CPUINFO_H #include "dlt_cdh.h" void get_registers(prstatus_t *prstatus, cdh_registers_t *registers); #endif /* DLT_CDH_CPUINFO_H */ dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_crashid.c000066400000000000000000000134561446635226000234330ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_crashid.c */ #include #include #include #include #include #include #include #include #include #include "dlt_cdh.h" #include "dlt_cdh_cpuinfo.h" #ifdef HAS_CITYHASH_C # include "city_c.h" #endif /*ARM32 specific */ /*#define REG_FRAME_POINTER 11 */ /*#define REG_INSTR_POINTER 12 */ /*#define REG_STACK_POINTER 13 */ /*#define REG_LINK_REGISTER 14 */ /*#define REG_PROC_COUNTER 15 */ #ifdef HAS_CITYHASH_C static cdh_status_t crashid_cityhash(proc_info_t *p_proc); #endif cdh_status_t get_phdr_num(proc_info_t *p_proc, unsigned int p_address, int *phdr_num) { int i = 0; if (phdr_num == NULL) return CDH_NOK; for (i = 0; i < p_proc->m_Ehdr.e_phnum; i++) if ((p_proc->m_pPhdr[i].p_vaddr < p_address) && (p_proc->m_pPhdr[i].p_vaddr + p_proc->m_pPhdr[i].p_memsz > p_address)) { *phdr_num = i; return CDH_OK; } *phdr_num = -1; return CDH_NOK; } /* Thanks to libunwind for the following definitions, which helps to */ #define ALIGN(x, a) (((x) + (a) - 1UL) & ~((a) - 1UL)) #define NOTE_SIZE(_hdr) (sizeof (_hdr) + ALIGN((_hdr).n_namesz, 4) + (_hdr).n_descsz) cdh_status_t get_crashed_registers(proc_info_t *p_proc) { int found = CDH_NOK; /* CDH_OK, when we find the page note associated to PID of crashed process */ unsigned int offset = 0; /* TODO: if no notes were found m_note_page_size was not set to 0 which leads to a crash in this loop because it is then used */ /* uninitialised here => this is an x86_64 issue */ while (found != CDH_OK && offset < p_proc->m_note_page_size) { /* Crash mentioned in TODO dlt_cdh_coredump.c line 163 */ ELF_Nhdr *ptr_note = (ELF_Nhdr *)(p_proc->m_Nhdr + offset); if (ptr_note->n_type == NT_PRSTATUS) { /* The first PRSTATUS note is the one of the crashed thread */ prstatus_t *prstatus = (prstatus_t *)((char *)ptr_note + sizeof(ELF_Nhdr) + ALIGN(ptr_note->n_namesz, 4)); p_proc->m_crashed_pid = prstatus->pr_pid; get_registers(prstatus, &p_proc->m_registers); found = CDH_OK; } offset += NOTE_SIZE(*ptr_note); } return found; } #ifdef HAS_CITYHASH_C cdh_status_t crashid_cityhash(proc_info_t *p_proc) { # define CRASHID_BUF_SIZE MAX_PROC_NAME_LENGTH + sizeof(uint64_t) char cityhash_in[CRASHID_BUF_SIZE]; uint64_t cityhash_result = 0; memcpy(cityhash_in, p_proc->name, MAX_PROC_NAME_LENGTH); memcpy(cityhash_in + MAX_PROC_NAME_LENGTH, &p_proc->m_crashid_phase1, sizeof(uint64_t)); cityhash_result = CityHash64(cityhash_in, CRASHID_BUF_SIZE); memcpy(p_proc->m_crashid, &cityhash_result, sizeof(uint64_t)); return CDH_OK; # undef CRASHID_BUF_SIZE } #endif /* HAS_CITYHASH_C */ cdh_status_t create_crashid(proc_info_t *p_proc) { uint32_t final_lr = 0; uint32_t final_pc = 0; int pc_phnum = 0; int lr_phnum = 0; /* translate address from virtual address (process point of view) to offset in the stack memory page */ #define ADDRESS_REBASE(__x, __phdr_num) (__x - p_proc->m_pPhdr[__phdr_num].p_vaddr) /* read value in the stack at position offset: +/- sizeof(), depends on stack growing upward or downward */ #define READ_STACK_VALUE(__offset, __type) (*(__type *)(stack_page + __offset - sizeof(__type))) get_phdr_num(p_proc, p_proc->m_registers.pc, &pc_phnum); final_pc = ADDRESS_REBASE(p_proc->m_registers.pc, pc_phnum); get_phdr_num(p_proc, p_proc->m_registers.lr, &lr_phnum); if (lr_phnum >= 0) final_lr = ADDRESS_REBASE(p_proc->m_registers.lr, lr_phnum); p_proc->m_crashid_phase1 = p_proc->signal << 24; p_proc->m_crashid_phase1 |= (uint64_t)final_lr; p_proc->m_crashid_phase1 <<= 32; p_proc->m_crashid_phase1 |= (uint64_t)final_pc; #ifdef HAS_CITYHASH_C crashid_cityhash(p_proc); #else memcpy(p_proc->m_crashid, &p_proc->m_crashid_phase1, sizeof(uint64_t)); #endif syslog(LOG_INFO, "Crash in \"%s\", thread=\"%s\", pid=%d, crashID=%" PRIx64 ", based on signal=%d, PC=0x%x, caller=0x%x", p_proc->name, p_proc->threadname, p_proc->pid, *((uint64_t *)p_proc->m_crashid), p_proc->signal, final_pc, final_lr ); return CDH_OK; } int write_crashid_to_filesystem(proc_info_t *p_proc) { FILE *crashid_file = NULL; if ((crashid_file = fopen(CRASHID_FILE, "wt")) == NULL) { syslog(LOG_ERR, "(pid=%d) cannot write crashid to %s: %s", p_proc->pid, CRASHID_FILE, strerror(errno)); return CDH_NOK; } fprintf(crashid_file, "%" PRIx64, *(uint64_t *)p_proc->m_crashid); fclose(crashid_file); return CDH_OK; } cdh_status_t treat_crash_data(proc_info_t *p_proc) { if (get_crashed_registers(p_proc) != CDH_OK) { syslog(LOG_ERR, "registers not found in notes"); return CDH_NOK; } if (create_crashid(p_proc) != CDH_OK) { syslog(LOG_ERR, "crashid not generated"); return CDH_NOK; } write_crashid_to_filesystem(p_proc); return CDH_OK; } dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_definitions.h000066400000000000000000000015531446635226000243310ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_definitions.h */ #ifndef DLT_CDH_DEFINITIONS_H #define DLT_CDH_DEFINITIONS_H typedef enum { CDH_OK = 0, CDH_NOK = -1 } cdh_status_t; #endif /* DLT_CDH_DEFINITIONS_H */ dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_streamer.c000066400000000000000000000127041446635226000236330ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_streamer.c */ #include #include #include #include #include #include "dlt_cdh_streamer.h" #define Z_CHUNK_SZ 1024 * 128 #define Z_MODE_STR "wb1" cdh_status_t stream_init(file_streamer_t *p_fs, const char *p_src_fname, const char *p_dst_fname) { if (p_fs == NULL) { syslog(LOG_ERR, "Internal pointer error in 'stream_init'"); return CDH_NOK; } memset(p_fs, 0, sizeof(file_streamer_t)); /* Allow to not save the coredump */ if (p_dst_fname == NULL) { p_fs->gz_dst_file = 0; } else { /* Create output file */ p_fs->gz_dst_file = gzopen(p_dst_fname, Z_MODE_STR); if (p_fs->gz_dst_file == Z_NULL) { /*return CDH_NOK; */ syslog(LOG_ERR, "Cannot open output filename <%s>. %s", p_dst_fname, strerror(errno)); p_fs->gz_dst_file = 0; } } if (p_fs->gz_dst_file == Z_NULL) syslog(LOG_WARNING, "The coredump will be processed, but not written"); /* Open input file */ if (p_src_fname == NULL) { p_fs->stream = stdin; } else if ((p_fs->stream = fopen(p_src_fname, "rb")) == NULL) { syslog(LOG_ERR, "Cannot open filename <%s>. %s", p_src_fname, strerror(errno)); return CDH_NOK; } /* Allocate read buffer */ if ((p_fs->read_buf = (unsigned char *)malloc(Z_CHUNK_SZ)) == NULL) { syslog(LOG_ERR, "Cannot allocate %d bytes for read buffer. %s", Z_CHUNK_SZ, strerror(errno)); return CDH_NOK; } return CDH_OK; } cdh_status_t stream_close(file_streamer_t *p_fs) { if (p_fs == NULL) { syslog(LOG_ERR, "Internal pointer error in 'stream_close'"); return CDH_NOK; } if (p_fs->gz_dst_file != NULL) { gzflush(p_fs->gz_dst_file, Z_FINISH); gzclose(p_fs->gz_dst_file); p_fs->gz_dst_file = NULL; } if (p_fs->stream != NULL) { fclose(p_fs->stream); p_fs->stream = NULL; } if (p_fs->read_buf != NULL) { free(p_fs->read_buf); p_fs->read_buf = NULL; } return CDH_OK; } cdh_status_t stream_read(file_streamer_t *p_fs, void *p_buf, unsigned int p_size) { unsigned int byte_read = 0; if (p_fs == NULL) { syslog(LOG_ERR, "Internal pointer error in 'stream_read'"); return CDH_NOK; } if (p_buf == NULL) { syslog(LOG_ERR, "Internal buffer pointer error in 'stream_read'"); return CDH_NOK; } if ((byte_read = fread(p_buf, 1, p_size, p_fs->stream)) != p_size) { syslog(LOG_WARNING, "Cannot read %d bytes from src. %s", p_size, strerror(errno)); return CDH_NOK; } p_fs->offset += byte_read; if (p_fs->gz_dst_file != NULL) gzwrite(p_fs->gz_dst_file, p_buf, byte_read); return CDH_OK; } int stream_finish(file_streamer_t *p_fs) { if ((p_fs == NULL) || (p_fs->stream == NULL)) { syslog(LOG_ERR, "Internal pointer error in 'stream_move_ahead'"); return CDH_NOK; } while (!feof(p_fs->stream)) { size_t read_bytes = fread(p_fs->read_buf, 1, Z_CHUNK_SZ, p_fs->stream); if (p_fs->gz_dst_file != NULL) gzwrite(p_fs->gz_dst_file, p_fs->read_buf, read_bytes); p_fs->offset += read_bytes; if (ferror(p_fs->stream)) { syslog(LOG_WARNING, "Error reading from the src stream: %s", strerror(errno)); return CDH_NOK; } } return CDH_OK; } int stream_move_to_offest(file_streamer_t *p_fs, unsigned int p_offset) { int bytes_to_read = 0; if (p_fs == NULL) { syslog(LOG_ERR, "Internal pointer error in 'stream_move_to_offest'"); return CDH_NOK; } bytes_to_read = p_offset - p_fs->offset; return stream_move_ahead(p_fs, bytes_to_read); } int stream_move_ahead(file_streamer_t *p_fs, unsigned int p_nbbytes) { int bytes_to_read = p_nbbytes; if (p_fs == NULL) { syslog(LOG_ERR, "Internal pointer error in 'stream_move_ahead'"); return CDH_NOK; } while (bytes_to_read > 0) { size_t chunk_size = bytes_to_read > Z_CHUNK_SZ ? Z_CHUNK_SZ : bytes_to_read; size_t read_bytes = fread(p_fs->read_buf, 1, chunk_size, p_fs->stream); if (read_bytes != chunk_size) { syslog(LOG_WARNING, "Cannot move ahead by %d bytes from src. Read %lu bytes", p_nbbytes, read_bytes); return CDH_NOK; } if (p_fs->gz_dst_file != 0) gzwrite(p_fs->gz_dst_file, p_fs->read_buf, chunk_size); bytes_to_read -= chunk_size; } p_fs->offset += p_nbbytes; return CDH_OK; } unsigned int stream_get_offset(file_streamer_t *p_fs) { if (p_fs == NULL) { syslog(LOG_ERR, "Internal pointer error in 'stream_get_offset'"); return CDH_NOK; } return p_fs->offset; } dlt-daemon-2.18.10/src/core_dump_handler/dlt_cdh_streamer.h000066400000000000000000000027471446635226000236460ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_cdh_streamer.h */ #ifndef DLT_CDH_STREAMER_H #define DLT_CDH_STREAMER_H #include #include #include "dlt_cdh_definitions.h" typedef struct { FILE *stream; unsigned int offset; gzFile gz_dst_file; unsigned char *read_buf; } file_streamer_t; cdh_status_t stream_init(file_streamer_t *p_fs, const char *p_src_fname, const char *p_dst_fname); cdh_status_t stream_close(file_streamer_t *p_fs); cdh_status_t stream_read(file_streamer_t *p_fs, void *p_buf, unsigned int p_size); cdh_status_t stream_finish(file_streamer_t *p_fs); cdh_status_t stream_move_to_offest(file_streamer_t *p_fs, unsigned int p_offset); cdh_status_t stream_move_ahead(file_streamer_t *p_fs, unsigned int p_nbbytes); unsigned int stream_get_offset(file_streamer_t *p_fs); #endif /* #ifndef DLT_CDH_STREAMER_H */ dlt-daemon-2.18.10/src/core_dump_handler/i686/000077500000000000000000000000001446635226000206545ustar00rootroot00000000000000dlt-daemon-2.18.10/src/core_dump_handler/i686/dlt_cdh_cpuinfo.c000066400000000000000000000020771446635226000241520ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file i686/dlt_cdh_cpuinfo.c */ #include "../dlt_cdh_cpuinfo.h" void get_registers(prstatus_t *prstatus, cdh_registers_t *registers) { struct user_regs_struct *ptr_reg = (struct user_regs_struct *)prstatus->pr_reg; registers->pc = ptr_reg->ecx; /* [REG_PROC_COUNTER]; */ registers->ip = ptr_reg->eip; /* [REG_INSTR_POINTER]; */ registers->lr = ptr_reg->ebp; /* [REG_LINK_REGISTER]; */ } dlt-daemon-2.18.10/src/core_dump_handler/x86_64/000077500000000000000000000000001446635226000211165ustar00rootroot00000000000000dlt-daemon-2.18.10/src/core_dump_handler/x86_64/dlt_cdh_cpuinfo.c000066400000000000000000000021011446635226000244000ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Magneti Marelli http://www.magnetimarelli.com * \author Lutz Helwing * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file x86_64/dlt_cdh_cpuinfo.c */ #include "../dlt_cdh_cpuinfo.h" void get_registers(prstatus_t *prstatus, cdh_registers_t *registers) { struct user_regs_struct *ptr_reg = (struct user_regs_struct *)prstatus->pr_reg; registers->pc = ptr_reg->rcx; /* [REG_PROC_COUNTER]; */ registers->ip = ptr_reg->rip; /* [REG_INSTR_POINTER]; */ registers->lr = ptr_reg->rsp; /* [REG_LINK_REGISTER]; */ } dlt-daemon-2.18.10/src/daemon/000077500000000000000000000000001446635226000157515ustar00rootroot00000000000000dlt-daemon-2.18.10/src/daemon/CMakeLists.txt000066400000000000000000000064731446635226000205230ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) message(STATUS "Added ${systemd_SRCS} to dlt-daemon") endif() set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_client.c dlt_daemon_common.c dlt_daemon_connection.c dlt_daemon_event_handler.c dlt_daemon_offline_logstorage.c dlt_daemon_serial.c dlt_daemon_socket.c dlt_daemon_unix_socket.c ${PROJECT_SOURCE_DIR}/src/gateway/dlt_gateway.c ${PROJECT_SOURCE_DIR}/src/lib/dlt_client.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_common.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_config_file_parser.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_multiple_files.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_protocol.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_user_shared.c ${PROJECT_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c ${PROJECT_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage_behavior.c ) if(WITH_DLT_SHM_ENABLE) set(dlt_daemon_SRCS ${dlt_daemon_SRCS} ${PROJECT_SOURCE_DIR}/src/shared/dlt_shm.c) endif() if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux|CYGWIN") set(RT_LIBRARY rt) set(SOCKET_LIBRARY "") else() set(RT_LIBRARY "") set(SOCKET_LIBRARY socket) endif() if(WITH_UDP_CONNECTION) include_directories(${PROJECT_SOURCE_DIR}/src/daemon/udp_connection) add_definitions(-DUDP_CONNECTION_SUPPORT) set(dlt_daemon_SRCS ${dlt_daemon_SRCS} ${PROJECT_SOURCE_DIR}/src/daemon/udp_connection/dlt_daemon_udp_socket.c) endif(WITH_UDP_CONNECTION) add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS}) target_link_libraries(dlt-daemon ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) if (WITH_SYSTEMD_SOCKET_ACTIVATION) target_link_libraries(dlt-daemon systemd) endif() if (WITH_DLT_LOGSTORAGE_GZIP) target_link_libraries(dlt-daemon ${ZLIB_LIBRARY}) endif() install(TARGETS dlt-daemon RUNTIME DESTINATION bin PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ COMPONENT base) if (WITH_DLT_UNIT_TESTS) set(library_SRCS ${dlt_daemon_SRCS}) if (WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) set(library_SRCS ${library_SRCS} ${systemd_SRCS}) endif(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) add_library(dlt_daemon ${library_SRCS}) target_link_libraries(dlt_daemon ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS dlt_daemon RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/static COMPONENT base) endif(WITH_DLT_UNIT_TESTS) INSTALL(FILES dlt.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) if (WITH_DLT_LOG_LEVEL_APP_CONFIG) INSTALL(FILES dlt-log-levels.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) endif() dlt-daemon-2.18.10/src/daemon/dlt-daemon.c000066400000000000000000004244561446635226000201600ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-daemon.c */ #include #include #include /* for printf() and fprintf() */ #include /* for socket(), connect(), (), and recv() */ #include #include /* for sockaddr_in and inet_addr() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() and access */ #include #include #include #include #include #include #ifdef linux # include #endif #include #include #include #if defined(linux) && defined(__NR_statx) # include #endif #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE # ifdef linux # include # endif # ifdef __QNX__ # include # endif #endif #include "dlt_types.h" #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common_cfg.h" #include "dlt_daemon_socket.h" #include "dlt_daemon_unix_socket.h" #include "dlt_daemon_serial.h" #include "dlt_daemon_client.h" #include "dlt_daemon_connection.h" #include "dlt_daemon_event_handler.h" #include "dlt_daemon_offline_logstorage.h" #include "dlt_gateway.h" #ifdef UDP_CONNECTION_SUPPORT # include "dlt_daemon_udp_socket.h" #endif #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) # include "sd-daemon.h" #endif /** * \defgroup daemon DLT Daemon * \addtogroup daemon \{ */ static int dlt_daemon_log_internal(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *str, int verbose); static int dlt_daemon_check_numeric_setting(char *token, char *value, unsigned long *data); #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE static uint32_t watchdog_trigger_interval; /* watchdog trigger interval in [s] */ #endif /* used in main event loop and signal handler */ int g_exit = 0; int g_signo = 0; /* used for value from conf file */ static int value_length = 1024; static char dlt_timer_conn_types[DLT_TIMER_UNKNOWN + 1] = { [DLT_TIMER_PACKET] = DLT_CONNECTION_ONE_S_TIMER, [DLT_TIMER_ECU] = DLT_CONNECTION_SIXTY_S_TIMER, #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE [DLT_TIMER_SYSTEMD] = DLT_CONNECTION_SYSTEMD_TIMER, #endif [DLT_TIMER_GATEWAY] = DLT_CONNECTION_GATEWAY_TIMER, [DLT_TIMER_UNKNOWN] = DLT_CONNECTION_TYPE_MAX }; static char dlt_timer_names[DLT_TIMER_UNKNOWN + 1][32] = { [DLT_TIMER_PACKET] = "Timing packet", [DLT_TIMER_ECU] = "ECU version", #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE [DLT_TIMER_SYSTEMD] = "Systemd watchdog", #endif [DLT_TIMER_GATEWAY] = "Gateway", [DLT_TIMER_UNKNOWN] = "Unknown timer" }; #ifdef __QNX__ static int dlt_timer_pipes[DLT_TIMER_UNKNOWN][2] = { /* [timer_id] = {read_pipe, write_pipe} */ [DLT_TIMER_PACKET] = {DLT_FD_INIT, DLT_FD_INIT}, [DLT_TIMER_ECU] = {DLT_FD_INIT, DLT_FD_INIT}, #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE [DLT_TIMER_SYSTEMD] = {DLT_FD_INIT, DLT_FD_INIT}, #endif [DLT_TIMER_GATEWAY] = {DLT_FD_INIT, DLT_FD_INIT} }; static pthread_t timer_threads[DLT_TIMER_UNKNOWN] = { [DLT_TIMER_PACKET] = 0, [DLT_TIMER_ECU] = 0, #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE [DLT_TIMER_SYSTEMD] = 0, #endif [DLT_TIMER_GATEWAY] = 0 }; static DltDaemonPeriodicData *timer_data[DLT_TIMER_UNKNOWN] = { [DLT_TIMER_PACKET] = NULL, [DLT_TIMER_ECU] = NULL, #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE [DLT_TIMER_SYSTEMD] = NULL, #endif [DLT_TIMER_GATEWAY] = NULL }; void close_pipes(int fds[2]) { if (fds[0] > 0) { close(fds[0]); fds[0] = DLT_FD_INIT; } if (fds[1] > 0) { close(fds[1]); fds[1] = DLT_FD_INIT; } } #endif // __QNX__ /** * Print usage information of tool. */ void usage() { char version[DLT_DAEMON_TEXTBUFSIZE]; dlt_get_version(version, DLT_DAEMON_TEXTBUFSIZE); /*printf("DLT logging daemon %s %s\n", _DLT_PACKAGE_VERSION, _DLT_PACKAGE_VERSION_STATE); */ /*printf("Compile options: %s %s %s %s",_DLT_SYSTEMD_ENABLE, _DLT_SYSTEMD_WATCHDOG_ENABLE, _DLT_TEST_ENABLE, _DLT_SHM_ENABLE); */ printf("%s", version); printf("Usage: dlt-daemon [options]\n"); printf("Options:\n"); printf(" -d Daemonize\n"); printf(" -h Usage\n"); printf(" -c filename DLT daemon configuration file (Default: " CONFIGURATION_FILES_DIR "/dlt.conf)\n"); #ifdef DLT_DAEMON_USE_FIFO_IPC printf(" -t directory Directory for local fifo and user-pipes (Default: /tmp)\n"); printf(" (Applications wanting to connect to a daemon using a\n"); printf(" custom directory need to be started with the environment \n"); printf(" variable DLT_PIPE_DIR set appropriately)\n"); #endif #ifdef DLT_SHM_ENABLE printf(" -s filename The file name to create the share memory (Default: /dlt-shm)\n"); printf(" (Applications wanting to connect to a daemon using a\n"); printf(" custom shm name need to be started with the environment \n"); printf(" variable DLT_SHM_NAME set appropriately)\n"); #endif printf(" -p port port to monitor for incoming requests (Default: 3490)\n"); printf(" (Applications wanting to connect to a daemon using a custom\n"); printf(" port need to be started with the environment variable\n"); printf(" DLT_DAEMON_TCP_PORT set appropriately)\n"); #ifdef DLT_LOG_LEVEL_APP_CONFIG printf(" -a filename The filename for load default app id log levels (Default: " CONFIGURATION_FILES_DIR "/dlt-log-levels.conf)\n"); #endif # } /* usage() */ /** * Option handling */ int option_handling(DltDaemonLocal *daemon_local, int argc, char *argv[]) { int c; char options[255]; memset(options, 0, sizeof options); const char *const default_options = "hdc:t:p:"; strcpy(options, default_options); if (daemon_local == 0) { fprintf (stderr, "Invalid parameter passed to option_handling()\n"); return -1; } /* Initialize flags */ memset(daemon_local, 0, sizeof(DltDaemonLocal)); /* default values */ daemon_local->flags.port = DLT_DAEMON_TCP_PORT; #ifdef DLT_DAEMON_USE_FIFO_IPC dlt_log_set_fifo_basedir(DLT_USER_IPC_PATH); #endif #ifdef DLT_SHM_ENABLE strncpy(dltShmName, "/dlt-shm", NAME_MAX); #endif opterr = 0; #ifdef DLT_SHM_ENABLE strcpy(options + strlen(options), "s:"); #endif #ifdef DLT_LOG_LEVEL_APP_CONFIG strcpy(options + strlen(options), "a:"); #endif while ((c = getopt(argc, argv, options)) != -1) switch (c) { case 'd': { daemon_local->flags.dflag = 1; break; } case 'c': { strncpy(daemon_local->flags.cvalue, optarg, NAME_MAX); break; } #ifdef DLT_LOG_LEVEL_APP_CONFIG case 'a': { strncpy(daemon_local->flags.avalue, optarg, NAME_MAX); break; } #endif #ifdef DLT_DAEMON_USE_FIFO_IPC case 't': { dlt_log_set_fifo_basedir(optarg); break; } #endif #ifdef DLT_SHM_ENABLE case 's': { strncpy(dltShmName, optarg, NAME_MAX); break; } #endif case 'p': { daemon_local->flags.port = (unsigned int) atoi(optarg); if (daemon_local->flags.port == 0) { fprintf (stderr, "Invalid port `%s' specified.\n", optarg); return -1; } break; } case 'h': { usage(); return -2; /* return no error */ } case '?': { if ((optopt == 'c') || (optopt == 't') || (optopt == 'p') #ifdef DLT_LOG_LEVEL_APP_CONFIG || (optopt == 'a') #endif ) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", (uint32_t)optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { fprintf (stderr, "Invalid option, this should never occur!\n"); return -1; } } /* switch() */ #ifdef DLT_DAEMON_USE_FIFO_IPC snprintf(daemon_local->flags.userPipesDir, DLT_PATH_MAX, "%s/dltpipes", dltFifoBaseDir); snprintf(daemon_local->flags.daemonFifoName, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir); #endif #ifdef DLT_SHM_ENABLE strncpy(daemon_local->flags.dltShmName, dltShmName, NAME_MAX); #endif return 0; } /* option_handling() */ /** * Option file parser */ int option_file_parser(DltDaemonLocal *daemon_local) { FILE *pFile; char line[value_length - 1]; char token[value_length]; char value[value_length]; char *pch; const char *filename; ssize_t n; /* set default values for configuration */ daemon_local->flags.sharedMemorySize = DLT_SHM_SIZE; daemon_local->flags.sendMessageTime = 0; daemon_local->flags.offlineTraceDirectory[0] = 0; daemon_local->flags.offlineTraceFileSize = 1000000; daemon_local->flags.offlineTraceMaxSize = 4000000; daemon_local->flags.offlineTraceFilenameTimestampBased = true; daemon_local->flags.loggingMode = DLT_LOG_TO_CONSOLE; daemon_local->flags.loggingLevel = LOG_INFO; #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC n = snprintf(daemon_local->flags.loggingFilename, sizeof(daemon_local->flags.loggingFilename), "%s/dlt.log", DLT_USER_IPC_PATH); #else /* DLT_DAEMON_USE_FIFO_IPC */ n = snprintf(daemon_local->flags.loggingFilename, sizeof(daemon_local->flags.loggingFilename), "%s/dlt.log", dltFifoBaseDir); #endif if (n < 0 || (size_t)n > sizeof(daemon_local->flags.loggingFilename)) { dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n", __func__, n, daemon_local->flags.loggingFilename); } daemon_local->flags.enableLoggingFileLimit = false; daemon_local->flags.loggingFileSize = 250000; daemon_local->flags.loggingFileMaxSize = 1000000; daemon_local->timeoutOnSend = 4; daemon_local->RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local->RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local->RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; daemon_local->daemonFifoSize = 0; daemon_local->flags.sendECUSoftwareVersion = 0; memset(daemon_local->flags.pathToECUSoftwareVersion, 0, sizeof(daemon_local->flags.pathToECUSoftwareVersion)); daemon_local->flags.sendTimezone = 0; daemon_local->flags.offlineLogstorageMaxDevices = 0; daemon_local->flags.offlineLogstorageDirPath[0] = 0; daemon_local->flags.offlineLogstorageTimestamp = 1; daemon_local->flags.offlineLogstorageDelimiter = '_'; daemon_local->flags.offlineLogstorageMaxCounter = UINT_MAX; daemon_local->flags.offlineLogstorageMaxCounterIdx = 0; daemon_local->flags.offlineLogstorageCacheSize = 30000; /* 30MB */ dlt_daemon_logstorage_set_logstorage_cache_size( daemon_local->flags.offlineLogstorageCacheSize); strncpy(daemon_local->flags.ctrlSockPath, DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH, sizeof(daemon_local->flags.ctrlSockPath)); #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC snprintf(daemon_local->flags.appSockPath, DLT_IPC_PATH_MAX, "%s/dlt", DLT_USER_IPC_PATH); if (strlen(DLT_USER_IPC_PATH) > DLT_IPC_PATH_MAX) fprintf(stderr, "Provided path too long...trimming it to path[%s]\n", daemon_local->flags.appSockPath); #else /* DLT_DAEMON_USE_FIFO_IPC */ memset(daemon_local->flags.daemonFifoGroup, 0, sizeof(daemon_local->flags.daemonFifoGroup)); #endif daemon_local->flags.gatewayMode = 0; strncpy(daemon_local->flags.gatewayConfigFile, DLT_GATEWAY_CONFIG_PATH, DLT_DAEMON_FLAG_MAX); daemon_local->flags.autoResponseGetLogInfoOption = 7; daemon_local->flags.contextLogLevel = DLT_LOG_INFO; daemon_local->flags.contextTraceStatus = DLT_TRACE_STATUS_OFF; daemon_local->flags.enforceContextLLAndTS = 0; /* default is off */ #ifdef UDP_CONNECTION_SUPPORT daemon_local->UDPConnectionSetup = MULTICAST_CONNECTION_ENABLED; strncpy(daemon_local->UDPMulticastIPAddress, MULTICASTIPADDRESS, MULTICASTIP_MAX_SIZE - 1); daemon_local->UDPMulticastIPPort = MULTICASTIPPORT; #endif daemon_local->flags.ipNodes = NULL; daemon_local->flags.injectionMode = 1; /* open configuration file */ if (daemon_local->flags.cvalue[0]) filename = daemon_local->flags.cvalue; else filename = CONFIGURATION_FILES_DIR "/dlt.conf"; /*printf("Load configuration from file: %s\n",filename); */ pFile = fopen (filename, "r"); if (pFile != NULL) { while (1) { /* fetch line from configuration file */ if (fgets (line, value_length - 1, pFile) != NULL) { pch = strtok (line, " =\r\n"); token[0] = 0; value[0] = 0; while (pch != NULL) { if (strcmp(pch, "#") == 0) break; if (token[0] == 0) { strncpy(token, pch, sizeof(token) - 1); token[sizeof(token) - 1] = 0; } else { strncpy(value, pch, sizeof(value) - 1); value[sizeof(value) - 1] = 0; break; } pch = strtok (NULL, " =\r\n"); } if (token[0] && value[0]) { /* parse arguments here */ if (strcmp(token, "Verbose") == 0) { daemon_local->flags.vflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "PrintASCII") == 0) { daemon_local->flags.aflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "PrintHex") == 0) { daemon_local->flags.xflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "PrintHeadersOnly") == 0) { daemon_local->flags.sflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "SendSerialHeader") == 0) { daemon_local->flags.lflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "SendContextRegistration") == 0) { daemon_local->flags.rflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "SendContextRegistrationOption") == 0) { daemon_local->flags.autoResponseGetLogInfoOption = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "SendMessageTime") == 0) { daemon_local->flags.sendMessageTime = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "RS232SyncSerialHeader") == 0) { daemon_local->flags.mflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "TCPSyncSerialHeader") == 0) { daemon_local->flags.nflag = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "RS232DeviceName") == 0) { strncpy(daemon_local->flags.yvalue, value, NAME_MAX); daemon_local->flags.yvalue[NAME_MAX] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "RS232Baudrate") == 0) { strncpy(daemon_local->flags.bvalue, value, NAME_MAX); daemon_local->flags.bvalue[NAME_MAX] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "ECUId") == 0) { strncpy(daemon_local->flags.evalue, value, NAME_MAX); daemon_local->flags.evalue[NAME_MAX] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "PersistanceStoragePath") == 0) { strncpy(daemon_local->flags.ivalue, value, NAME_MAX); daemon_local->flags.ivalue[NAME_MAX] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "LoggingMode") == 0) { daemon_local->flags.loggingMode = (DltLoggingMode)atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "LoggingLevel") == 0) { daemon_local->flags.loggingLevel = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "LoggingFilename") == 0) { strncpy(daemon_local->flags.loggingFilename, value, sizeof(daemon_local->flags.loggingFilename) - 1); daemon_local->flags.loggingFilename[sizeof(daemon_local->flags.loggingFilename) - 1] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "EnableLoggingFileLimit") == 0) { daemon_local->flags.enableLoggingFileLimit = (bool)atoi(value); } else if (strcmp(token, "LoggingFileSize") == 0) { daemon_local->flags.loggingFileSize = atoi(value); } else if (strcmp(token, "LoggingFileMaxSize") == 0) { daemon_local->flags.loggingFileMaxSize = atoi(value); } else if (strcmp(token, "TimeOutOnSend") == 0) { daemon_local->timeoutOnSend = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "RingbufferMinSize") == 0) { if (dlt_daemon_check_numeric_setting(token, value, &(daemon_local->RingbufferMinSize)) < 0) return -1; } else if (strcmp(token, "RingbufferMaxSize") == 0) { if (dlt_daemon_check_numeric_setting(token, value, &(daemon_local->RingbufferMaxSize)) < 0) return -1; } else if (strcmp(token, "RingbufferStepSize") == 0) { if (dlt_daemon_check_numeric_setting(token, value, &(daemon_local->RingbufferStepSize)) < 0) return -1; } else if (strcmp(token, "SharedMemorySize") == 0) { daemon_local->flags.sharedMemorySize = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "OfflineTraceDirectory") == 0) { strncpy(daemon_local->flags.offlineTraceDirectory, value, sizeof(daemon_local->flags.offlineTraceDirectory) - 1); daemon_local->flags.offlineTraceDirectory[sizeof(daemon_local->flags.offlineTraceDirectory) - 1] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "OfflineTraceFileSize") == 0) { daemon_local->flags.offlineTraceFileSize = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "OfflineTraceMaxSize") == 0) { daemon_local->flags.offlineTraceMaxSize = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "OfflineTraceFileNameTimestampBased") == 0) { daemon_local->flags.offlineTraceFilenameTimestampBased = (bool)atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "SendECUSoftwareVersion") == 0) { daemon_local->flags.sendECUSoftwareVersion = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "PathToECUSoftwareVersion") == 0) { strncpy(daemon_local->flags.pathToECUSoftwareVersion, value, sizeof(daemon_local->flags.pathToECUSoftwareVersion) - 1); daemon_local->flags.pathToECUSoftwareVersion[sizeof(daemon_local->flags.pathToECUSoftwareVersion) - 1] = 0; /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "SendTimezone") == 0) { daemon_local->flags.sendTimezone = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "OfflineLogstorageMaxDevices") == 0) { daemon_local->flags.offlineLogstorageMaxDevices = (uint32_t) atoi(value); } else if (strcmp(token, "OfflineLogstorageDirPath") == 0) { strncpy(daemon_local->flags.offlineLogstorageDirPath, value, sizeof(daemon_local->flags.offlineLogstorageDirPath) - 1); } else if (strcmp(token, "OfflineLogstorageTimestamp") == 0) { /* Check if set to 0, default otherwise */ if (atoi(value) == 0) daemon_local->flags.offlineLogstorageTimestamp = 0; } else if (strcmp(token, "OfflineLogstorageDelimiter") == 0) { /* Check if valid punctuation, default otherwise*/ if (ispunct((char)value[0])) daemon_local->flags.offlineLogstorageDelimiter = (char)value[0]; } else if (strcmp(token, "OfflineLogstorageMaxCounter") == 0) { daemon_local->flags.offlineLogstorageMaxCounter = (unsigned int) atoi(value); daemon_local->flags.offlineLogstorageMaxCounterIdx = (unsigned int) strlen(value); } else if (strcmp(token, "OfflineLogstorageCacheSize") == 0) { daemon_local->flags.offlineLogstorageCacheSize = (unsigned int)atoi(value); dlt_daemon_logstorage_set_logstorage_cache_size( daemon_local->flags.offlineLogstorageCacheSize); } else if (strcmp(token, "ControlSocketPath") == 0) { memset( daemon_local->flags.ctrlSockPath, 0, DLT_DAEMON_FLAG_MAX); strncpy( daemon_local->flags.ctrlSockPath, value, DLT_DAEMON_FLAG_MAX - 1); } else if (strcmp(token, "GatewayMode") == 0) { daemon_local->flags.gatewayMode = atoi(value); /*printf("Option: %s=%s\n",token,value); */ } else if (strcmp(token, "GatewayConfigFile") == 0) { memset( daemon_local->flags.gatewayConfigFile, 0, DLT_DAEMON_FLAG_MAX); strncpy( daemon_local->flags.gatewayConfigFile, value, DLT_DAEMON_FLAG_MAX - 1); } else if (strcmp(token, "ContextLogLevel") == 0) { int const intval = atoi(value); if ((intval >= DLT_LOG_OFF) && (intval <= DLT_LOG_VERBOSE)) { daemon_local->flags.contextLogLevel = intval; printf("Option: %s=%s\n", token, value); } else { fprintf(stderr, "Invalid value for ContextLogLevel: %i. Must be in range [%i..%i]\n", intval, DLT_LOG_OFF, DLT_LOG_VERBOSE); } } else if (strcmp(token, "ContextTraceStatus") == 0) { int const intval = atoi(value); if ((intval >= DLT_TRACE_STATUS_OFF) && (intval <= DLT_TRACE_STATUS_ON)) { daemon_local->flags.contextTraceStatus = intval; printf("Option: %s=%s\n", token, value); } else { fprintf(stderr, "Invalid value for ContextTraceStatus: %i. Must be in range [%i..%i]\n", intval, DLT_TRACE_STATUS_OFF, DLT_TRACE_STATUS_ON); } } else if (strcmp(token, "ForceContextLogLevelAndTraceStatus") == 0) { int const intval = atoi(value); if ((intval >= 0) && (intval <= 1)) { daemon_local->flags.enforceContextLLAndTS = intval; printf("Option: %s=%s\n", token, value); } else { fprintf(stderr, "Invalid value for ForceContextLogLevelAndTraceStatus: %i. Must be 0, 1\n", intval); } } #ifdef DLT_DAEMON_USE_FIFO_IPC else if (strcmp(token, "DaemonFIFOSize") == 0) { if (dlt_daemon_check_numeric_setting(token, value, &(daemon_local->daemonFifoSize)) < 0) return -1; #ifndef __linux__ printf("Option DaemonFIFOSize is set but only supported on Linux. Ignored.\n"); #endif } else if (strcmp(token, "DaemonFifoGroup") == 0) { strncpy(daemon_local->flags.daemonFifoGroup, value, NAME_MAX); daemon_local->flags.daemonFifoGroup[NAME_MAX] = 0; } #endif #ifdef UDP_CONNECTION_SUPPORT else if (strcmp(token, "UDPConnectionSetup") == 0) { const long longval = strtol(value, NULL, 10); if ((longval == MULTICAST_CONNECTION_DISABLED) || (longval == MULTICAST_CONNECTION_ENABLED)) { daemon_local->UDPConnectionSetup = longval; printf("Option: %s=%s\n", token, value); } else { daemon_local->UDPConnectionSetup = MULTICAST_CONNECTION_DISABLED; fprintf(stderr, "Invalid value for UDPConnectionSetup set to default %ld\n", longval); } } else if (strcmp(token, "UDPMulticastIPAddress") == 0) { strncpy(daemon_local->UDPMulticastIPAddress, value, MULTICASTIP_MAX_SIZE - 1); } else if (strcmp(token, "UDPMulticastIPPort") == 0) { daemon_local->UDPMulticastIPPort = strtol(value, NULL, 10); } #endif else if (strcmp(token, "BindAddress") == 0) { DltBindAddress_t *newNode = NULL; DltBindAddress_t *temp = NULL; char *tok = strtok(value, ",;"); if (tok != NULL) { daemon_local->flags.ipNodes = calloc(1, sizeof(DltBindAddress_t)); if (daemon_local->flags.ipNodes == NULL) { dlt_vlog(LOG_ERR, "Could not allocate for IP list\n"); fclose(pFile); return -1; } else { strncpy(daemon_local->flags.ipNodes->ip, tok, sizeof(daemon_local->flags.ipNodes->ip) - 1); daemon_local->flags.ipNodes->next = NULL; temp = daemon_local->flags.ipNodes; tok = strtok(NULL, ",;"); while (tok != NULL) { newNode = calloc(1, sizeof(DltBindAddress_t)); if (newNode == NULL) { dlt_vlog(LOG_ERR, "Could not allocate for IP list\n"); fclose(pFile); return -1; } else { strncpy(newNode->ip, tok, sizeof(newNode->ip) - 1); } temp->next = newNode; temp = temp->next; tok = strtok(NULL, ",;"); } } } else { dlt_vlog(LOG_WARNING, "BindAddress option is empty\n"); } } else if (strcmp(token, "InjectionMode") == 0) { daemon_local->flags.injectionMode = atoi(value); } else { fprintf(stderr, "Unknown option: %s=%s\n", token, value); } } } else { break; } } fclose (pFile); } else { fprintf(stderr, "Cannot open configuration file: %s\n", filename); } return 0; } #ifdef DLT_LOG_LEVEL_APP_CONFIG /** * Load configuration file parser */ static int compare_app_id_conf(const void *lhs, const void *rhs) { return strncmp(((DltDaemonContextLogSettings *)lhs)->apid, ((DltDaemonContextLogSettings *)rhs)->apid, DLT_ID_SIZE); } int app_id_default_log_level_config_parser(DltDaemon *daemon, DltDaemonLocal *daemon_local) { FILE *pFile; char line[value_length - 1]; char app_id_value[value_length]; char ctx_id_value[value_length]; DltLogLevelType log_level_value; char *pch; const char *filename; /* open configuration file */ filename = daemon_local->flags.avalue[0] ? daemon_local->flags.avalue : CONFIGURATION_FILES_DIR "/dlt-log-levels.conf"; pFile = fopen(filename, "r"); if (pFile == NULL) { dlt_vlog(LOG_WARNING, "Cannot open app log level configuration%s\n", filename); return -errno; } /* fetch lines from configuration file */ while (fgets(line, value_length - 1, pFile) != NULL) { pch = strtok(line, " \t"); memset(app_id_value, 0, value_length); memset(ctx_id_value, 0, value_length); log_level_value = DLT_LOG_MAX; /* ignore comments and new lines*/ if (strncmp(pch, "#", 1) == 0 || strncmp(pch, "\n", 1) == 0 || strlen(pch) < 1) continue; strncpy(app_id_value, pch, sizeof(app_id_value) - 1); app_id_value[sizeof(app_id_value) - 1] = 0; if (strlen(app_id_value) == 0 || strlen(app_id_value) > DLT_ID_SIZE) { if (app_id_value[strlen(app_id_value) - 1] == '\n') { dlt_vlog(LOG_WARNING, "Missing log level for apid %s in log settings\n", app_id_value); } else { dlt_vlog(LOG_WARNING, "Invalid apid for log settings settings: app id: %s\n", app_id_value); } continue; } char *pch_next1 = strtok(NULL, " \t"); char *pch_next2 = strtok(NULL, " \t"); char *log_level; /* no context id given, log level is next token */ if (pch_next2 == NULL || pch_next2[0] == '#') { log_level = pch_next1; } else { /* context id is given, log level is second to next token */ log_level = pch_next2; /* next token is token id */ strncpy(ctx_id_value, pch_next1, sizeof(ctx_id_value) - 1); if (strlen(ctx_id_value) == 0 || strlen(app_id_value) > DLT_ID_SIZE) { dlt_vlog(LOG_WARNING, "Invalid ctxid for log settings: app id: %s " "(skipping line)\n", app_id_value); continue; } ctx_id_value[sizeof(ctx_id_value) - 1] = 0; } errno = 0; log_level_value = strtol(log_level, NULL, 10); if (errno != 0 || log_level_value >= DLT_LOG_MAX || log_level_value <= DLT_LOG_DEFAULT) { dlt_vlog(LOG_WARNING, "Invalid log level (%i), app id %s, conversion error: %s\n", log_level_value, app_id_value, strerror(errno)); continue; } DltDaemonContextLogSettings *settings = dlt_daemon_find_configured_app_id_ctx_id_settings( daemon, app_id_value, NULL); if (settings != NULL && strncmp(settings->ctid, ctx_id_value, DLT_ID_SIZE) == 0) { if (strlen(ctx_id_value) > 0) { dlt_vlog(LOG_WARNING, "Appid %s with ctxid %s is already configured, skipping " "duplicated entry\n", app_id_value, ctx_id_value); } else { dlt_vlog(LOG_WARNING, "Appid %s is already configured, skipping duplicated entry\n", app_id_value); } continue; } /* allocate one more element in the trace load settings */ DltDaemonContextLogSettings *tmp = realloc(daemon->app_id_log_level_settings, (++daemon->num_app_id_log_level_settings) * sizeof(DltDaemonContextLogSettings)); if (tmp == NULL) { dlt_log(LOG_CRIT, "Failed to allocate memory for app load settings\n"); continue; } daemon->app_id_log_level_settings = tmp; /* update newly created entry */ settings = &daemon->app_id_log_level_settings [daemon->num_app_id_log_level_settings -1]; memset(settings, 0, sizeof(DltDaemonContextLogSettings)); memcpy(settings->apid, app_id_value, DLT_ID_SIZE); memcpy(settings->ctid, ctx_id_value, DLT_ID_SIZE); settings->log_level = log_level_value; /* make sure ids are 0 terminated for printing */ char apid_buf[DLT_ID_SIZE + 1] = {0}; char ctid_buf[DLT_ID_SIZE + 1] = {0}; memcpy(apid_buf, app_id_value, DLT_ID_SIZE); memcpy(ctid_buf, ctx_id_value, DLT_ID_SIZE); /* log with or without context id */ if (strlen(ctid_buf) > 0) { dlt_vlog( LOG_INFO, "Configured trace limits for app id %s, context id %s, level %u\n", apid_buf, ctid_buf, log_level_value); } else { dlt_vlog(LOG_INFO, "Configured trace limits for app id %s, level %u\n", apid_buf, log_level_value); } } /* while */ fclose(pFile); /* list must be sorted to speed up dlt_daemon_find_configured_app_id_ctx_id_settings */ qsort(daemon->app_id_log_level_settings, daemon->num_app_id_log_level_settings, sizeof(DltDaemonContextLogSettings), compare_app_id_conf); return 0; } #endif static int dlt_mkdir_recursive(const char *dir) { int ret = 0; char tmp[PATH_MAX + 1]; char *p = NULL; char *end = NULL; size_t len; strncpy(tmp, dir, PATH_MAX); len = strlen(tmp); if (tmp[len - 1] == '/') tmp[len - 1] = 0; end = tmp + len; for (p = tmp + 1; ((*p) && (ret == 0)) || ((ret == -1 && errno == EEXIST) && (p != end)); p++) if (*p == '/') { *p = 0; if (access(tmp, F_OK) != 0 && errno == ENOENT) { ret = mkdir(tmp, #ifdef DLT_DAEMON_USE_FIFO_IPC S_IRWXU); #else S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH /*S_IRWXU*/); #endif } *p = '/'; } if ((ret == 0) || ((ret == -1) && (errno == EEXIST))) ret = mkdir(tmp, #ifdef DLT_DAEMON_USE_FIFO_IPC S_IRWXU); #else S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH /*S_IRWXU*/); #endif if ((ret == -1) && (errno == EEXIST)) ret = 0; return ret; } #ifdef DLT_DAEMON_USE_FIFO_IPC static DltReturnValue dlt_daemon_create_pipes_dir(char *dir) { int ret = DLT_RETURN_OK; if (dir == NULL) { dlt_vlog(LOG_ERR, "%s: Invalid parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* create dlt pipes directory */ ret = mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_ISVTX); if ((ret == -1) && (errno != EEXIST)) { dlt_vlog(LOG_ERR, "FIFO user dir %s cannot be created (%s)!\n", dir, strerror(errno)); return DLT_RETURN_ERROR; } /* S_ISGID cannot be set by mkdir, let's reassign right bits */ ret = chmod(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH | S_ISGID | S_ISVTX); if (ret == -1) { dlt_vlog(LOG_ERR, "FIFO user dir %s cannot be chmoded (%s)!\n", dir, strerror(errno)); return DLT_RETURN_ERROR; } return ret; } #endif /** * Main function of tool. */ int main(int argc, char *argv[]) { char version[DLT_DAEMON_TEXTBUFSIZE]; char local_str[DLT_DAEMON_TEXTBUFSIZE]; DltDaemonLocal daemon_local; DltDaemon daemon; int back = 0; memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&daemon, 0, sizeof(DltDaemon)); /* Command line option handling */ if ((back = option_handling(&daemon_local, argc, argv)) < 0) { if (back != -2) fprintf (stderr, "option_handling() failed!\n"); return -1; } /* Configuration file option handling */ if ((back = option_file_parser(&daemon_local)) < 0) { if (back != -2) fprintf (stderr, "option_file_parser() failed!\n"); return -1; } /* Initialize internal logging facility */ dlt_log_set_filename(daemon_local.flags.loggingFilename); dlt_log_set_level(daemon_local.flags.loggingLevel); DltReturnValue log_init_result = dlt_log_init_multiple_logfiles_support(daemon_local.flags.loggingMode, daemon_local.flags.enableLoggingFileLimit, daemon_local.flags.loggingFileSize, daemon_local.flags.loggingFileMaxSize); if (log_init_result != DLT_RETURN_OK) { fprintf(stderr, "Failed to init internal logging\n"); #if WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK if (daemon_local.flags.loggingMode == DLT_LOG_TO_FILE) { fprintf(stderr, "Falling back to syslog mode\n"); daemon_local.flags.loggingMode = DLT_LOG_TO_SYSLOG; log_init_result = dlt_log_init(daemon_local.flags.loggingMode); if (log_init_result != DLT_RETURN_OK) { fprintf(stderr, "Failed to setup syslog logging, internal logs will " "not be available\n"); } } #endif } /* Print version information */ dlt_get_version(version, DLT_DAEMON_TEXTBUFSIZE); dlt_vlog(LOG_NOTICE, "Starting DLT Daemon; %s\n", version); PRINT_FUNCTION_VERBOSE(daemon_local.flags.vflag); /* Make sure the parent user directory is created */ #ifdef DLT_DAEMON_USE_FIFO_IPC if (dlt_mkdir_recursive(dltFifoBaseDir) != 0) { dlt_vlog(LOG_ERR, "Base dir %s cannot be created!\n", dltFifoBaseDir); return -1; } #else if (dlt_mkdir_recursive(DLT_USER_IPC_PATH) != 0) { dlt_vlog(LOG_ERR, "Base dir %s cannot be created!\n", daemon_local.flags.appSockPath); return -1; } #endif /* --- Daemon init phase 1 begin --- */ if (dlt_daemon_local_init_p1(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) { dlt_log(LOG_CRIT, "Initialization of phase 1 failed!\n"); return -1; } /* --- Daemon init phase 1 end --- */ if (dlt_daemon_prepare_event_handling(&daemon_local.pEvent)) { /* TODO: Perform clean-up */ dlt_log(LOG_CRIT, "Initialization of event handling failed!\n"); return -1; } /* --- Daemon connection init begin */ if (dlt_daemon_local_connection_init(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) { dlt_log(LOG_CRIT, "Initialization of local connections failed!\n"); return -1; } /* --- Daemon connection init end */ if (dlt_daemon_init_runtime_configuration(&daemon, daemon_local.flags.ivalue, daemon_local.flags.vflag) == -1) { dlt_log(LOG_ERR, "Could not load runtime config\n"); return -1; } /* * Load dlt-runtime.cfg if available. * This must be loaded before offline setup */ dlt_daemon_configuration_load(&daemon, daemon.runtime_configuration, daemon_local.flags.vflag); /* --- Daemon init phase 2 begin --- */ if (dlt_daemon_local_init_p2(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) { dlt_log(LOG_CRIT, "Initialization of phase 2 failed!\n"); return -1; } #ifdef DLT_LOG_LEVEL_APP_CONFIG /* Load control app id level configuration file without setting `back` to * prevent exit if file is missing */ if (app_id_default_log_level_config_parser(&daemon, &daemon_local) < 0) { dlt_vlog(LOG_WARNING, "app_id_default_log_level_config_parser() failed, " "no app specific log levels will be configured\n"); } #endif /* --- Daemon init phase 2 end --- */ if (daemon_local.flags.offlineLogstorageDirPath[0]) if (dlt_daemon_logstorage_setup_internal_storage( &daemon, &daemon_local, daemon_local.flags.offlineLogstorageDirPath, daemon_local.flags.vflag) == -1) dlt_log(LOG_INFO, "Setting up internal offline log storage failed!\n"); /* create fd for watchdog */ #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE { char *watchdogUSec = getenv("WATCHDOG_USEC"); int watchdogTimeoutSeconds = 0; dlt_log(LOG_DEBUG, "Systemd watchdog initialization\n"); if (watchdogUSec) watchdogTimeoutSeconds = atoi(watchdogUSec) / 2000000; watchdog_trigger_interval = watchdogTimeoutSeconds; create_timer_fd(&daemon_local, watchdogTimeoutSeconds, watchdogTimeoutSeconds, DLT_TIMER_SYSTEMD); } #endif /* create fd for timer timing packets */ create_timer_fd(&daemon_local, 1, 1, DLT_TIMER_PACKET); /* create fd for timer ecu version */ if ((daemon_local.flags.sendECUSoftwareVersion > 0) || (daemon_local.flags.sendTimezone > 0)) create_timer_fd(&daemon_local, 60, 60, DLT_TIMER_ECU); /* initiate gateway */ if (daemon_local.flags.gatewayMode == 1) { if (dlt_gateway_init(&daemon_local, daemon_local.flags.vflag) == -1) { dlt_log(LOG_CRIT, "Failed to create gateway\n"); return -1; } /* create gateway timer */ create_timer_fd(&daemon_local, daemon_local.pGateway.interval, daemon_local.pGateway.interval, DLT_TIMER_GATEWAY); } /* For offline tracing we still can use the same states */ /* as for socket sending. Using this trick we see the traces */ /* In the offline trace AND in the socket stream. */ if (daemon_local.flags.yvalue[0]) dlt_daemon_change_state(&daemon, DLT_DAEMON_STATE_SEND_DIRECT); else dlt_daemon_change_state(&daemon, DLT_DAEMON_STATE_BUFFER); dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, daemon_local.flags.gatewayMode, daemon_local.flags.vflag); /* * Check for app and ctx runtime cfg. * These cfg must be loaded after ecuId and num_user_lists are available */ if ((dlt_daemon_applications_load(&daemon, daemon.runtime_application_cfg, daemon_local.flags.vflag) == 0) && (dlt_daemon_contexts_load(&daemon, daemon.runtime_context_cfg, daemon_local.flags.vflag) == 0)) daemon.runtime_context_cfg_loaded = 1; dlt_daemon_log_internal(&daemon, &daemon_local, "Daemon launched. Starting to output traces...", daemon_local.flags.vflag); /* Even handling loop. */ while ((back >= 0) && (g_exit >= 0)) back = dlt_daemon_handle_event(&daemon_local.pEvent, &daemon, &daemon_local); snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Exiting DLT daemon... [%d]", g_signo); dlt_daemon_log_internal(&daemon, &daemon_local, local_str, daemon_local.flags.vflag); dlt_vlog(LOG_NOTICE, "%s%s", local_str, "\n"); dlt_daemon_local_cleanup(&daemon, &daemon_local, daemon_local.flags.vflag); #ifdef UDP_CONNECTION_SUPPORT dlt_daemon_udp_close_connection(); #endif dlt_gateway_deinit(&daemon_local.pGateway, daemon_local.flags.vflag); dlt_daemon_free(&daemon, daemon_local.flags.vflag); dlt_log(LOG_NOTICE, "Leaving DLT daemon\n"); dlt_log_free(); return 0; } /* main() */ int dlt_daemon_local_init_p1(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int ret = DLT_RETURN_OK; if ((daemon == 0) || (daemon_local == 0)) { dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p1()\n"); return -1; } #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) ret = sd_booted(); if (ret == 0) { dlt_log(LOG_CRIT, "System not booted with systemd!\n"); } else if (ret < 0) { dlt_log(LOG_CRIT, "sd_booted failed!\n"); return -1; } else { dlt_log(LOG_INFO, "System booted with systemd\n"); } #endif #ifdef DLT_DAEMON_USE_FIFO_IPC if (dlt_daemon_create_pipes_dir(daemon_local->flags.userPipesDir) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; #endif /* Check for daemon mode */ if (daemon_local->flags.dflag) dlt_daemon_daemonize(daemon_local->flags.vflag); /* initialise structure to use DLT file */ ret = dlt_file_init(&(daemon_local->file), daemon_local->flags.vflag); if (ret == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Could not initialize file structure\n"); /* Return value ignored, dlt daemon will exit */ dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag); return ret; } signal(SIGPIPE, SIG_IGN); signal(SIGTERM, dlt_daemon_signal_handler); /* software termination signal from kill */ signal(SIGHUP, dlt_daemon_signal_handler); /* hangup signal */ signal(SIGQUIT, dlt_daemon_signal_handler); signal(SIGINT, dlt_daemon_signal_handler); #ifdef __QNX__ signal(SIGUSR1, dlt_daemon_signal_handler); /* for timer threads */ #endif return DLT_RETURN_OK; } int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == 0) || (daemon_local == 0)) { dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p2()\n"); return -1; } /* Daemon data */ if (dlt_daemon_init(daemon, daemon_local->RingbufferMinSize, daemon_local->RingbufferMaxSize, daemon_local->RingbufferStepSize, daemon_local->flags.ivalue, daemon_local->flags.contextLogLevel, daemon_local->flags.contextTraceStatus, daemon_local->flags.enforceContextLLAndTS, daemon_local->flags.vflag) == -1) { dlt_log(LOG_ERR, "Could not initialize daemon data\n"); return -1; } /* init offline trace */ if (((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) && daemon_local->flags.offlineTraceDirectory[0]) { if (multiple_files_buffer_init(&(daemon_local->offlineTrace), daemon_local->flags.offlineTraceDirectory, daemon_local->flags.offlineTraceFileSize, daemon_local->flags.offlineTraceMaxSize, daemon_local->flags.offlineTraceFilenameTimestampBased, false, DLT_OFFLINETRACE_FILENAME_BASE, DLT_OFFLINETRACE_FILENAME_EXT) == -1) { dlt_log(LOG_ERR, "Could not initialize offline trace\n"); return -1; } } /* Init offline logstorage for MAX devices */ if (daemon_local->flags.offlineLogstorageMaxDevices > 0) { daemon->storage_handle = malloc(sizeof(DltLogStorage) * daemon_local->flags.offlineLogstorageMaxDevices); if (daemon->storage_handle == NULL) { dlt_log(LOG_ERR, "Could not initialize offline logstorage\n"); return -1; } memset(daemon->storage_handle, 0, (sizeof(DltLogStorage) * daemon_local->flags.offlineLogstorageMaxDevices)); } /* Set ECU id of daemon */ if (daemon_local->flags.evalue[0]) dlt_set_id(daemon->ecuid, daemon_local->flags.evalue); else dlt_set_id(daemon->ecuid, DLT_DAEMON_ECU_ID); /* Set flag for optional sending of serial header */ daemon->sendserialheader = daemon_local->flags.lflag; #ifdef DLT_SHM_ENABLE /* init shared memory */ if (dlt_shm_init_server(&(daemon_local->dlt_shm), daemon_local->flags.dltShmName, daemon_local->flags.sharedMemorySize) == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Could not initialize shared memory\n"); return -1; } daemon_local->recv_buf_shm = (unsigned char *)calloc(1, DLT_SHM_RCV_BUFFER_SIZE); if (NULL == daemon_local->recv_buf_shm) { dlt_log(LOG_ERR, "failed to allocated the buffer to receive shm data\n"); return -1; } #endif /* prepare main loop */ if (dlt_message_init(&(daemon_local->msg), daemon_local->flags.vflag) == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Could not initialize message\n"); return -1; } /* configure sending timing packets */ if (daemon_local->flags.sendMessageTime) daemon->timingpackets = 1; /* Get ECU version info from a file. If it fails, use dlt_version as fallback. */ if (dlt_daemon_local_ecu_version_init(daemon, daemon_local, daemon_local->flags.vflag) < 0) { daemon->ECUVersionString = malloc(DLT_DAEMON_TEXTBUFSIZE); if (daemon->ECUVersionString == 0) { dlt_log(LOG_WARNING, "Could not allocate memory for version string\n"); return -1; } dlt_get_version(daemon->ECUVersionString, DLT_DAEMON_TEXTBUFSIZE); } /* Set to allows to maintain logstorage loglevel as default */ daemon->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_ON; return 0; } static int dlt_daemon_init_serial(DltDaemonLocal *daemon_local) { /* create and open serial connection from/to client */ /* open serial connection */ int fd = -1; if (daemon_local->flags.yvalue[0] == '\0') return 0; fd = open(daemon_local->flags.yvalue, O_RDWR); if (fd < 0) { dlt_vlog(LOG_ERR, "Failed to open serial device %s\n", daemon_local->flags.yvalue); daemon_local->flags.yvalue[0] = 0; return -1; } if (isatty(fd)) { int speed = DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE; if (daemon_local->flags.bvalue[0]) speed = atoi(daemon_local->flags.bvalue); daemon_local->baudrate = dlt_convert_serial_speed(speed); if (dlt_setup_serial(fd, (speed_t) daemon_local->baudrate) < 0) { close(fd); daemon_local->flags.yvalue[0] = 0; dlt_vlog(LOG_ERR, "Failed to configure serial device %s (%s) \n", daemon_local->flags.yvalue, strerror(errno)); return -1; } if (daemon_local->flags.vflag) dlt_log(LOG_DEBUG, "Serial init done\n"); } else { close(fd); fprintf(stderr, "Device is not a serial device, device = %s (%s) \n", daemon_local->flags.yvalue, strerror(errno)); daemon_local->flags.yvalue[0] = 0; return -1; } return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_MSG_SERIAL); } #ifdef DLT_DAEMON_USE_FIFO_IPC static int dlt_daemon_init_fifo(DltDaemonLocal *daemon_local) { int ret; int fd = -1; int fifo_size; /* open named pipe(FIFO) to receive DLT messages from users */ umask(0); /* Try to delete existing pipe, ignore result of unlink */ const char *tmpFifo = daemon_local->flags.daemonFifoName; unlink(tmpFifo); ret = mkfifo(tmpFifo, S_IRUSR | S_IWUSR | S_IWGRP); if (ret == -1) { dlt_vlog(LOG_WARNING, "FIFO user %s cannot be created (%s)!\n", tmpFifo, strerror(errno)); return -1; } /* if */ /* Set group of daemon FIFO */ if (daemon_local->flags.daemonFifoGroup[0] != 0) { errno = 0; struct group *group_dlt = getgrnam(daemon_local->flags.daemonFifoGroup); if (group_dlt) { ret = chown(tmpFifo, -1, group_dlt->gr_gid); if (ret == -1) dlt_vlog(LOG_ERR, "FIFO user %s cannot be chowned to group %s (%s)\n", tmpFifo, daemon_local->flags.daemonFifoGroup, strerror(errno)); } else if ((errno == 0) || (errno == ENOENT) || (errno == EBADF) || (errno == EPERM)) { dlt_vlog(LOG_ERR, "Group name %s is not found (%s)\n", daemon_local->flags.daemonFifoGroup, strerror(errno)); } else { dlt_vlog(LOG_ERR, "Failed to get group id of %s (%s)\n", daemon_local->flags.daemonFifoGroup, strerror(errno)); } } fd = open(tmpFifo, O_RDWR); if (fd == -1) { dlt_vlog(LOG_WARNING, "FIFO user %s cannot be opened (%s)!\n", tmpFifo, strerror(errno)); return -1; } /* if */ #ifdef __linux__ /* F_SETPIPE_SZ and F_GETPIPE_SZ are only supported for Linux. * For other OSes it depends on its system e.g. pipe manager. */ if (daemon_local->daemonFifoSize != 0) { /* Set Daemon FIFO size */ if (fcntl(fd, F_SETPIPE_SZ, daemon_local->daemonFifoSize) == -1) dlt_vlog(LOG_ERR, "set FIFO size error: %s\n", strerror(errno)); } /* Get Daemon FIFO size */ if ((fifo_size = fcntl(fd, F_GETPIPE_SZ, 0)) == -1) dlt_vlog(LOG_ERR, "get FIFO size error: %s\n", strerror(errno)); else dlt_vlog(LOG_INFO, "FIFO size: %d\n", fifo_size); #endif /* Early init, to be able to catch client (app) connections * as soon as possible. This registration is automatically ignored * during next execution. */ return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_APP_MSG); } #endif #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE static int dlt_daemon_init_vsock(DltDaemonLocal *daemon_local) { int fd; struct sockaddr_vm addr; fd = socket(AF_VSOCK, SOCK_STREAM, 0); if (fd == -1) { dlt_vlog(LOG_ERR, "Failed to create VSOCK socket: %s\n", strerror(errno)); return -1; } memset(&addr, 0, sizeof(addr)); addr.svm_family = AF_VSOCK; addr.svm_port = DLT_VSOCK_PORT; addr.svm_cid = VMADDR_CID_ANY; if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) { dlt_vlog(LOG_ERR, "Failed to bind VSOCK socket: %s\n", strerror(errno)); close(fd); return -1; } if (listen(fd, 1) != 0) { dlt_vlog(LOG_ERR, "Failed to listen on VSOCK socket: %s\n", strerror(errno)); close(fd); return -1; } return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_APP_CONNECT); } #endif #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC static DltReturnValue dlt_daemon_init_app_socket(DltDaemonLocal *daemon_local) { /* socket access permission set to srw-rw-rw- (666) */ int mask = S_IXUSR | S_IXGRP | S_IXOTH; DltReturnValue ret = DLT_RETURN_OK; int fd = -1; if (daemon_local == NULL) { dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__); return DLT_RETURN_ERROR; } #ifdef ANDROID /* on android if we want to use security contexts on Unix sockets, * they should be created by init (see dlt-daemon.rc in src/daemon) * and recovered through the below API */ ret = dlt_daemon_unix_android_get_socket(&fd, daemon_local->flags.appSockPath); if (ret < DLT_RETURN_OK) { /* we failed to get app socket created by init. * To avoid blocking users to launch dlt-daemon only through * init on android (e.g: by hand for debugging purpose), try to * create app socket by ourselves */ ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.appSockPath, SOCK_STREAM, mask); } #else ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.appSockPath, SOCK_STREAM, mask); #endif if (ret == DLT_RETURN_OK) { if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_APP_CONNECT)) { dlt_log(LOG_CRIT, "Could not create connection for app socket.\n"); return DLT_RETURN_ERROR; } } else { dlt_log(LOG_CRIT, "Could not create and open app socket.\n"); return DLT_RETURN_ERROR; } return ret; } #endif static DltReturnValue dlt_daemon_initialize_control_socket(DltDaemonLocal *daemon_local) { /* socket access permission set to srw-rw---- (660) */ int mask = S_IXUSR | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH; DltReturnValue ret = DLT_RETURN_OK; int fd = -1; if (daemon_local == NULL) { dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__); return -1; } #ifdef ANDROID /* on android if we want to use security contexts on Unix sockets, * they should be created by init (see dlt-daemon.rc in src/daemon) * and recovered through the below API */ ret = dlt_daemon_unix_android_get_socket(&fd, daemon_local->flags.ctrlSockPath); if (ret < DLT_RETURN_OK) { /* we failed to get app socket created by init. * To avoid blocking users to launch dlt-daemon only through * init on android (e.g by hand for debugging purpose), try to * create app socket by ourselves */ ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.ctrlSockPath, SOCK_STREAM, mask); } #else ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.ctrlSockPath, SOCK_STREAM, mask); #endif if (ret == DLT_RETURN_OK) { if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CONTROL_CONNECT) < DLT_RETURN_OK) { dlt_log(LOG_ERR, "Could not initialize control socket.\n"); ret = DLT_RETURN_ERROR; } } return ret; } int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { int fd = -1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__); return -1; } DltBindAddress_t *head = daemon_local->flags.ipNodes; #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC /* create and open socket to receive incoming connections from user application */ if (dlt_daemon_init_app_socket(daemon_local) < DLT_RETURN_OK) { dlt_log(LOG_ERR, "Unable to initialize app socket.\n"); return DLT_RETURN_ERROR; } #else /* DLT_DAEMON_USE_FIFO_IPC */ if (dlt_daemon_init_fifo(daemon_local)) { dlt_log(LOG_ERR, "Unable to initialize fifo.\n"); return DLT_RETURN_ERROR; } #endif #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE if (dlt_daemon_init_vsock(daemon_local) != 0) { dlt_log(LOG_ERR, "Unable to initialize app VSOCK socket.\n"); return DLT_RETURN_ERROR; } #endif /* create and open socket to receive incoming connections from client */ daemon_local->client_connections = 0; if (head == NULL) { /* no IP set in BindAddress option, will use "0.0.0.0" as default */ if (dlt_daemon_socket_open(&fd, daemon_local->flags.port, "0.0.0.0") == DLT_RETURN_OK) { if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_CONNECT)) { dlt_log(LOG_ERR, "Could not initialize main socket.\n"); return DLT_RETURN_ERROR; } } else { dlt_log(LOG_ERR, "Could not initialize main socket.\n"); return DLT_RETURN_ERROR; } } else { bool any_open = false; while (head != NULL) { /* open socket for each IP in the bindAddress list */ if (dlt_daemon_socket_open(&fd, daemon_local->flags.port, head->ip) == DLT_RETURN_OK) { if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_CONNECT)) { dlt_vlog(LOG_ERR, "Could not create connection, for binding %s\n", head->ip); } else { any_open = true; } } else { dlt_vlog(LOG_ERR, "Could not open main socket, for binding %s\n", head->ip); } head = head->next; } if (!any_open) { dlt_vlog(LOG_ERR, "Failed create main socket for any configured binding\n"); return DLT_RETURN_ERROR; } } #ifdef UDP_CONNECTION_SUPPORT if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) { if (dlt_daemon_udp_connection_setup(daemon_local) < 0) { dlt_log(LOG_ERR, "UDP fd creation failed\n"); return DLT_RETURN_ERROR; } else { dlt_log(LOG_INFO, "UDP fd creation success\n"); } } #endif /* create and open unix socket to receive incoming connections from * control application */ if (dlt_daemon_initialize_control_socket(daemon_local) < DLT_RETURN_OK) { dlt_log(LOG_ERR, "Could not initialize control socket.\n"); return DLT_RETURN_ERROR; } /* Init serial */ if (dlt_daemon_init_serial(daemon_local) < 0) { dlt_log(LOG_ERR, "Could not initialize daemon data\n"); return DLT_RETURN_ERROR; } return 0; } int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { char *version = NULL; FILE *f = NULL; PRINT_FUNCTION_VERBOSE(verbose); /* By default, version string is null. */ daemon->ECUVersionString = NULL; /* Open the file. Bail out if error occurs */ f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r"); if (f == NULL) { /* Error level notice, because this might be deliberate choice */ dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n"); return -1; } /* Get the file size. Bail out if stat fails. */ int fd = fileno(f); struct stat s_buf; if (fstat(fd, &s_buf) < 0) { dlt_log(LOG_WARNING, "Failed to stat ECU Software version file.\n"); fclose(f); return -1; } /* Bail out if file is too large. Use DLT_DAEMON_TEXTBUFSIZE max. * Reserve one byte for trailing '\0' */ off_t size = s_buf.st_size; if (size >= DLT_DAEMON_TEXTBUFSIZE) { dlt_log(LOG_WARNING, "Too large file for ECU version.\n"); fclose(f); return -1; } /* Allocate permanent buffer for version info */ version = malloc((size_t) (size + 1)); if (version == 0) { dlt_log(LOG_WARNING, "Cannot allocate memory for ECU version.\n"); fclose(f); return -1; } off_t offset = 0; while (!feof(f)) { offset += (off_t) fread(version + offset, 1, (size_t) size, f); if (ferror(f)) { dlt_log(LOG_WARNING, "Failed to read ECU Software version file.\n"); free(version); fclose(f); return -1; } if (offset > size) { dlt_log(LOG_WARNING, "Too long file for ECU Software version info.\n"); free(version); fclose(f); return -1; } } version[offset] = '\0';/*append null termination at end of version string */ daemon->ECUVersionString = version; fclose(f); return 0; } void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == 0) || (daemon_local == 0)) { dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_cleanup()\n"); return; } /* Don't receive event anymore */ dlt_event_handler_cleanup_connections(&daemon_local->pEvent); dlt_message_free(&(daemon_local->msg), daemon_local->flags.vflag); /* free shared memory */ if (daemon_local->flags.offlineTraceDirectory[0]) multiple_files_buffer_free(&(daemon_local->offlineTrace)); /* Ignore result */ dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag); #ifdef DLT_DAEMON_USE_FIFO_IPC /* Try to delete existing pipe, ignore result of unlink() */ unlink(daemon_local->flags.daemonFifoName); #else /* DLT_DAEMON_USE_UNIX_SOCKET_IPC */ /* Try to delete existing pipe, ignore result of unlink() */ unlink(daemon_local->flags.appSockPath); #endif #ifdef DLT_SHM_ENABLE /* free shared memory */ dlt_shm_free_server(&(daemon_local->dlt_shm), daemon_local->flags.dltShmName); free(daemon_local->recv_buf_shm); daemon_local->recv_buf_shm = NULL; #endif if (daemon_local->flags.offlineLogstorageMaxDevices > 0) { /* disconnect all logstorage devices */ dlt_daemon_logstorage_cleanup(daemon, daemon_local, daemon_local->flags.vflag); free(daemon->storage_handle); } if (daemon->ECUVersionString != NULL) free(daemon->ECUVersionString); unlink(daemon_local->flags.ctrlSockPath); /* free IP list */ free(daemon_local->flags.ipNodes); } void dlt_daemon_exit_trigger() { /* stop event loop */ g_exit = -1; #ifdef DLT_DAEMON_USE_FIFO_IPC char tmp[DLT_PATH_MAX] = { 0 }; ssize_t n; n = snprintf(tmp, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir); if (n < 0 || (size_t)n > DLT_PATH_MAX) { dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n", __func__, n, tmp); } (void)unlink(tmp); #endif #ifdef __QNX__ dlt_daemon_cleanup_timers(); #endif } void dlt_daemon_signal_handler(int sig) { g_signo = sig; switch (sig) { case SIGHUP: case SIGTERM: case SIGINT: case SIGQUIT: { /* finalize the server */ dlt_vlog(LOG_NOTICE, "Exiting DLT daemon due to signal: %s\n", strsignal(sig)); dlt_daemon_exit_trigger(); break; } default: { /* This case should never happen! */ break; } } /* switch */ } /* dlt_daemon_signal_handler() */ #ifdef __QNX__ void dlt_daemon_cleanup_timers() { int i = 0; while (i < DLT_TIMER_UNKNOWN) { /* Remove FIFO of every timer and kill timer thread */ if (0 != timer_threads[i]) { pthread_kill(timer_threads[i], SIGUSR1); pthread_join(timer_threads[i], NULL); timer_threads[i] = 0; close_pipes(dlt_timer_pipes[i]); /* Free data of every timer */ if (NULL != timer_data[i]) { free(timer_data[i]); timer_data[i] = NULL; } } i++; } } #endif void dlt_daemon_daemonize(int verbose) { int i; int fd; PRINT_FUNCTION_VERBOSE(verbose); dlt_log(LOG_NOTICE, "Daemon mode\n"); /* Daemonize */ i = fork(); if (i < 0) { dlt_log(LOG_CRIT, "Unable to fork(), exiting DLT daemon\n"); exit(-1); /* fork error */ } if (i > 0) exit(0); /* parent exits */ /* child (daemon) continues */ /* Process independency */ /* obtain a new process group */ if (setsid() == -1) { dlt_log(LOG_CRIT, "setsid() failed, exiting DLT daemon\n"); exit(-1); /* fork error */ } /* Open standard descriptors stdin, stdout, stderr */ fd = open("/dev/null", O_RDWR); if (fd != -1) { /* Redirect STDOUT to /dev/null */ if (dup2(fd, STDOUT_FILENO) < 0) dlt_vlog(LOG_WARNING, "Failed to direct stdout to /dev/null. Error: %s\n", strerror(errno)); /* Redirect STDERR to /dev/null */ if (dup2(fd, STDERR_FILENO) < 0) dlt_vlog(LOG_WARNING, "Failed to direct stderr to /dev/null. Error: %s\n", strerror(errno)); close(fd); } else { dlt_log(LOG_CRIT, "Error opening /dev/null, exiting DLT daemon\n"); exit(-1); /* fork error */ } /* Set umask */ umask(DLT_DAEMON_UMASK); /* Change to root directory */ if (chdir("/") < 0) dlt_log(LOG_WARNING, "Failed to chdir to root\n"); /* Catch signals */ signal(SIGCHLD, SIG_IGN); /* ignore child */ signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); } /* dlt_daemon_daemonize() */ /* This function logs str to the configured output sink (socket, serial, offline trace). * To avoid recursion this function must be called only from DLT highlevel functions. * E. g. calling it to output a failure when the open of the offline trace file fails * would cause an endless loop because dlt_daemon_log_internal() would itself again try * to open the offline trace file. * This is a dlt-daemon only function. The libdlt has no equivalent function available. */ int dlt_daemon_log_internal(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *str, int verbose) { DltMessage msg = { 0 }; static uint8_t uiMsgCount = 0; DltStandardHeaderExtra *pStandardExtra = NULL; uint32_t uiType; uint16_t uiSize; uint32_t uiExtraSize; PRINT_FUNCTION_VERBOSE(verbose); /* Set storageheader */ msg.storageheader = (DltStorageHeader *)(msg.headerbuffer); dlt_set_storageheader(msg.storageheader, daemon->ecuid); /* Set standardheader */ msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); msg.standardheader->htyp = DLT_HTYP_UEH | DLT_HTYP_WEID | DLT_HTYP_WSID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1; msg.standardheader->mcnt = uiMsgCount++; uiExtraSize = (uint32_t) (DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) + (DLT_IS_HTYP_UEH(msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0)); msg.headersize = (uint32_t) sizeof(DltStorageHeader) + (uint32_t) sizeof(DltStandardHeader) + uiExtraSize; /* Set extraheader */ pStandardExtra = (DltStandardHeaderExtra *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)); dlt_set_id(pStandardExtra->ecu, daemon->ecuid); pStandardExtra->tmsp = DLT_HTOBE_32(dlt_uptime()); pStandardExtra->seid = (unsigned int) DLT_HTOBE_32(getpid()); /* Set extendedheader */ msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); msg.extendedheader->msin = DLT_MSIN_VERB | (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((DLT_LOG_INFO << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN); msg.extendedheader->noar = 1; dlt_set_id(msg.extendedheader->apid, "DLTD"); dlt_set_id(msg.extendedheader->ctid, "INTM"); /* Set payload data... */ uiType = DLT_TYPE_INFO_STRG; uiSize = (uint16_t) (strlen(str) + 1); msg.datasize = (uint32_t) (sizeof(uint32_t) + sizeof(uint16_t) + uiSize); msg.databuffer = (uint8_t *)malloc((size_t) msg.datasize); msg.databuffersize = msg.datasize; if (msg.databuffer == 0) { dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n"); return -1; } msg.datasize = 0; memcpy((uint8_t *)(msg.databuffer + msg.datasize), (uint8_t *)(&uiType), sizeof(uint32_t)); msg.datasize += (uint32_t) sizeof(uint32_t); memcpy((uint8_t *)(msg.databuffer + msg.datasize), (uint8_t *)(&uiSize), sizeof(uint16_t)); msg.datasize += (uint32_t) sizeof(uint16_t); memcpy((uint8_t *)(msg.databuffer + msg.datasize), str, uiSize); msg.datasize += uiSize; /* Calc length */ msg.standardheader->len = DLT_HTOBE_16(msg.headersize - sizeof(DltStorageHeader) + msg.datasize); dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL, daemon,daemon_local, msg.headerbuffer, sizeof(DltStorageHeader), msg.headerbuffer + sizeof(DltStorageHeader), (int) (msg.headersize - sizeof(DltStorageHeader)), msg.databuffer, (int) msg.datasize, verbose); free(msg.databuffer); return 0; } int dlt_daemon_check_numeric_setting(char *token, char *value, unsigned long *data) { char value_check[value_length]; value_check[0] = 0; sscanf(value, "%lu%s", data, value_check); if (value_check[0] || !isdigit(value[0])) { fprintf(stderr, "Invalid input [%s] detected in option %s\n", value, token); return -1; } return 0; } int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { socklen_t cli_size; struct sockaddr_un cli; int in_sock = -1; char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_log(LOG_ERR, "Invalid function parameters used for function " "dlt_daemon_process_client_connect()\n"); return -1; } /* event from TCP server socket, new connection */ cli_size = sizeof(cli); if ((in_sock = accept(receiver->fd, (struct sockaddr *)&cli, &cli_size)) < 0) { if (errno == ECONNABORTED) // Caused by nmap -v -p 3490 -Pn return 0; dlt_vlog(LOG_ERR, "accept() for socket %d failed: %s\n", receiver->fd, strerror(errno)); return -1; } /* check if file file descriptor was already used, and make it invalid if it * is reused. */ /* This prevents sending messages to wrong file descriptor */ dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose); dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose); /* Set socket timeout in reception */ struct timeval timeout_send; timeout_send.tv_sec = daemon_local->timeoutOnSend; timeout_send.tv_usec = 0; if (setsockopt (in_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout_send, sizeof(timeout_send)) < 0) dlt_log(LOG_WARNING, "setsockopt failed\n"); if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_CLIENT_MSG_TCP)) { dlt_log(LOG_ERR, "Failed to register new client. \n"); /* TODO: Perform clean-up */ return -1; } /* send connection info about connected */ dlt_daemon_control_message_connection_info(in_sock, daemon, daemon_local, DLT_CONNECTION_STATUS_CONNECTED, "", verbose); /* send ecu version string */ if (daemon_local->flags.sendECUSoftwareVersion > 0) { if (daemon_local->flags.sendECUSoftwareVersion > 0) dlt_daemon_control_get_software_version(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag); if (daemon_local->flags.sendTimezone > 0) dlt_daemon_control_message_timezone(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag); } snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "New client connection #%d established, Total Clients : %d", in_sock, daemon_local->client_connections); dlt_daemon_log_internal(daemon, daemon_local, local_str, daemon_local->flags.vflag); dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n"); if (daemon_local->client_connections == 1) { if (daemon_local->flags.vflag) dlt_log(LOG_DEBUG, "Send ring-buffer to client\n"); dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER); if (dlt_daemon_send_ringbuffer_to_client(daemon, daemon_local, verbose) == -1) { dlt_log(LOG_WARNING, "Can't send contents of ringbuffer to clients\n"); close(in_sock); in_sock = -1; return -1; } /* send new log state to all applications */ daemon->connectionState = 1; dlt_daemon_user_send_all_log_state(daemon, verbose); } return 0; } int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { int bytes_to_be_removed = 0; int must_close_socket = -1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_log(LOG_ERR, "Invalid function parameters used for function " "dlt_daemon_process_client_messages()\n"); return -1; } must_close_socket = dlt_receiver_receive(receiver); if (must_close_socket < 0) { dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose); return -1; } /* Process all received messages */ while (dlt_message_read(&(daemon_local->msg), (uint8_t *)receiver->buf, (unsigned int) receiver->bytesRcvd, daemon_local->flags.nflag, daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) { /* Check for control message */ if ((0 < receiver->fd) && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) dlt_daemon_client_process_control(receiver->fd, daemon, daemon_local, &(daemon_local->msg), daemon_local->flags.vflag); bytes_to_be_removed = (int) (daemon_local->msg.headersize + daemon_local->msg.datasize - sizeof(DltStorageHeader)); if (daemon_local->msg.found_serialheader) bytes_to_be_removed += (int) sizeof(dltSerialHeader); if (daemon_local->msg.resync_offset) bytes_to_be_removed += daemon_local->msg.resync_offset; if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) { dlt_log(LOG_WARNING, "Can't remove bytes from receiver for sockets\n"); return -1; } } /* while */ if (dlt_receiver_move_to_begin(receiver) == -1) { dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for sockets\n"); return -1; } if (must_close_socket == 0) /* FIXME: Why the hell do we need to close the socket * on control message reception ?? */ dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose); return 0; } int dlt_daemon_process_client_messages_serial(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { int bytes_to_be_removed = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_log(LOG_ERR, "Invalid function parameters used for function " "dlt_daemon_process_client_messages_serial()\n"); return -1; } if (dlt_receiver_receive(receiver) <= 0) { dlt_log(LOG_WARNING, "dlt_receiver_receive_fd() for messages from serial interface " "failed!\n"); return -1; } /* Process all received messages */ while (dlt_message_read(&(daemon_local->msg), (uint8_t *)receiver->buf, (unsigned int) receiver->bytesRcvd, daemon_local->flags.mflag, daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) { /* Check for control message */ if (DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) { if (dlt_daemon_client_process_control(receiver->fd, daemon, daemon_local, &(daemon_local->msg), daemon_local->flags.vflag) == -1) { dlt_log(LOG_WARNING, "Can't process control messages\n"); return -1; } } bytes_to_be_removed = (int) (daemon_local->msg.headersize + daemon_local->msg.datasize - sizeof(DltStorageHeader)); if (daemon_local->msg.found_serialheader) bytes_to_be_removed += (int) sizeof(dltSerialHeader); if (daemon_local->msg.resync_offset) bytes_to_be_removed += daemon_local->msg.resync_offset; if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) { dlt_log(LOG_WARNING, "Can't remove bytes from receiver for serial connection\n"); return -1; } } /* while */ if (dlt_receiver_move_to_begin(receiver) == -1) { dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for serial " "connection\n"); return -1; } return 0; } int dlt_daemon_process_control_connect( DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { socklen_t ctrl_size; struct sockaddr_un ctrl; int in_sock = -1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_log(LOG_ERR, "Invalid function parameters used for function " "dlt_daemon_process_control_connect()\n"); return -1; } /* event from UNIX server socket, new connection */ ctrl_size = sizeof(ctrl); if ((in_sock = accept(receiver->fd, (struct sockaddr *)&ctrl, &ctrl_size)) < 0) { dlt_vlog(LOG_ERR, "accept() on UNIX control socket %d failed: %s\n", receiver->fd, strerror(errno)); return -1; } /* check if file file descriptor was already used, and make it invalid if it * is reused */ /* This prevents sending messages to wrong file descriptor */ dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose); dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose); if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_CONTROL_MSG)) { dlt_log(LOG_ERR, "Failed to register new client. \n"); /* TODO: Perform clean-up */ return -1; } if (verbose) dlt_vlog(LOG_INFO, "New connection to control client established\n"); return 0; } #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE int dlt_daemon_process_app_connect( DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { int in_sock = -1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* event from server socket, new connection */ if ((in_sock = accept(receiver->fd, NULL, NULL)) < 0) { dlt_vlog(LOG_ERR, "accept() on UNIX socket %d failed: %s\n", receiver->fd, strerror(errno)); return -1; } /* check if file file descriptor was already used, and make it invalid if it * is reused. This prevents sending messages to wrong file descriptor */ dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose); dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose); if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_APP_MSG)) { dlt_log(LOG_ERR, "Failed to register new application. \n"); close(in_sock); return -1; } if (verbose) dlt_vlog(LOG_INFO, "New connection to application established\n"); return 0; } #endif int dlt_daemon_process_control_messages( DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { int bytes_to_be_removed = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_log(LOG_ERR, "Invalid function parameters used for function " "dlt_daemon_process_control_messages()\n"); return -1; } if (dlt_receiver_receive(receiver) <= 0) { dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose); /* FIXME: Why the hell do we need to close the socket * on control message reception ?? */ return 0; } /* Process all received messages */ while (dlt_message_read( &(daemon_local->msg), (uint8_t *)receiver->buf, (unsigned int) receiver->bytesRcvd, daemon_local->flags.nflag, daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) { /* Check for control message */ if ((receiver->fd > 0) && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) dlt_daemon_client_process_control(receiver->fd, daemon, daemon_local, &(daemon_local->msg), daemon_local->flags.vflag); bytes_to_be_removed = (int) (daemon_local->msg.headersize + daemon_local->msg.datasize - sizeof(DltStorageHeader)); if (daemon_local->msg.found_serialheader) bytes_to_be_removed += (int) sizeof(dltSerialHeader); if (daemon_local->msg.resync_offset) bytes_to_be_removed += daemon_local->msg.resync_offset; if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) { dlt_log(LOG_WARNING, "Can't remove bytes from receiver for sockets\n"); return -1; } } /* while */ if (dlt_receiver_move_to_begin(receiver) == -1) { dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for sockets\n"); return -1; } return 0; } static int dlt_daemon_process_user_message_not_sup(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { DltUserHeader *userheader = (DltUserHeader *)(receiver->buf); (void)daemon; (void)daemon_local; PRINT_FUNCTION_VERBOSE(verbose); dlt_vlog(LOG_ERR, "Invalid user message type received: %u!\n", userheader->message); /* remove user header */ if (dlt_receiver_remove(receiver, sizeof(DltUserHeader)) == -1) dlt_log(LOG_WARNING, "Can't remove bytes from receiver for user messages\n"); return -1; } static dlt_daemon_process_user_message_func process_user_func[DLT_USER_MESSAGE_NOT_SUPPORTED] = { dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_log, dlt_daemon_process_user_message_register_application, dlt_daemon_process_user_message_unregister_application, dlt_daemon_process_user_message_register_context, dlt_daemon_process_user_message_unregister_context, dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_overflow, dlt_daemon_process_user_message_set_app_ll_ts, dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_marker, dlt_daemon_process_user_message_not_sup, dlt_daemon_process_user_message_not_sup }; int dlt_daemon_process_user_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { int offset = 0; int run_loop = 1; int32_t min_size = (int32_t) sizeof(DltUserHeader); DltUserHeader *userheader; int recv; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_log(LOG_ERR, "Invalid function parameters used for function " "dlt_daemon_process_user_messages()\n"); return -1; } recv = dlt_receiver_receive(receiver); if (recv <= 0 && receiver->type == DLT_RECEIVE_SOCKET) { dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose); return 0; } else if (recv < 0) { dlt_log(LOG_WARNING, "dlt_receiver_receive_fd() for user messages failed!\n"); return -1; } /* look through buffer as long as data is in there */ while ((receiver->bytesRcvd >= min_size) && run_loop) { dlt_daemon_process_user_message_func func = NULL; offset = 0; userheader = (DltUserHeader *)(receiver->buf + offset); while (!dlt_user_check_userheader(userheader) && (offset + min_size <= receiver->bytesRcvd)) { /* resync if necessary */ offset++; userheader = (DltUserHeader *)(receiver->buf + offset); } /* Check for user header pattern */ if (!dlt_user_check_userheader(userheader)) break; /* Set new start offset */ if (offset > 0) dlt_receiver_remove(receiver, offset); if (userheader->message >= DLT_USER_MESSAGE_NOT_SUPPORTED) func = dlt_daemon_process_user_message_not_sup; else func = process_user_func[userheader->message]; if (func(daemon, daemon_local, receiver, daemon_local->flags.vflag) == -1) run_loop = 0; } /* keep not read data in buffer */ if (dlt_receiver_move_to_begin(receiver) == -1) { dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for user " "messages\n"); return -1; } return 0; } int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t len = sizeof(DltUserControlMsgBufferOverflow); DltUserControlMsgBufferOverflow userpayload; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return -1; } if (dlt_receiver_check_and_get(rec, &userpayload, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) /* Not enough bytes received */ return -1; /* Store in daemon, that a message buffer overflow has occured */ /* look if TCP connection to client is available or it least message can be put into buffer */ if (dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, userpayload.overflow_counter, userpayload.apid, verbose)) /* there was an error when storing message */ /* add the counter of lost messages to the daemon counter */ daemon->overflow_counter += userpayload.overflow_counter; return 0; } int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { int ret; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == 0) || (daemon_local == 0)) { dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n"); return DLT_DAEMON_ERROR_UNKNOWN; } /* Store in daemon, that a message buffer overflow has occured */ if ((ret = dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon->overflow_counter, "", verbose))) return ret; return DLT_DAEMON_ERROR_OK; } int dlt_daemon_process_user_message_register_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t len = sizeof(DltUserControlMsgRegisterApplication); uint32_t to_remove = 0; DltDaemonApplication *application = NULL; DltDaemonApplication *old_application = NULL; pid_t old_pid = 0; char description[DLT_DAEMON_DESCSIZE + 1] = { '\0' }; DltUserControlMsgRegisterApplication userapp; char *origin; int fd = -1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return -1; } memset(&userapp, 0, sizeof(DltUserControlMsgRegisterApplication)); origin = rec->buf; /* Adding temp variable to check the return value */ int temp = 0; /* We shall not remove data before checking that everything is there. */ temp = dlt_receiver_check_and_get(rec, &userapp, len, DLT_RCV_SKIP_HEADER); if (temp < 0) /* Not enough bytes received */ return -1; else { to_remove = (uint32_t) temp; } len = userapp.description_length; if (len > DLT_DAEMON_DESCSIZE) { len = DLT_DAEMON_DESCSIZE; dlt_log(LOG_WARNING, "Application description exceeds limit\n"); } /* adjust buffer pointer */ rec->buf += to_remove + sizeof(DltUserHeader); if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) { dlt_log(LOG_ERR, "Unable to get application description\n"); /* in case description was not readable, set dummy description */ memcpy(description, "Unknown", sizeof("Unknown")); /* unknown len of original description, set to 0 to not remove in next * step. Because message buffer is re-adjusted the corrupted description * is ignored. */ len = 0; } /* adjust to_remove */ to_remove += (uint32_t) sizeof(DltUserHeader) + len; /* point to begin of message */ rec->buf = origin; /* We can now remove data. */ if (dlt_receiver_remove(rec, (int) to_remove) != DLT_RETURN_OK) { dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n"); return -1; } old_application = dlt_daemon_application_find(daemon, userapp.apid, daemon->ecuid, verbose); if (old_application != NULL) old_pid = old_application->pid; if (rec->type == DLT_RECEIVE_SOCKET) fd = rec->fd; /* For sockets, an app specific fd has already been created with accept(). */ application = dlt_daemon_application_add(daemon, userapp.apid, userapp.pid, description, fd, daemon->ecuid, verbose); /* send log state to new application */ dlt_daemon_user_send_log_state(daemon, application, verbose); if (application == NULL) { dlt_vlog(LOG_WARNING, "Can't add ApplicationID '%.4s' for PID %d\n", userapp.apid, userapp.pid); return -1; } else if (old_pid != application->pid) { char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "ApplicationID '%.4s' registered for PID %d, Description=%s", application->apid, application->pid, application->application_description); dlt_daemon_log_internal(daemon, daemon_local, local_str, daemon_local->flags.vflag); dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n"); } return 0; } int dlt_daemon_process_user_message_register_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t to_remove = 0; uint32_t len = sizeof(DltUserControlMsgRegisterContext); DltUserControlMsgRegisterContext userctxt; char description[DLT_DAEMON_DESCSIZE + 1] = { '\0' }; DltDaemonApplication *application = NULL; DltDaemonContext *context = NULL; DltServiceGetLogInfoRequest *req = NULL; char *origin; DltMessage msg; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return -1; } memset(&userctxt, 0, sizeof(DltUserControlMsgRegisterContext)); origin = rec->buf; /* Adding temp variable to check the return value */ int temp = 0; temp = dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER); if (temp < 0) /* Not enough bytes received */ return -1; else { to_remove = (uint32_t) temp; } len = userctxt.description_length; if (len > DLT_DAEMON_DESCSIZE) { dlt_vlog(LOG_WARNING, "Context description exceeds limit: %u\n", len); len = DLT_DAEMON_DESCSIZE; } /* adjust buffer pointer */ rec->buf += to_remove + sizeof(DltUserHeader); if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) { dlt_log(LOG_ERR, "Unable to get context description\n"); /* in case description was not readable, set dummy description */ memcpy(description, "Unknown", sizeof("Unknown")); /* unknown len of original description, set to 0 to not remove in next * step. Because message buffer is re-adjusted the corrupted description * is ignored. */ len = 0; } /* adjust to_remove */ to_remove += (uint32_t) sizeof(DltUserHeader) + len; /* point to begin of message */ rec->buf = origin; /* We can now remove data. */ if (dlt_receiver_remove(rec, (int) to_remove) != DLT_RETURN_OK) { dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n"); return -1; } application = dlt_daemon_application_find(daemon, userctxt.apid, daemon->ecuid, verbose); if (application == 0) { dlt_vlog(LOG_WARNING, "ApID '%.4s' not found for new ContextID '%.4s' in %s\n", userctxt.apid, userctxt.ctid, __func__); return 0; } /* Set log level */ if (userctxt.log_level == DLT_USER_LOG_LEVEL_NOT_SET) { userctxt.log_level = DLT_LOG_DEFAULT; } else { /* Plausibility check */ if ((userctxt.log_level < DLT_LOG_DEFAULT) || (userctxt.log_level > DLT_LOG_VERBOSE)) { return -1; } } /* Set trace status */ if (userctxt.trace_status == DLT_USER_TRACE_STATUS_NOT_SET) { userctxt.trace_status = DLT_TRACE_STATUS_DEFAULT; } else { /* Plausibility check */ if ((userctxt.trace_status < DLT_TRACE_STATUS_DEFAULT) || (userctxt.trace_status > DLT_TRACE_STATUS_ON)) { return -1; } } context = dlt_daemon_context_add(daemon, userctxt.apid, userctxt.ctid, userctxt.log_level, userctxt.trace_status, userctxt.log_level_pos, application->user_handle, description, daemon->ecuid, verbose); if (context == 0) { dlt_vlog(LOG_WARNING, "Can't add ContextID '%.4s' for ApID '%.4s'\n in %s", userctxt.ctid, userctxt.apid, __func__); return -1; } else { char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "ContextID '%.4s' registered for ApID '%.4s', Description=%s", context->ctid, context->apid, context->context_description); if (verbose) dlt_daemon_log_internal(daemon, daemon_local, local_str, verbose); dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n"); } if (daemon_local->flags.offlineLogstorageMaxDevices) /* Store log level set for offline logstorage into context structure*/ context->storage_log_level = (int8_t) dlt_daemon_logstorage_get_loglevel(daemon, (int8_t) daemon_local->flags.offlineLogstorageMaxDevices, userctxt.apid, userctxt.ctid); else context->storage_log_level = DLT_LOG_DEFAULT; /* Create automatic get log info response for registered context */ if (daemon_local->flags.rflag) { /* Prepare request for get log info with one application and one context */ if (dlt_message_init(&msg, verbose) == -1) { dlt_log(LOG_WARNING, "Can't initialize message"); return -1; } msg.datasize = sizeof(DltServiceGetLogInfoRequest); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) { dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n"); return -1; } req = (DltServiceGetLogInfoRequest *)msg.databuffer; req->service_id = DLT_SERVICE_ID_GET_LOG_INFO; req->options = (uint8_t) daemon_local->flags.autoResponseGetLogInfoOption; dlt_set_id(req->apid, userctxt.apid); dlt_set_id(req->ctid, userctxt.ctid); dlt_set_id(req->com, "remo"); dlt_daemon_control_get_log_info(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, &msg, verbose); dlt_message_free(&msg, verbose); } if (context->user_handle >= DLT_FD_MINIMUM) { if ((userctxt.log_level == DLT_LOG_DEFAULT) || (userctxt.trace_status == DLT_TRACE_STATUS_DEFAULT)) { /* This call also replaces the default values with the values defined for default */ if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) { dlt_vlog(LOG_WARNING, "Can't send current log level as response to %s for (%.4s;%.4s)\n", __func__, context->apid, context->ctid); return -1; } } } return 0; } int dlt_daemon_process_user_message_unregister_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t len = sizeof(DltUserControlMsgUnregisterApplication); DltUserControlMsgUnregisterApplication userapp; DltDaemonApplication *application = NULL; DltDaemonContext *context; int i, offset_base; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return -1; } if (dlt_receiver_check_and_get(rec, &userapp, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) /* Not enough bytes received */ return -1; user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return -1; if (user_list->num_applications > 0) { /* Delete this application and all corresponding contexts * for this application from internal table. */ application = dlt_daemon_application_find(daemon, userapp.apid, daemon->ecuid, verbose); if (application) { /* Calculate start offset within contexts[] */ offset_base = 0; for (i = 0; i < (application - (user_list->applications)); i++) offset_base += user_list->applications[i].num_contexts; for (i = (application->num_contexts) - 1; i >= 0; i--) { context = &(user_list->contexts[offset_base + i]); if (context) { /* Delete context */ if (dlt_daemon_context_del(daemon, context, daemon->ecuid, verbose) == -1) { dlt_vlog(LOG_WARNING, "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n", context->ctid, context->apid, __func__); return -1; } } } /* Delete this application entry from internal table*/ if (dlt_daemon_application_del(daemon, application, daemon->ecuid, verbose) == -1) { dlt_vlog(LOG_WARNING, "Can't delete ApID '%.4s' in %s\n", application->apid, __func__); return -1; } else { char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Unregistered ApID '%.4s'", userapp.apid); dlt_daemon_log_internal(daemon, daemon_local, local_str, verbose); dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n"); } } } return 0; } int dlt_daemon_process_user_message_unregister_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t len = sizeof(DltUserControlMsgUnregisterContext); DltUserControlMsgUnregisterContext userctxt; DltDaemonContext *context; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return -1; } if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) /* Not enough bytes received */ return -1; context = dlt_daemon_context_find(daemon, userctxt.apid, userctxt.ctid, daemon->ecuid, verbose); /* In case the daemon is loaded with predefined contexts and its context * unregisters, the context information will not be deleted from daemon's * table until its parent application is unregistered. */ if (context && (context->predefined == false)) { /* Delete this connection entry from internal table*/ if (dlt_daemon_context_del(daemon, context, daemon->ecuid, verbose) == -1) { dlt_vlog(LOG_WARNING, "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n", userctxt.ctid, userctxt.apid, __func__); return -1; } else { char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Unregistered CtID '%.4s' for ApID '%.4s'", userctxt.ctid, userctxt.apid); if (verbose) dlt_daemon_log_internal(daemon, daemon_local, local_str, verbose); dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n"); } } /* Create automatic unregister context response for unregistered context */ if (daemon_local->flags.rflag) dlt_daemon_control_message_unregister_context(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, userctxt.apid, userctxt.ctid, "remo", verbose); return 0; } int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { int ret = 0; int size = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "%s: invalid function parameters.\n", __func__); return DLT_DAEMON_ERROR_UNKNOWN; } #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE daemon->received_message_since_last_watchdog_interval = 1; #endif #ifdef DLT_SHM_ENABLE /** In case of SHM, the header still received via fifo/unix_socket receiver, * so we need to remove header from the receiver. */ if (dlt_receiver_remove(rec, sizeof(DltUserHeader)) < 0) /* Not enough bytes received to remove*/ return DLT_DAEMON_ERROR_UNKNOWN; while (1) { /* get log message from SHM then store into receiver buffer */ size = dlt_shm_pull(&(daemon_local->dlt_shm), daemon_local->recv_buf_shm, DLT_SHM_RCV_BUFFER_SIZE); if (size <= 0) break; ret = dlt_message_read(&(daemon_local->msg), daemon_local->recv_buf_shm, size, 0, verbose); if (DLT_MESSAGE_ERROR_OK != ret) { dlt_shm_remove(&(daemon_local->dlt_shm)); dlt_log(LOG_WARNING, "failed to read messages from shm.\n"); return DLT_DAEMON_ERROR_UNKNOWN; } #ifdef DLT_LOG_LEVEL_APP_CONFIG DltDaemonApplication *app = dlt_daemon_application_find( daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose); #endif /* discard non-allowed levels if enforcement is on */ bool keep_message = enforce_context_ll_and_ts_keep_message( daemon_local #ifdef DLT_LOG_LEVEL_APP_CONFIG , app #endif ); if (keep_message) dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose); if (DLT_DAEMON_ERROR_OK != ret) dlt_log(LOG_ERR, "failed to send message to client.\n"); } #else ret = dlt_message_read(&(daemon_local->msg), (unsigned char *)rec->buf + sizeof(DltUserHeader), (unsigned int) ((unsigned int) rec->bytesRcvd - sizeof(DltUserHeader)), 0, verbose); if (ret != DLT_MESSAGE_ERROR_OK) { if (ret != DLT_MESSAGE_ERROR_SIZE) /* This is a normal usecase: The daemon reads the data in 10kb chunks. * Thus the last trace in this chunk is probably not complete and will be completed * with the next chunk read. This happens always when the FIFO is filled with more than 10kb before * the daemon is able to read from the FIFO. * Thus the loglevel of this message is set to DEBUG. * A cleaner solution would be to check more in detail whether the message is not complete (normal usecase) * or the headers are corrupted (error case). */ dlt_log(LOG_DEBUG, "Can't read messages from receiver\n"); if (dlt_receiver_remove(rec, rec->bytesRcvd) != DLT_RETURN_OK) { /* In certain rare scenarios where only a partial message has been received * (Eg: kernel IPC buffer memory being full), we want to discard the message * and not broadcast it forward to connected clients. Since the DLT library * checks return value of the writev() call against the sent total message * length, the partial message will be buffered and retransmitted again. * This implicitly ensures that no message loss occurs. */ dlt_log(LOG_WARNING, "failed to remove required bytes from receiver.\n"); } return DLT_DAEMON_ERROR_UNKNOWN; } #ifdef DLT_LOG_LEVEL_APP_CONFIG DltDaemonApplication *app = dlt_daemon_application_find( daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose); #endif /* discard non-allowed levels if enforcement is on */ bool keep_message = enforce_context_ll_and_ts_keep_message( daemon_local #ifdef DLT_LOG_LEVEL_APP_CONFIG , app #endif ); if (keep_message) dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose); /* keep not read data in buffer */ size = (int) (daemon_local->msg.headersize + daemon_local->msg.datasize - sizeof(DltStorageHeader) + sizeof(DltUserHeader)); if (daemon_local->msg.found_serialheader) size += (int) sizeof(dltSerialHeader); if (dlt_receiver_remove(rec, size) != DLT_RETURN_OK) { dlt_log(LOG_WARNING, "failed to remove bytes from receiver.\n"); return DLT_DAEMON_ERROR_UNKNOWN; } #endif return DLT_DAEMON_ERROR_OK; } bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local #ifdef DLT_LOG_LEVEL_APP_CONFIG , DltDaemonApplication *app #endif ) { if (!daemon_local->flags.enforceContextLLAndTS || !daemon_local->msg.extendedheader) { return true; } const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msg.extendedheader->msin); #ifdef DLT_LOG_LEVEL_APP_CONFIG if (app->num_context_log_level_settings > 0) { DltDaemonContextLogSettings *log_settings = dlt_daemon_find_app_log_level_config(app, daemon_local->msg.extendedheader->ctid); if (log_settings != NULL) { return mtin <= log_settings->log_level; } } #endif return mtin <= daemon_local->flags.contextLogLevel; } int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t len = sizeof(DltUserControlMsgAppLogLevelTraceStatus); DltUserControlMsgAppLogLevelTraceStatus userctxt; DltDaemonApplication *application; DltDaemonContext *context; int i, offset_base; int8_t old_log_level, old_trace_status; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return DLT_RETURN_ERROR; } user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return DLT_RETURN_ERROR; memset(&userctxt, 0, len); if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) /* Not enough bytes received */ return DLT_RETURN_ERROR; if (user_list->num_applications > 0) { /* Get all contexts with application id matching the received application id */ application = dlt_daemon_application_find(daemon, userctxt.apid, daemon->ecuid, verbose); if (application) { /* Calculate start offset within contexts[] */ offset_base = 0; for (i = 0; i < (application - (user_list->applications)); i++) offset_base += user_list->applications[i].num_contexts; for (i = 0; i < application->num_contexts; i++) { context = &(user_list->contexts[offset_base + i]); if (context) { old_log_level = context->log_level; context->log_level = (int8_t) userctxt.log_level; /* No endianess conversion necessary*/ old_trace_status = context->trace_status; context->trace_status = (int8_t) userctxt.trace_status; /* No endianess conversion necessary */ /* The following function sends also the trace status */ if ((context->user_handle >= DLT_FD_MINIMUM) && (dlt_daemon_user_send_log_level(daemon, context, verbose) != 0)) { context->log_level = old_log_level; context->trace_status = old_trace_status; } } } } } return DLT_RETURN_OK; } int dlt_daemon_process_user_message_log_mode(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { DltUserControlMsgLogMode userctxt; uint32_t len = sizeof(DltUserControlMsgLogMode); PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == 0) || (daemon_local == 0)) { dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_log_mode()\n"); return -1; } memset(&userctxt, 0, len); if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) /* Not enough bytes received */ return -1; /* set the new log mode */ daemon->mode = userctxt.log_mode; /* write configuration persistantly */ dlt_daemon_configuration_save(daemon, daemon->runtime_configuration, verbose); return 0; } int dlt_daemon_process_user_message_marker(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose) { uint32_t len = sizeof(DltUserControlMsgLogMode); DltUserControlMsgLogMode userctxt; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return -1; } memset(&userctxt, 0, len); if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) /* Not enough bytes received */ return -1; /* Create automatic unregister context response for unregistered context */ dlt_daemon_control_message_marker(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, verbose); return 0; } int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { int ret; static uint8_t data[DLT_DAEMON_RCVBUFSIZE]; int length; #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE uint32_t curr_time; #endif PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == 0) || (daemon_local == 0)) { dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_send_ringbuffer_to_client()\n"); return DLT_DAEMON_ERROR_UNKNOWN; } if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) { dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT); return DLT_DAEMON_ERROR_OK; } #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE if (sd_notify(0, "WATCHDOG=1") < 0) dlt_vlog(LOG_WARNING, "Could not reset systemd watchdog: %s\n", strerror(errno)); curr_time = dlt_uptime(); #endif while ((length = dlt_buffer_copy(&(daemon->client_ringbuffer), data, sizeof(data))) > 0) { #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE if ((dlt_uptime() - curr_time) / 10000 >= watchdog_trigger_interval) { if (sd_notify(0, "WATCHDOG=1") < 0) dlt_log(LOG_WARNING, "Could not reset systemd watchdog\n"); curr_time = dlt_uptime(); } #endif if ((ret = dlt_daemon_client_send(DLT_DAEMON_SEND_FORCE, daemon, daemon_local, 0, 0, data, length, 0, 0, verbose))) return ret; dlt_buffer_remove(&(daemon->client_ringbuffer)); if (daemon->state != DLT_DAEMON_STATE_SEND_BUFFER) dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER); if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) { dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT); return DLT_DAEMON_ERROR_OK; } } return DLT_DAEMON_ERROR_OK; } #ifdef __QNX__ static void *timer_thread(void *data) { int pexit = 0; unsigned int sleep_ret = 0; DltDaemonPeriodicData* timer_thread_data = (DltDaemonPeriodicData*) data; /* Timer will start in starts_in sec*/ if ((sleep_ret = sleep(timer_thread_data->starts_in))) { dlt_vlog(LOG_NOTICE, "Sleep remains [%u] for starting!" "Stop thread of timer [%d]\n", sleep_ret, timer_thread_data->timer_id); close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]); return NULL; } while (1) { if ((dlt_timer_pipes[timer_thread_data->timer_id][1] > 0) && (0 > write(dlt_timer_pipes[timer_thread_data->timer_id][1], "1", 1))) { dlt_vlog(LOG_ERR, "Failed to send notification for timer [%s]!\n", dlt_timer_names[timer_thread_data->timer_id]); pexit = 1; } if (pexit || g_exit) { dlt_vlog(LOG_NOTICE, "Received signal!" "Stop thread of timer [%d]\n", timer_thread_data->timer_id); close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]); return NULL; } if ((sleep_ret = sleep(timer_thread_data->period_sec))) { dlt_vlog(LOG_NOTICE, "Sleep remains [%u] for interval!" "Stop thread of timer [%d]\n", sleep_ret, timer_thread_data->timer_id); close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]); return NULL; } } } #endif int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, DltTimers timer_id) { int local_fd = DLT_FD_INIT; char *timer_name = NULL; if (timer_id >= DLT_TIMER_UNKNOWN) { dlt_log(DLT_LOG_ERROR, "Unknown timer."); return -1; } timer_name = dlt_timer_names[timer_id]; if (daemon_local == NULL) { dlt_log(DLT_LOG_ERROR, "Daemon local structure is NULL"); return -1; } if ((period_sec <= 0) || (starts_in <= 0)) { /* timer not activated via the service file */ dlt_vlog(LOG_INFO, "<%s> not set: period=0\n", timer_name); local_fd = DLT_FD_INIT; } else { #ifdef linux struct itimerspec l_timer_spec; local_fd = timerfd_create(CLOCK_MONOTONIC, 0); if (local_fd < 0) dlt_vlog(LOG_WARNING, "<%s> timerfd_create failed: %s\n", timer_name, strerror(errno)); l_timer_spec.it_interval.tv_sec = period_sec; l_timer_spec.it_interval.tv_nsec = 0; l_timer_spec.it_value.tv_sec = starts_in; l_timer_spec.it_value.tv_nsec = 0; if (timerfd_settime(local_fd, 0, &l_timer_spec, NULL) < 0) { dlt_vlog(LOG_WARNING, "<%s> timerfd_settime failed: %s\n", timer_name, strerror(errno)); local_fd = DLT_FD_INIT; } #elif __QNX__ /* * Since timerfd is not valid in QNX, new threads are introduced * to manage timers and communicate with main thread when timer expires. */ if(0 != pipe(dlt_timer_pipes[timer_id])) { dlt_vlog(LOG_ERR, "Failed to create pipe for timer [%s]", dlt_timer_names[timer_id]); return -1; } if (NULL == timer_data[timer_id]) { timer_data[timer_id] = calloc(1, sizeof(DltDaemonPeriodicData)); if (NULL == timer_data[timer_id]) { dlt_vlog(LOG_ERR, "Failed to allocate memory for timer_data [%s]!\n", dlt_timer_names[timer_id]); close_pipes(dlt_timer_pipes[timer_id]); return -1; } } timer_data[timer_id]->timer_id = timer_id; timer_data[timer_id]->period_sec = period_sec; timer_data[timer_id]->starts_in = starts_in; timer_data[timer_id]->wakeups_missed = 0; if (0 != pthread_create(&timer_threads[timer_id], NULL, &timer_thread, (void*)timer_data[timer_id])) { dlt_vlog(LOG_ERR, "Failed to create new thread for timer [%s]!\n", dlt_timer_names[timer_id]); /* Clean up timer before returning */ close_pipes(dlt_timer_pipes[timer_id]); free(timer_data[timer_id]); timer_data[timer_id] = NULL; return -1; } local_fd = dlt_timer_pipes[timer_id][0]; #endif } return dlt_connection_create(daemon_local, &daemon_local->pEvent, local_fd, POLLIN, dlt_timer_conn_types[timer_id]); } /* Close connection function */ int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon_local == NULL) || (daemon == NULL)) { dlt_log(LOG_ERR, "dlt_daemon_close_socket: Invalid input parmeters\n"); return -1; } /* Closure is done while unregistering has for any connection */ dlt_event_handler_unregister_connection(&daemon_local->pEvent, daemon_local, sock); if (daemon_local->client_connections == 0) { /* send new log state to all applications */ daemon->connectionState = 0; dlt_daemon_user_send_all_log_state(daemon, verbose); /* For offline tracing we still can use the same states */ /* as for socket sending. Using this trick we see the traces */ /* In the offline trace AND in the socket stream. */ if (daemon_local->flags.yvalue[0] == 0) dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_BUFFER); } dlt_daemon_control_message_connection_info(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, DLT_CONNECTION_STATUS_DISCONNECTED, "", verbose); snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Client connection #%d closed. Total Clients : %d", sock, daemon_local->client_connections); dlt_daemon_log_internal(daemon, daemon_local, local_str, daemon_local->flags.vflag); dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n"); return 0; } /** \} */ dlt-daemon-2.18.10/src/daemon/dlt-daemon.h000066400000000000000000000406771446635226000201640ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-daemon.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-daemon.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_DAEMON_H #define DLT_DAEMON_H #include /* for NAME_MAX */ #include #include #include "dlt_daemon_common.h" #include "dlt_user_shared.h" #include "dlt_user_shared_cfg.h" #include "dlt_daemon_event_handler_types.h" #include "dlt_gateway_types.h" #include "dlt_offline_trace.h" #define DLT_DAEMON_FLAG_MAX 256 /** * The flags of a dlt daemon. */ typedef struct { int aflag; /**< (Boolean) Print DLT messages; payload as ASCII */ int sflag; /**< (Boolean) Print DLT messages; payload as hex */ int xflag; /**< (Boolean) Print DLT messages; only headers */ int vflag; /**< (Boolean) Verbose mode */ int dflag; /**< (Boolean) Daemonize */ int lflag; /**< (Boolean) Send DLT messages with serial header */ int rflag; /**< (Boolean) Send automatic get log info response during context registration */ int mflag; /**< (Boolean) Sync to serial header on serial connection */ int nflag; /**< (Boolean) Sync to serial header on all TCP connections */ char evalue[NAME_MAX + 1]; /**< (String: ECU ID) Set ECU ID (Default: ECU1) */ char bvalue[NAME_MAX + 1]; /**< (String: Baudrate) Serial device baudrate (Default: 115200) */ char yvalue[NAME_MAX + 1]; /**< (String: Devicename) Additional support for serial device */ char ivalue[NAME_MAX + 1]; /**< (String: Directory) Directory where to store the persistant configuration (Default: /tmp) */ char cvalue[NAME_MAX + 1]; /**< (String: Directory) Filename of DLT configuration file (Default: /etc/dlt.conf) */ #ifdef DLT_LOG_LEVEL_APP_CONFIG char avalue[NAME_MAX + 1]; /**< (String: Directory) Filename of the app id default level config (Default: /etc/dlt-log-levels.conf) */ #endif int sharedMemorySize; /**< (int) Size of shared memory (Default: 100000) */ int sendMessageTime; /**< (Boolean) Send periodic Message Time if client is connected (Default: 0) */ char offlineTraceDirectory[DLT_DAEMON_FLAG_MAX]; /**< (String: Directory) Store DLT messages to local directory (Default: /etc/dlt.conf) */ int offlineTraceFileSize; /**< (int) Maximum size in bytes of one trace file (Default: 1000000) */ int offlineTraceMaxSize; /**< (int) Maximum size of all trace files (Default: 4000000) */ bool offlineTraceFilenameTimestampBased; /**< (Boolean) timestamp based or index based (Default: true=Timestamp based) */ DltLoggingMode loggingMode; /**< (int) The logging console for internal logging of dlt-daemon (Default: 0) */ int loggingLevel; /**< (int) The logging level for internal logging of dlt-daemon (Default: 6) */ char loggingFilename[DLT_DAEMON_FLAG_MAX]; /**< (String: Filename) The logging filename if internal logging mode is log to file (Default: /tmp/log) */ bool enableLoggingFileLimit; /**< (Boolean) Indicate whether size of logging file(s) is limited (Default: false) */ int loggingFileSize; /**< (int) Maximum size in bytes of one logging file (Default: 250000) */ int loggingFileMaxSize; /**< (int) Maximum size in bytes of all logging files (Default: 1000000) */ int sendECUSoftwareVersion; /**< (Boolean) Send ECU software version perdiodically */ char pathToECUSoftwareVersion[DLT_DAEMON_FLAG_MAX]; /**< (String: Filename) The file from which to read the ECU version from. */ int sendTimezone; /**< (Boolean) Send Timezone perdiodically */ int offlineLogstorageMaxDevices; /**< (int) Maximum devices to be used as offline logstorage devices */ char offlineLogstorageDirPath[DLT_MOUNT_PATH_MAX]; /**< (String: Directory) DIR path to store offline logs */ int offlineLogstorageTimestamp; /**< (int) Append timestamp in offline logstorage filename */ char offlineLogstorageDelimiter; /**< (char) Append delimeter character in offline logstorage filename */ unsigned int offlineLogstorageMaxCounter; /**< (int) Maximum offline logstorage file counter index until wraparound */ unsigned int offlineLogstorageMaxCounterIdx; /**< (int) String len of offlineLogstorageMaxCounter*/ unsigned int offlineLogstorageCacheSize; /**< Max cache size offline logstorage cache */ #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC char appSockPath[DLT_DAEMON_FLAG_MAX]; /**< Path to User socket */ #else /* DLT_DAEMON_USE_FIFO_IPC */ char userPipesDir[DLT_PATH_MAX]; /**< (String: Directory) directory where dltpipes reside (Default: /tmp/dltpipes) */ char daemonFifoName[DLT_PATH_MAX]; /**< (String: Filename) name of local fifo (Default: /tmp/dlt) */ char daemonFifoGroup[DLT_PATH_MAX]; /**< (String: Group name) Owner group of local fifo (Default: Primary Group) */ #endif #ifdef DLT_SHM_ENABLE char dltShmName[NAME_MAX + 1]; /**< Shared memory name */ #endif unsigned int port; /**< port number */ char ctrlSockPath[DLT_DAEMON_FLAG_MAX]; /**< Path to Control socket */ int gatewayMode; /**< (Boolean) Gateway Mode */ char gatewayConfigFile[DLT_DAEMON_FLAG_MAX]; /**< Gateway config file path */ int autoResponseGetLogInfoOption; /**< (int) The Option of automatic get log info response during context registration. (Default: 7)*/ int contextLogLevel; /**< (int) log level sent to context if registered with default log-level or if enforced*/ int contextTraceStatus; /**< (int) trace status sent to context if registered with default trace status or if enforced*/ int enforceContextLLAndTS; /**< (Boolean) Enforce log-level, trace-status not to exceed contextLogLevel, contextTraceStatus */ DltBindAddress_t* ipNodes; /**< (String: BindAddress) The daemon accepts connections only on this list of IP addresses */ int injectionMode; /**< (Boolean) Injection mode */ } DltDaemonFlags; /** * The global parameters of a dlt daemon. */ typedef struct { DltDaemonFlags flags; /**< flags of the daemon */ DltFile file; /**< struct for file access */ DltEventHandler pEvent; /**< struct for message producer event handling */ DltGateway pGateway; /**< struct for passive node connection handling */ DltMessage msg; /**< one dlt message */ int client_connections; /**< counter for nr. of client connections */ size_t baudrate; /**< Baudrate of serial connection */ #ifdef DLT_SHM_ENABLE DltShm dlt_shm; /**< Shared memory handling */ unsigned char *recv_buf_shm; /**< buffer for receive message from shm */ #endif MultipleFilesRingBuffer offlineTrace; /**< Offline trace handling */ MultipleFilesRingBuffer dltLogging; /**< Dlt logging handling */ int timeoutOnSend; unsigned long RingbufferMinSize; unsigned long RingbufferMaxSize; unsigned long RingbufferStepSize; unsigned long daemonFifoSize; #ifdef UDP_CONNECTION_SUPPORT int UDPConnectionSetup; /* enable/disable the UDP connection */ char UDPMulticastIPAddress[MULTICASTIP_MAX_SIZE]; /* multicast ip addres */ int UDPMulticastIPPort; /* multicast port */ #endif } DltDaemonLocal; typedef struct { unsigned long long wakeups_missed; int period_sec; int starts_in; int timer_id; } DltDaemonPeriodicData; typedef struct { DltDaemon *daemon; DltDaemonLocal *daemon_local; } DltDaemonTimingPacketThreadData; typedef DltDaemonTimingPacketThreadData DltDaemonECUVersionThreadData; #define DLT_DAEMON_ERROR_OK 0 #define DLT_DAEMON_ERROR_UNKNOWN -1 #define DLT_DAEMON_ERROR_BUFFER_FULL -2 #define DLT_DAEMON_ERROR_SEND_FAILED -3 #define DLT_DAEMON_ERROR_WRITE_FAILED -4 /* Function prototypes */ void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_local_init_p1(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); void dlt_daemon_daemonize(int verbose); void dlt_daemon_exit_trigger(); void dlt_daemon_signal_handler(int sig); #ifdef __QNX__ void dlt_daemon_cleanup_timers(); void close_pipes(int fds[2]); #endif int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *revc, int verbose); int dlt_daemon_process_client_messages_serial(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); int dlt_daemon_process_user_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); int dlt_daemon_process_one_s_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); int dlt_daemon_process_sixty_s_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); int dlt_daemon_process_systemd_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); int dlt_daemon_process_control_connect(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE int dlt_daemon_process_app_connect(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); #endif int dlt_daemon_process_control_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); typedef int (*dlt_daemon_process_user_message_func)(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_process_user_message_register_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_process_user_message_unregister_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_process_user_message_register_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_process_user_message_unregister_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local #ifdef DLT_LOG_LEVEL_APP_CONFIG ,DltDaemonApplication *app #endif ); int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_process_user_message_marker(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); void dlt_daemon_timingpacket_thread(void *ptr); void dlt_daemon_ecu_version_thread(void *ptr); #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) void dlt_daemon_systemd_watchdog_thread(void *ptr); #endif int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, DltTimers timer); int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); #endif /* DLT_DAEMON_H */ dlt-daemon-2.18.10/src/daemon/dlt-daemon.rc000066400000000000000000000003651446635226000203270ustar00rootroot00000000000000service dlt-daemon /vendor/bin/dlt-daemon class late_start user root group root socket dlt stream 666 root root socket dlt-ctrl.sock stream 660 root root disabled on post-fs-data mkdir /data/vendor/dlt 0775 root root dlt-daemon-2.18.10/src/daemon/dlt-daemon_cfg.h000066400000000000000000000120031446635226000207610ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-daemon_cfg.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-daemon-cfg.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_DAEMON_CFG_H #define DLT_DAEMON_CFG_H /*************/ /* Changable */ /*************/ /* Stack size of timing packet thread */ #define DLT_DAEMON_TIMINGPACKET_THREAD_STACKSIZE 100000 /* Stack size of ecu version thread */ #define DLT_DAEMON_ECU_VERSION_THREAD_STACKSIZE 100000 /* Size of receive buffer for shm connection (from user application) */ #define DLT_SHM_RCV_BUFFER_SIZE 10000 /* Size of receive buffer for fifo connection (from user application) */ #define DLT_DAEMON_RCVBUFSIZE 10024 /* Size of receive buffer for socket connection (from dlt client) */ #define DLT_DAEMON_RCVBUFSIZESOCK 10024 /* Size of receive buffer for serial connection (from dlt client) */ #define DLT_DAEMON_RCVBUFSIZESERIAL 10024 /* Size of buffer for text output */ #define DLT_DAEMON_TEXTSIZE 10024 /* Size of buffer */ #define DLT_DAEMON_TEXTBUFSIZE 512 /* Maximum length of a description */ #define DLT_DAEMON_DESCSIZE 256 /* Umask of daemon, creates files with permission 750 */ #define DLT_DAEMON_UMASK 027 /* Default ECU ID, used in storage header and transmitted to client*/ #define DLT_DAEMON_ECU_ID "ECU1" /* Default baudrate for serial interface */ #define DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE 115200 /************************/ /* Don't change please! */ /************************/ #endif /* DLT_DAEMON_CFG_H */ dlt-daemon-2.18.10/src/daemon/dlt-log-levels.conf000066400000000000000000000014401446635226000214510ustar00rootroot00000000000000# Configuration for default log levels. # APPIDs in this configuration file overwrite the global ContextLogLevel level from dlt.conf # It can be used to prevent single applications from logging (for example due to logging sensitive data) # or to disable file transfers from an application etc. # Furthermore single applications can use a higher log level than the default. # If the context id is empty, the configuration will be valid for all context id's of the given application id. # !!!! # Note: this file is space separated, and wildcards are not supported # !!!! # DLT_LOG_OFF = 0, DLT_LOG_FATAL = 1, DLT_LOG_ERROR = 2, DLT_LOG_WARN = 3, DLT_LOG_INFO = 4, DLT_LOG_DEBUG = 5, DLT_LOG_VERBOSE = 6 # APID [CTID] LogLevel FOO BAR 3 # configure bar TEST 3 APP1 5 # Initial loglevel for Application 1dlt-daemon-2.18.10/src/daemon/dlt.conf000066400000000000000000000217471446635226000174160ustar00rootroot00000000000000# Configuration file of DLT daemon # # Configurations made here will overwrite settings by command line ######################################################################## # General configuration # ######################################################################## # Start daemon in debug mode, so that all internal debug information is printed out on the console # Verbose = 1 # Daemonize DLT daemon, if it is started as daemon # Daemonize = 1 # Send DLT messages with serial header # SendSerialHeader = 1 # Send automatic get log info response during context registration SendContextRegistration = 1 # Option of get log info response during context registration (Default: 7) # Apid and Ctid Only = 3, with LogLevel = 4, with TraceStatus = 5, with LL and TS = 6, with LL, TS, and Description = 7 # SendContextRegistrationOption = 7 # Send automatic time packets every second if client is connected (Default: 0) # SendMessageTime = 0 # Set ECU ID (Default: ECU1) ECUId = ECU1 # Size of shared memory (Default: 100000) SharedMemorySize = 100000 # Directory where to store the persistant configuration (Default: /tmp) # PersistanceStoragePath = /tmp # The logging console for internal logging of dlt-daemon (Default: 0) # 0 = log to stdout # 1 = log to syslog # 2 = log to file (see LoggingFilename) # 3 = log to stderr LoggingMode = 0 # The internal log level, up to which logs are written (Default: 6) # LOG_EMERG = 0, LOG_ALERT = 1, LOG_CRIT = 2, LOG_ERR = 3, LOG_WARNING = 4, LOG_NOTICE = 5, LOG_INFO = 6, LOG_DEBUG = 7 LoggingLevel = 6 # The logging filename if internal logging mode is log to file (Default: /tmp/dlt.log) # If access to the file is not possible, the daemon will fall back to syslog # if WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK is set as compile flag LoggingFilename = /tmp/dlt.log # Indicate whether size of logging file(s) is limited (Default: 0) EnableLoggingFileLimit = 0 # Maximum size in bytes of one logging file (Default: 250000) # LoggingFileSize = 250000 # Maximum size in bytes of all logging files (Default: 1000000) # LoggingFileMaxSize = 1000000 # Timeout on send to client (sec) TimeOutOnSend = 4 # The minimum size of the Ringbuffer, used for storing temporary DLT messages, until client is connected (Default: 500000) RingbufferMinSize = 500000 # The max size of the Ringbuffer, used for storing temporary DLT messages, until client is connected (Default: 10000000) RingbufferMaxSize = 10000000 # The step size the Ringbuffer is increased, used for storing temporary DLT messages, until client is connected (Default: 500000) RingbufferStepSize = 500000 # The size of Daemon FIFO (/tmp/dlt) (Default: 65536, MinSize: depend on pagesize of system, MaxSize: please check /proc/sys/fs/pipe-max-size) # This is only supported for Linux. # DaemonFIFOSize = 65536 # Initial log-level that is sent when an application registers (Default: 4) # DLT_LOG_OFF = 0, DLT_LOG_FATAL = 1, DLT_LOG_ERROR = 2, DLT_LOG_WARN = 3, DLT_LOG_INFO = 4, DLT_LOG_DEBUG = 5, DLT_LOG_VERBOSE = 6 # ContextLogLevel = 4 # Initial trace-status that is sent when an application registers (Default: 0) # DLT_TRACE_STATUS_OFF = 0, DLT_TRACE_STATUS_ON = 1 # ContextTraceStatus = 0 # Force log level and trace status of context to not exceed "ContextLogLevel" and "ContextTraceStatus" (Default: 0 = OFF) # If set to 1 (ON) whenever a context registers or changes the log-level it has to be lower or equal to ContextLogLevel # ForceContextLogLevelAndTraceStatus = 1 # Allows injection mode usage (Default: 1) # InjectionMode = 1 ######################################################################## # Gateway Configuration # ######################################################################## # Enable Gateway mode (Default: 0) # GatewayMode = 1 # Read gateway configuration from another location # GatewayConfigFile = /etc/dlt_gateway.conf ######################################################################## # Permission configuration # # ==================================================================== # # Owner group of daemon FIFO directory(Default: /tmp/dlt) # (If not set, primary group of dlt-daemon process is used) # DaemonFifoGroup = dlt_user_apps_group ######################################################################## # Control Application # ######################################################################## ControlSocketPath = /tmp/dlt-ctrl.sock ######################################################################## # Offline Trace memory # ######################################################################## # Store DLT messages to local directory, if not set offline Trace is off (Default: off) # OfflineTraceDirectory = /tmp # Maximum size in bytes of one trace file (Default: 1000000) # OfflineTraceFileSize = 1000000 # Maximum size of all trace files (Default: 4000000) # OfflineTraceMaxSize = 4000000 # Filename timestamp based or index based (Default:1) (timestamp based=1, index based =0) # OfflineTraceFileNameTimestampBased = 1 ######################################################################## # Local console output configuration # ######################################################################## # Print DLT messages; payload as ASCII # PrintASCII = 1 # Print DLT messages; payload as hex # PrintHex = 1 # Print DLT messages; only headers # PrintHeadersOnly = 1 ######################################################################## # Client Serial port configuration # ######################################################################## # Additional support for serial device # If a device name is set serial port is enabled. # RS232DeviceName = /dev/ttyS0 # Serial device baudrate (Default: 115200) # RS232Baudrate = 115200 # Sync to serial header on serial connection # RS232SyncSerialHeader = 1 ######################################################################## # TCP Serial port configuration # ######################################################################## # Sync to serial header on all TCP connections # TCPSyncSerialHeader = 1 ######################################################################## # ECU Software version info # ######################################################################## # Send periodic get ecu version info (Default: 0) # SendECUSoftwareVersion = 0 # Absolute path to file storing version info - otherwise DLT version is used # PathToECUSoftwareVersion = ######################################################################## # Timezone info # ######################################################################## # Send periodic timezone info (Default: 0) # SendTimezone = 0 ############################################################################## # Offline logstorage # ############################################################################## # Store DLT log messages, if not set offline logstorage is off (Default: off) # Maximum devices to be used as offline logstorage devices # OfflineLogstorageMaxDevices = 1 # Path to store DLT offline log storage messages (Default: off) # OfflineLogstorageDirPath = /opt # File options # Appends timestamp in log file name, Disable by setting to 0 (Default: 1) # OfflineLogstorageTimestamp = 0 # Appends delimiter in log file name, allowed punctutations only (Default: _) # OfflineLogstorageDelimiter = _ # Wrap around value for log file count in file name (Default: UINT_MAX) # OfflineLogstorageMaxCounter = 999 # Maximal used memory for Logstorage Cache in KB (Default: 30000 KB) # OfflineLogstorageCacheSize = 30000 ############################################################################## # UDP Multicast Configuration # ############################################################################## # Enable UDP connection support for daemon(Control Message/Multicast is enabled) # UDPConnectionSetup = 1 # UDP multicast address(default:225.0.0.37) # UDPMulticastIPAddress = 225.0.0.37 # UDP multicast port(default:3491) # UDPMulticastIPPort = 3491 ############################################################################## # BindAddress Limitation # ############################################################################## # Accept connections only on this list of IP addresses (Default: "0.0.0.0" INADDR_ANY) # The IP addresses must be separated with ',' or ';' but not with space character ' ' # If DLT_USE_IPv6 flag is ON, then only IPv6 addresses are accepted # If DLT_USE_IPv6 flag is OFF, then only IPv4 addresses are accepted # BindAddress = 160.48.199.97;160.48.199.98 dlt-daemon-2.18.10/src/daemon/dlt_daemon_client.c000066400000000000000000003225431446635226000215720ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_client.c */ #include #include #include /* for printf() and fprintf() */ #include /* for socket(), connect(), (), and recv() */ #include /* for stat() */ #include /* for sockaddr_in and inet_addr() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include #include #include #include #ifdef linux # include #endif #include #if defined(linux) && defined(__NR_statx) # include #endif #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE # include #endif #include "dlt_types.h" #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common_cfg.h" #include "dlt_daemon_socket.h" #include "dlt_daemon_serial.h" #include "dlt_daemon_client.h" #include "dlt_daemon_connection.h" #include "dlt_daemon_event_handler.h" #include "dlt_daemon_offline_logstorage.h" #include "dlt_gateway.h" /** Inline function to calculate/set the requested log level or traces status * with default log level or trace status when "ForceContextLogLevelAndTraceStatus" * is enabled and set to 1 in dlt.conf file. * * @param request_log The requested log level (or) trace status * @param context_log The default log level (or) trace status * * @return The log level if requested log level is lower or equal to ContextLogLevel */ static inline int8_t getStatus(uint8_t request_log, int context_log) { return (request_log <= context_log) ? request_log : context_log; } #ifdef UDP_CONNECTION_SUPPORT # include "dlt_daemon_udp_socket.h" #endif /** @brief Sends up to 2 messages to all the clients. * * Runs through the client list and sends the messages to them. If the message * transfer fails and the connection is a socket connection, the socket is closed. * Takes and release dlt_daemon_mutex. * * @param daemon Daemon structure needed for socket closure. * @param daemon_local Daemon local structure * @param data1 The first message to be sent. * @param size1 The size of the first message. * @param data2 The second message to be send. * @param size2 The second message size. * @param verbose Needed for socket closure. * * @return The amount of data transfered. */ static int dlt_daemon_client_send_all_multiple(DltDaemon *daemon, DltDaemonLocal *daemon_local, void *data1, int size1, void *data2, int size2, int verbose) { int sent = 0; unsigned int i = 0; int ret = 0; DltConnection *temp = NULL; int type_mask = (DLT_CON_MASK_CLIENT_MSG_TCP | DLT_CON_MASK_CLIENT_MSG_SERIAL); PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return 0; } for (i = 0; i < daemon_local->pEvent.nfds; i++) { temp = dlt_event_handler_find_connection(&(daemon_local->pEvent), daemon_local->pEvent.pfd[i].fd); if ((temp == NULL) || (temp->receiver == NULL) || !((1 << temp->type) & type_mask)) { dlt_log(LOG_DEBUG, "The connection not found or the connection type not TCP/Serial.\n"); continue; } ret = dlt_connection_send_multiple(temp, data1, size1, data2, size2, daemon->sendserialheader); if ((ret != DLT_DAEMON_ERROR_OK) && (DLT_CONNECTION_CLIENT_MSG_TCP == temp->type)) { dlt_daemon_close_socket(temp->receiver->fd, daemon, daemon_local, verbose); } if (ret != DLT_DAEMON_ERROR_OK) dlt_vlog(LOG_WARNING, "%s: send dlt message failed\n", __func__); else /* If sent to at least one client, * then do not store in ring buffer */ sent = 1; } /* for */ return sent; } int dlt_daemon_client_send(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, void *storage_header, int storage_header_size, void *data1, int size1, void *data2, int size2, int verbose) { int sent, ret; static int sent_message_overflow_cnt = 0; if ((daemon == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid arguments\n", __func__); return DLT_DAEMON_ERROR_UNKNOWN; } if ((sock != DLT_DAEMON_SEND_TO_ALL) && (sock != DLT_DAEMON_SEND_FORCE)) { /* Send message to specific socket */ if (isatty(sock)) { if ((ret = dlt_daemon_serial_send(sock, data1, size1, data2, size2, daemon->sendserialheader))) { dlt_vlog(LOG_WARNING, "%s: serial send dlt message failed\n", __func__); return ret; } } else { if ((ret = dlt_daemon_socket_send(sock, data1, size1, data2, size2, daemon->sendserialheader))) { dlt_vlog(LOG_WARNING, "%s: socket send dlt message failed\n", __func__); return ret; } } return DLT_DAEMON_ERROR_OK; } /* write message to offline trace */ /* In the SEND_BUFFER state we must skip offline tracing because the offline traces */ /* are going without buffering directly to the offline trace. Thus we have to filter out */ /* the traces that are coming from the buffer. */ if ((sock != DLT_DAEMON_SEND_FORCE) && (daemon->state != DLT_DAEMON_STATE_SEND_BUFFER)) { if (((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) && daemon_local->flags.offlineTraceDirectory[0]) { if (dlt_offline_trace_write(&(daemon_local->offlineTrace), storage_header, storage_header_size, data1, size1, data2, size2)) { static int error_dlt_offline_trace_write_failed = 0; if (!error_dlt_offline_trace_write_failed) { dlt_vlog(LOG_ERR, "%s: dlt_offline_trace_write failed!\n", __func__); error_dlt_offline_trace_write_failed = 1; } /*return DLT_DAEMON_ERROR_WRITE_FAILED; */ } } /* write messages to offline logstorage only if there is an extended header set * this need to be checked because the function is dlt_daemon_client_send is called by * newly introduced dlt_daemon_log_internal */ if (daemon_local->flags.offlineLogstorageMaxDevices > 0) dlt_daemon_logstorage_write(daemon, &daemon_local->flags, storage_header, storage_header_size, data1, size1, data2, size2); } /* send messages to daemon socket */ if ((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) { #ifdef UDP_CONNECTION_SUPPORT if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) dlt_daemon_udp_dltmsg_multicast(data1, size1, data2, size2, verbose); #endif if ((sock == DLT_DAEMON_SEND_FORCE) || (daemon->state == DLT_DAEMON_STATE_SEND_DIRECT)) { sent = dlt_daemon_client_send_all_multiple(daemon, daemon_local, data1, size1, data2, size2, verbose); if ((sock == DLT_DAEMON_SEND_FORCE) && !sent) return DLT_DAEMON_ERROR_SEND_FAILED; } } /* Message was not sent to client, so store it in client ringbuffer */ if ((sock != DLT_DAEMON_SEND_FORCE) && ((daemon->state == DLT_DAEMON_STATE_BUFFER) || (daemon->state == DLT_DAEMON_STATE_SEND_BUFFER) || (daemon->state == DLT_DAEMON_STATE_BUFFER_FULL))) { if (daemon->state != DLT_DAEMON_STATE_BUFFER_FULL) { /* Store message in history buffer */ ret = dlt_buffer_push3(&(daemon->client_ringbuffer), data1, size1, data2, size2, 0, 0); if (ret < DLT_RETURN_OK) { dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_BUFFER_FULL); } } if (daemon->state == DLT_DAEMON_STATE_BUFFER_FULL) { daemon->overflow_counter += 1; if (daemon->overflow_counter == 1) dlt_vlog(LOG_INFO, "%s: Buffer is full! Messages will be discarded.\n", __func__); return DLT_DAEMON_ERROR_BUFFER_FULL; } } else { if ((daemon->overflow_counter > 0) && (daemon_local->client_connections > 0)) { sent_message_overflow_cnt++; if (sent_message_overflow_cnt >= 2) { sent_message_overflow_cnt--; } else { if (dlt_daemon_send_message_overflow(daemon, daemon_local, verbose) == DLT_DAEMON_ERROR_OK) { dlt_vlog(LOG_WARNING, "%s: %u messages discarded! Now able to send messages to the client.\n", __func__, daemon->overflow_counter); daemon->overflow_counter = 0; sent_message_overflow_cnt--; } } } } return DLT_DAEMON_ERROR_OK; } int dlt_daemon_client_send_message_to_all_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { static char text[DLT_DAEMON_TEXTSIZE]; char * ecu_ptr = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: invalid arguments\n", __func__); return DLT_DAEMON_ERROR_UNKNOWN; } /* set overwrite ecu id */ if ((daemon_local->flags.evalue[0]) && (strncmp(daemon_local->msg.headerextra.ecu, DLT_DAEMON_ECU_ID, DLT_ID_SIZE) == 0)) { /* Set header extra parameters */ dlt_set_id(daemon_local->msg.headerextra.ecu, daemon->ecuid); /*msg.headerextra.seid = 0; */ if (dlt_message_set_extraparameters(&(daemon_local->msg), 0)) { dlt_vlog(LOG_WARNING, "%s: failed to set message extra parameters.\n", __func__); return DLT_DAEMON_ERROR_UNKNOWN; } /* Correct value of timestamp, this was changed by dlt_message_set_extraparameters() */ daemon_local->msg.headerextra.tmsp = DLT_BETOH_32(daemon_local->msg.headerextra.tmsp); } /* prepare storage header */ if (DLT_IS_HTYP_WEID(daemon_local->msg.standardheader->htyp)) { ecu_ptr = daemon_local->msg.headerextra.ecu; } else { ecu_ptr = daemon->ecuid; } if (dlt_set_storageheader(daemon_local->msg.storageheader, ecu_ptr)) { dlt_vlog(LOG_WARNING, "%s: failed to set storage header with header type: 0x%x\n", __func__, daemon_local->msg.standardheader->htyp); return DLT_DAEMON_ERROR_UNKNOWN; } /* if no filter set or filter is matching display message */ if (daemon_local->flags.xflag) { if (DLT_RETURN_OK != dlt_message_print_hex(&(daemon_local->msg), text, DLT_DAEMON_TEXTSIZE, verbose)) dlt_log(LOG_WARNING, "dlt_message_print_hex() failed!\n"); } else if (daemon_local->flags.aflag) { if (DLT_RETURN_OK != dlt_message_print_ascii(&(daemon_local->msg), text, DLT_DAEMON_TEXTSIZE, verbose)) dlt_log(LOG_WARNING, "dlt_message_print_ascii() failed!\n"); } else if (daemon_local->flags.sflag) { if (DLT_RETURN_OK != dlt_message_print_header(&(daemon_local->msg), text, DLT_DAEMON_TEXTSIZE, verbose)) dlt_log(LOG_WARNING, "dlt_message_print_header() failed!\n"); } /* send message to client or write to log file */ return dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->msg.headerbuffer, sizeof(DltStorageHeader), daemon_local->msg.headerbuffer + sizeof(DltStorageHeader), (int) (daemon_local->msg.headersize - sizeof(DltStorageHeader)), daemon_local->msg.databuffer, (int) daemon_local->msg.datasize, verbose); } int dlt_daemon_client_send_control_message(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, char *apid, char *ctid, int verbose) { int ret; int32_t len; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == 0) || (msg == 0) || (apid == 0) || (ctid == 0)) return DLT_DAEMON_ERROR_UNKNOWN; /* prepare storage header */ msg->storageheader = (DltStorageHeader *)msg->headerbuffer; if (dlt_set_storageheader(msg->storageheader, daemon->ecuid) == DLT_RETURN_ERROR) return DLT_DAEMON_ERROR_UNKNOWN; /* prepare standard header */ msg->standardheader = (DltStandardHeader *)(msg->headerbuffer + sizeof(DltStorageHeader)); msg->standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1; #if (BYTE_ORDER == BIG_ENDIAN) msg->standardheader->htyp = (msg->standardheader->htyp | DLT_HTYP_MSBF); #endif msg->standardheader->mcnt = 0; /* Set header extra parameters */ dlt_set_id(msg->headerextra.ecu, daemon->ecuid); /*msg->headerextra.seid = 0; */ msg->headerextra.tmsp = dlt_uptime(); dlt_message_set_extraparameters(msg, verbose); /* prepare extended header */ msg->extendedheader = (DltExtendedHeader *)(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp)); msg->extendedheader->msin = DLT_MSIN_CONTROL_RESPONSE; msg->extendedheader->noar = 1; /* number of arguments */ if (strcmp(apid, "") == 0) dlt_set_id(msg->extendedheader->apid, DLT_DAEMON_CTRL_APID); /* application id */ else dlt_set_id(msg->extendedheader->apid, apid); if (strcmp(ctid, "") == 0) dlt_set_id(msg->extendedheader->ctid, DLT_DAEMON_CTRL_CTID); /* context id */ else dlt_set_id(msg->extendedheader->ctid, ctid); /* prepare length information */ msg->headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp)); len = (int32_t) (msg->headersize - sizeof(DltStorageHeader) + msg->datasize); if (len > UINT16_MAX) { dlt_log(LOG_WARNING, "Huge control message discarded!\n"); return DLT_DAEMON_ERROR_UNKNOWN; } msg->standardheader->len = DLT_HTOBE_16(((uint16_t)len)); if ((ret = dlt_daemon_client_send(sock, daemon, daemon_local, msg->headerbuffer, sizeof(DltStorageHeader), msg->headerbuffer + sizeof(DltStorageHeader), (int) (msg->headersize - sizeof(DltStorageHeader)), msg->databuffer, (int) msg->datasize, verbose))) { dlt_log(LOG_DEBUG, "dlt_daemon_control_send_control_message: DLT message send to all failed!.\n"); return ret; } return DLT_DAEMON_ERROR_OK; } int dlt_daemon_client_process_control(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { uint32_t id, id_tmp = 0; DltStandardHeaderExtra extra; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (msg == NULL)) return -1; if (msg->datasize < (int32_t)sizeof(uint32_t)) return -1; extra = msg->headerextra; /* check if the message needs to be forwarded */ if (daemon_local->flags.gatewayMode == 1) { if (strncmp(daemon_local->flags.evalue, extra.ecu, DLT_ID_SIZE) != 0) return dlt_gateway_forward_control_message(&daemon_local->pGateway, daemon_local, msg, extra.ecu, verbose); } id_tmp = *((uint32_t *)(msg->databuffer)); id = DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp); if ((id > DLT_SERVICE_ID) && (id < DLT_SERVICE_ID_CALLSW_CINJECTION)) { /* Control message handling */ switch (id) { case DLT_SERVICE_ID_SET_LOG_LEVEL: { dlt_daemon_control_set_log_level(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_SET_TRACE_STATUS: { dlt_daemon_control_set_trace_status(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_GET_LOG_INFO: { dlt_daemon_control_get_log_info(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL: { dlt_daemon_control_get_default_log_level(sock, daemon, daemon_local, verbose); break; } case DLT_SERVICE_ID_STORE_CONFIG: { if (dlt_daemon_applications_save(daemon, daemon->runtime_application_cfg, verbose) == 0) { if (dlt_daemon_contexts_save(daemon, daemon->runtime_context_cfg, verbose) == 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } else { /* Delete saved files */ dlt_daemon_control_reset_to_factory_default(daemon, daemon->runtime_application_cfg, daemon->runtime_context_cfg, daemon_local->flags.contextLogLevel, daemon_local->flags.contextTraceStatus, daemon_local->flags.enforceContextLLAndTS, verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } break; } case DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT: { dlt_daemon_control_reset_to_factory_default(daemon, daemon->runtime_application_cfg, daemon->runtime_context_cfg, daemon_local->flags.contextLogLevel, daemon_local->flags.contextTraceStatus, daemon_local->flags.enforceContextLLAndTS, verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); break; } case DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_SET_VERBOSE_MODE: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_SET_MESSAGE_FILTERING: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_SET_TIMING_PACKETS: { dlt_daemon_control_set_timing_packets(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_GET_LOCAL_TIME: { /* Send response with valid timestamp (TMSP) field */ dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); break; } case DLT_SERVICE_ID_USE_ECU_ID: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_USE_SESSION_ID: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_USE_TIMESTAMP: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_USE_EXTENDED_HEADER: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } case DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL: { dlt_daemon_control_set_default_log_level(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS: { dlt_daemon_control_set_default_trace_status(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_GET_SOFTWARE_VERSION: { dlt_daemon_control_get_software_version(sock, daemon, daemon_local, verbose); break; } case DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW: { dlt_daemon_control_message_buffer_overflow(sock, daemon, daemon_local, daemon->overflow_counter, "", verbose); break; } case DLT_SERVICE_ID_OFFLINE_LOGSTORAGE: { dlt_daemon_control_service_logstorage(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_PASSIVE_NODE_CONNECT: { dlt_daemon_control_passive_node_connect(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS: { dlt_daemon_control_passive_node_connect_status(sock, daemon, daemon_local, verbose); break; } case DLT_SERVICE_ID_SET_ALL_LOG_LEVEL: { dlt_daemon_control_set_all_log_level(sock, daemon, daemon_local, msg, verbose); break; } case DLT_SERVICE_ID_SET_ALL_TRACE_STATUS: { dlt_daemon_control_set_all_trace_status(sock, daemon, daemon_local, msg, verbose); break; } default: { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); break; } } } else { /* Injection handling */ dlt_daemon_control_callsw_cinjection(sock, daemon, daemon_local, msg, verbose); } return 0; } void dlt_daemon_control_get_software_version(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { DltMessage msg; uint32_t len; DltServiceGetSoftwareVersionResponse *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_SOFTWARE_VERSION, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } /* prepare payload of data */ len = (uint32_t) strlen(daemon->ECUVersionString); /* msg.datasize = sizeof(serviceID) + sizeof(status) + sizeof(length) + len */ msg.datasize = (uint32_t) (sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t) + len); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_SOFTWARE_VERSION, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } resp = (DltServiceGetSoftwareVersionResponse *)msg.databuffer; resp->service_id = DLT_SERVICE_ID_GET_SOFTWARE_VERSION; resp->status = DLT_SERVICE_RESPONSE_OK; resp->length = len; memcpy(msg.databuffer + msg.datasize - len, daemon->ECUVersionString, len); /* send message */ dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose); /* free message */ dlt_message_free(&msg, 0); } void dlt_daemon_control_get_default_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { DltMessage msg; DltServiceGetDefaultLogLevelResponse *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } msg.datasize = sizeof(DltServiceGetDefaultLogLevelResponse); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } resp = (DltServiceGetDefaultLogLevelResponse *)msg.databuffer; resp->service_id = DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL; resp->status = DLT_SERVICE_RESPONSE_OK; resp->log_level = (uint8_t) daemon->default_log_level; /* send message */ dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose); /* free message */ dlt_message_free(&msg, 0); } void dlt_daemon_control_get_log_info(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { DltServiceGetLogInfoRequest *req; DltMessage resp; DltDaemonContext *context = 0; DltDaemonApplication *application = 0; int num_applications = 0, num_contexts = 0; uint16_t count_app_ids = 0, count_con_ids = 0; #if (DLT_DEBUG_GETLOGINFO == 1) char buf[255]; #endif int32_t i, j; size_t offset = 0; char *apid = 0; int8_t ll, ts; uint16_t len; int8_t value; size_t sizecont = 0; int offset_base; uint32_t sid; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceGetLogInfoRequest)) < 0) return; user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; /* prepare pointer to message request */ req = (DltServiceGetLogInfoRequest *)(msg->databuffer); /* initialise new message */ if (dlt_message_init(&resp, 0) == DLT_RETURN_ERROR) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_LOG_INFO, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } /* check request */ if ((req->options < 3) || (req->options > 7)) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_LOG_INFO, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } if (req->apid[0] != '\0') { application = dlt_daemon_application_find(daemon, req->apid, daemon->ecuid, verbose); if (application) { num_applications = 1; if (req->ctid[0] != '\0') { context = dlt_daemon_context_find(daemon, req->apid, req->ctid, daemon->ecuid, verbose); num_contexts = ((context) ? 1 : 0); } else { num_contexts = application->num_contexts; } } else { num_applications = 0; num_contexts = 0; } } else { /* Request all applications and contexts */ num_applications = user_list->num_applications; num_contexts = user_list->num_contexts; } /* prepare payload of data */ /* Calculate maximum size for a response */ resp.datasize = sizeof(uint32_t) /* SID */ + sizeof(int8_t) /* status*/ + sizeof(ID4) /* DLT_DAEMON_REMO_STRING */; sizecont = sizeof(uint32_t) /* context_id */; /* Add additional size for response of Mode 4, 6, 7 */ if ((req->options == 4) || (req->options == 6) || (req->options == 7)) sizecont += sizeof(int8_t); /* log level */ /* Add additional size for response of Mode 5, 6, 7 */ if ((req->options == 5) || (req->options == 6) || (req->options == 7)) sizecont += sizeof(int8_t); /* trace status */ resp.datasize += (uint32_t) (((uint32_t) num_applications * (sizeof(uint32_t) /* app_id */ + sizeof(uint16_t) /* count_con_ids */)) + ((size_t) num_contexts * sizecont)); resp.datasize += (uint32_t) sizeof(uint16_t) /* count_app_ids */; /* Add additional size for response of Mode 7 */ if (req->options == 7) { if (req->apid[0] != '\0') { if (req->ctid[0] != '\0') { /* One application, one context */ /* context = dlt_daemon_context_find(daemon, req->apid, req->ctid, verbose); */ if (context) { resp.datasize += (uint32_t) sizeof(uint16_t) /* len_context_description */; if (context->context_description != 0) resp.datasize += (uint32_t) strlen(context->context_description); /* context_description */ } } else /* One application, all contexts */ if ((user_list->applications) && (application)) { /* Calculate start offset within contexts[] */ offset_base = 0; for (i = 0; i < (application - (user_list->applications)); i++) offset_base += user_list->applications[i].num_contexts; /* Iterate over all contexts belonging to this application */ for (j = 0; j < application->num_contexts; j++) { context = &(user_list->contexts[offset_base + j]); if (context) { resp.datasize += (uint32_t) sizeof(uint16_t) /* len_context_description */; if (context->context_description != 0) resp.datasize += (uint32_t) strlen(context->context_description); /* context_description */ } } } /* Space for application description */ if (application) { resp.datasize += (uint32_t) sizeof(uint16_t) /* len_app_description */; if (application->application_description != 0) resp.datasize += (uint32_t) strlen(application->application_description); /* app_description */ } } else { /* All applications, all contexts */ for (i = 0; i < user_list->num_contexts; i++) { resp.datasize += (uint32_t) sizeof(uint16_t) /* len_context_description */; if (user_list->contexts[i].context_description != 0) resp.datasize += (uint32_t) strlen(user_list->contexts[i].context_description); } for (i = 0; i < user_list->num_applications; i++) { resp.datasize += (uint32_t) sizeof(uint16_t) /* len_app_description */; if (user_list->applications[i].application_description != 0) resp.datasize += (uint32_t) strlen(user_list->applications[i].application_description); /* app_description */ } } } if (verbose) dlt_vlog(LOG_DEBUG, "Allocate %u bytes for response msg databuffer\n", resp.datasize); /* Allocate buffer for response message */ resp.databuffer = (uint8_t *)malloc(resp.datasize); resp.databuffersize = resp.datasize; if (resp.databuffer == 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_GET_LOG_INFO, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } memset(resp.databuffer, 0, resp.datasize); /* Preparation finished */ /* Prepare response */ sid = DLT_SERVICE_ID_GET_LOG_INFO; memcpy(resp.databuffer, &sid, sizeof(uint32_t)); offset += sizeof(uint32_t); value = (int8_t) (((num_applications != 0) && (num_contexts != 0)) ? req->options : 8); /* 8 = no matching context found */ memcpy(resp.databuffer + offset, &value, sizeof(int8_t)); offset += sizeof(int8_t); count_app_ids = (uint16_t) num_applications; if (count_app_ids != 0) { memcpy(resp.databuffer + offset, &count_app_ids, sizeof(uint16_t)); offset += sizeof(uint16_t); #if (DLT_DEBUG_GETLOGINFO == 1) dlt_vlog(LOG_DEBUG, "#apid: %d \n", count_app_ids); #endif for (i = 0; i < count_app_ids; i++) { if (req->apid[0] != '\0') { apid = req->apid; } else { if (user_list->applications) apid = user_list->applications[i].apid; else /* This should never occur! */ apid = 0; } application = dlt_daemon_application_find(daemon, apid, daemon->ecuid, verbose); if ((user_list->applications) && (application)) { /* Calculate start offset within contexts[] */ offset_base = 0; for (j = 0; j < (application - (user_list->applications)); j++) offset_base += user_list->applications[j].num_contexts; dlt_set_id((char *)(resp.databuffer + offset), apid); offset += sizeof(ID4); #if (DLT_DEBUG_GETLOGINFO == 1) dlt_print_id(buf, apid); dlt_vlog(LOG_DEBUG, "apid: %s\n", buf); #endif if (req->apid[0] != '\0') count_con_ids = (uint16_t) num_contexts; else count_con_ids = (uint16_t) application->num_contexts; memcpy(resp.databuffer + offset, &count_con_ids, sizeof(uint16_t)); offset += sizeof(uint16_t); #if (DLT_DEBUG_GETLOGINFO == 1) dlt_vlog(LOG_DEBUG, "#ctid: %d \n", count_con_ids); #endif for (j = 0; j < count_con_ids; j++) { #if (DLT_DEBUG_GETLOGINFO == 1) dlt_vlog(LOG_DEBUG, "j: %d \n", j); #endif if (!((count_con_ids == 1) && (req->apid[0] != '\0') && (req->ctid[0] != '\0'))) context = &(user_list->contexts[offset_base + j]); /* else: context was already searched and found * (one application (found) with one context (found))*/ if ((context) && ((req->ctid[0] == '\0') || ((req->ctid[0] != '\0') && (memcmp(context->ctid, req->ctid, DLT_ID_SIZE) == 0))) ) { dlt_set_id((char *)(resp.databuffer + offset), context->ctid); offset += sizeof(ID4); #if (DLT_DEBUG_GETLOGINFO == 1) dlt_print_id(buf, context->ctid); dlt_vlog(LOG_DEBUG, "ctid: %s \n", buf); #endif /* Mode 4, 6, 7 */ if ((req->options == 4) || (req->options == 6) || (req->options == 7)) { ll = context->log_level; memcpy(resp.databuffer + offset, &ll, sizeof(int8_t)); offset += sizeof(int8_t); } /* Mode 5, 6, 7 */ if ((req->options == 5) || (req->options == 6) || (req->options == 7)) { ts = context->trace_status; memcpy(resp.databuffer + offset, &ts, sizeof(int8_t)); offset += sizeof(int8_t); } /* Mode 7 */ if (req->options == 7) { if (context->context_description) { len = (uint16_t) strlen(context->context_description); memcpy(resp.databuffer + offset, &len, sizeof(uint16_t)); offset += sizeof(uint16_t); memcpy(resp.databuffer + offset, context->context_description, strlen(context->context_description)); offset += strlen(context->context_description); } else { len = 0; memcpy(resp.databuffer + offset, &len, sizeof(uint16_t)); offset += sizeof(uint16_t); } } #if (DLT_DEBUG_GETLOGINFO == 1) dlt_vlog(LOG_DEBUG, "ll=%d ts=%d \n", (int32_t)ll, (int32_t)ts); #endif } #if (DLT_DEBUG_GETLOGINFO == 1) dlt_log(LOG_DEBUG, "\n"); #endif } /* Mode 7 */ if (req->options == 7) { if (application->application_description) { len = (uint16_t) strlen(application->application_description); memcpy(resp.databuffer + offset, &len, sizeof(uint16_t)); offset += sizeof(uint16_t); memcpy(resp.databuffer + offset, application->application_description, strlen(application->application_description)); offset += strlen(application->application_description); } else { len = 0; memcpy(resp.databuffer + offset, &len, sizeof(uint16_t)); offset += sizeof(uint16_t); } } } /* if (application) */ } /* for (i=0;iservice_id = DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW; resp->status = DLT_SERVICE_RESPONSE_OK; resp->overflow = DLT_MESSAGE_BUFFER_OVERFLOW; resp->overflow_counter = overflow_counter; /* send message */ if ((ret = dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, apid, "", verbose))) { dlt_message_free(&msg, 0); return ret; } /* free message */ dlt_message_free(&msg, 0); return DLT_DAEMON_ERROR_OK; } void dlt_daemon_control_service_response(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, uint32_t service_id, int8_t status, int verbose) { DltMessage msg; DltServiceResponse *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return; /* prepare payload of data */ msg.datasize = sizeof(DltServiceResponse); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) return; resp = (DltServiceResponse *)msg.databuffer; resp->service_id = service_id; resp->status = (uint8_t) status; /* send message */ dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose); /* free message */ dlt_message_free(&msg, 0); } int dlt_daemon_control_message_unregister_context(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, char *apid, char *ctid, char *comid, int verbose) { DltMessage msg; DltServiceUnregisterContext *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return -1; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return -1; /* prepare payload of data */ msg.datasize = sizeof(DltServiceUnregisterContext); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) return -1; resp = (DltServiceUnregisterContext *)msg.databuffer; resp->service_id = DLT_SERVICE_ID_UNREGISTER_CONTEXT; resp->status = DLT_SERVICE_RESPONSE_OK; dlt_set_id(resp->apid, apid); dlt_set_id(resp->ctid, ctid); dlt_set_id(resp->comid, comid); /* send message */ if (dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose)) { dlt_message_free(&msg, 0); return -1; } /* free message */ dlt_message_free(&msg, 0); return 0; } int dlt_daemon_control_message_connection_info(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, uint8_t state, char *comid, int verbose) { DltMessage msg; DltServiceConnectionInfo *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return -1; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return -1; /* prepare payload of data */ msg.datasize = sizeof(DltServiceConnectionInfo); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) return -1; resp = (DltServiceConnectionInfo *)msg.databuffer; resp->service_id = DLT_SERVICE_ID_CONNECTION_INFO; resp->status = DLT_SERVICE_RESPONSE_OK; resp->state = state; dlt_set_id(resp->comid, comid); /* send message */ if (dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose)) { dlt_message_free(&msg, 0); return -1; } /* free message */ dlt_message_free(&msg, 0); return 0; } int dlt_daemon_control_message_timezone(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { DltMessage msg; DltServiceTimezone *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return -1; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return -1; /* prepare payload of data */ msg.datasize = sizeof(DltServiceTimezone); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) return -1; resp = (DltServiceTimezone *)msg.databuffer; resp->service_id = DLT_SERVICE_ID_TIMEZONE; resp->status = DLT_SERVICE_RESPONSE_OK; time_t t = time(NULL); struct tm lt; tzset(); localtime_r(&t, <); #if !defined(__CYGWIN__) resp->timezone = (int32_t)lt.tm_gmtoff; #endif resp->isdst = (uint8_t)lt.tm_isdst; /* send message */ if (dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose)) { dlt_message_free(&msg, 0); return -1; } /* free message */ dlt_message_free(&msg, 0); return 0; } int dlt_daemon_control_message_marker(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { DltMessage msg; DltServiceMarker *resp; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return -1; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return -1; /* prepare payload of data */ msg.datasize = sizeof(DltServiceMarker); if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) return -1; resp = (DltServiceMarker *)msg.databuffer; resp->service_id = DLT_SERVICE_ID_MARKER; resp->status = DLT_SERVICE_RESPONSE_OK; /* send message */ if (dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose)) { dlt_message_free(&msg, 0); return -1; } /* free message */ dlt_message_free(&msg, 0); return 0; } void dlt_daemon_control_callsw_cinjection(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { char apid[DLT_ID_SIZE], ctid[DLT_ID_SIZE]; uint32_t id = 0, id_tmp = 0; uint8_t *ptr; DltDaemonContext *context; uint32_t data_length_inject = 0; uint32_t data_length_inject_tmp = 0; int32_t datalength; DltUserHeader userheader; DltUserControlMsgInjection usercontext; uint8_t *userbuffer; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; datalength = (int32_t) msg->datasize; ptr = msg->databuffer; DLT_MSG_READ_VALUE(id_tmp, ptr, datalength, uint32_t); /* Get service id */ id = DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp); /* injectionMode is disabled */ if (daemon_local->flags.injectionMode == 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_PERM_DENIED, verbose); return; } /* id is always less than DLT_DAEMON_INJECTION_MAX since its type is uinit32_t */ if (id >= DLT_DAEMON_INJECTION_MIN) { /* This a a real SW-C injection call */ data_length_inject = 0; data_length_inject_tmp = 0; DLT_MSG_READ_VALUE(data_length_inject_tmp, ptr, datalength, uint32_t); /* Get data length */ data_length_inject = DLT_ENDIAN_GET_32(msg->standardheader->htyp, data_length_inject_tmp); /* Get context handle for apid, ctid (and seid) */ /* Warning: seid is ignored in this implementation! */ if (DLT_IS_HTYP_UEH(msg->standardheader->htyp)) { dlt_set_id(apid, msg->extendedheader->apid); dlt_set_id(ctid, msg->extendedheader->ctid); } else { /* No extended header, and therefore no apid and ctid available */ dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } /* At this point, apid and ctid is available */ context = dlt_daemon_context_find(daemon, apid, ctid, daemon->ecuid, verbose); if (context == 0) { /* dlt_log(LOG_INFO,"No context found!\n"); */ dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } /* Send user message to handle, specified in context */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_INJECTION) < DLT_RETURN_OK) { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } usercontext.log_level_pos = context->log_level_pos; if (data_length_inject > (uint32_t) msg->databuffersize) { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } userbuffer = malloc(data_length_inject); if (userbuffer == 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } usercontext.data_length_inject = (uint32_t) data_length_inject; usercontext.service_id = id; memcpy(userbuffer, ptr, (size_t) data_length_inject); /* Copy received injection to send buffer */ /* write to FIFO */ DltReturnValue ret = dlt_user_log_out3_with_timeout(context->user_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgInjection), userbuffer, (size_t) data_length_inject); if (ret < DLT_RETURN_OK) { if (ret == DLT_RETURN_PIPE_ERROR) { /* Close connection */ close(context->user_handle); context->user_handle = DLT_FD_INIT; } dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } free(userbuffer); userbuffer = 0; } else { /* Invalid ID */ dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED, verbose); } } void dlt_daemon_send_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltDaemonContext *context, int8_t loglevel, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int32_t id = DLT_SERVICE_ID_SET_LOG_LEVEL; int8_t old_log_level = 0; old_log_level = context->log_level; context->log_level = loglevel; /* No endianess conversion necessary*/ if ((context->user_handle >= DLT_FD_MINIMUM) && (dlt_daemon_user_send_log_level(daemon, context, verbose) == 0)) { dlt_daemon_control_service_response(sock, daemon, daemon_local, (uint32_t) id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_log(LOG_ERR, "Log level could not be sent!\n"); context->log_level = old_log_level; dlt_daemon_control_service_response(sock, daemon, daemon_local, (uint32_t) id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_find_multiple_context_and_send_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int8_t app_flag, char *str, int8_t len, int8_t loglevel, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int count = 0; DltDaemonContext *context = NULL; char src_str[DLT_ID_SIZE + 1] = { 0 }; int ret = 0; DltDaemonRegisteredUsers *user_list = NULL; if (daemon == 0) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return; } user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; for (count = 0; count < user_list->num_contexts; count++) { context = &(user_list->contexts[count]); if (context) { if (app_flag == 1) strncpy(src_str, context->apid, DLT_ID_SIZE); else strncpy(src_str, context->ctid, DLT_ID_SIZE); ret = strncmp(src_str, str, len); if (ret == 0) dlt_daemon_send_log_level(sock, daemon, daemon_local, context, loglevel, verbose); else if ((ret > 0) && (app_flag == 1)) break; else continue; } } } void dlt_daemon_control_set_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); char apid[DLT_ID_SIZE + 1] = { 0 }; char ctid[DLT_ID_SIZE + 1] = { 0 }; DltServiceSetLogLevel *req = NULL; DltDaemonContext *context = NULL; int8_t apid_length = 0; int8_t ctid_length = 0; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetLogLevel)) < 0) return; req = (DltServiceSetLogLevel *)(msg->databuffer); if (daemon_local->flags.enforceContextLLAndTS) req->log_level = (uint8_t) getStatus(req->log_level, daemon_local->flags.contextLogLevel); dlt_set_id(apid, req->apid); dlt_set_id(ctid, req->ctid); apid_length = (int8_t) strlen(apid); ctid_length = (int8_t) strlen(ctid); if ((apid_length != 0) && (apid[apid_length - 1] == '*') && (ctid[0] == 0)) { /*apid provided having '*' in it and ctid is null*/ dlt_daemon_find_multiple_context_and_send_log_level(sock, daemon, daemon_local, 1, apid, (int8_t) (apid_length - 1), (int8_t) req->log_level, verbose); } else if ((ctid_length != 0) && (ctid[ctid_length - 1] == '*') && (apid[0] == 0)) /*ctid provided is having '*' in it and apid is null*/ { dlt_daemon_find_multiple_context_and_send_log_level(sock, daemon, daemon_local, 0, ctid, (int8_t) (ctid_length - 1), (int8_t) req->log_level, verbose); } else if ((apid_length != 0) && (apid[apid_length - 1] != '*') && (ctid[0] == 0)) /*only app id case*/ { dlt_daemon_find_multiple_context_and_send_log_level(sock, daemon, daemon_local, 1, apid, DLT_ID_SIZE, (int8_t) req->log_level, verbose); } else if ((ctid_length != 0) && (ctid[ctid_length - 1] != '*') && (apid[0] == 0)) /*only context id case*/ { dlt_daemon_find_multiple_context_and_send_log_level(sock, daemon, daemon_local, 0, ctid, DLT_ID_SIZE, (int8_t) req->log_level, verbose); } else { context = dlt_daemon_context_find(daemon, apid, ctid, daemon->ecuid, verbose); /* Set log level */ if (context != 0) { dlt_daemon_send_log_level(sock, daemon, daemon_local, context, (int8_t) req->log_level, verbose); } else { dlt_vlog(LOG_ERR, "Could not set log level: %d. Context [%.4s:%.4s] not found:", req->log_level, apid, ctid); dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_SET_LOG_LEVEL, DLT_SERVICE_RESPONSE_ERROR, verbose); } } } void dlt_daemon_send_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltDaemonContext *context, int8_t tracestatus, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int32_t id = DLT_SERVICE_ID_SET_TRACE_STATUS; int8_t old_trace_status = 0; old_trace_status = context->trace_status; context->trace_status = tracestatus; /* No endianess conversion necessary*/ if ((context->user_handle >= DLT_FD_MINIMUM) && (dlt_daemon_user_send_log_level(daemon, context, verbose) == 0)) { dlt_daemon_control_service_response(sock, daemon, daemon_local, (uint32_t) id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_log(LOG_ERR, "Trace status could not be sent!\n"); context->trace_status = old_trace_status; dlt_daemon_control_service_response(sock, daemon, daemon_local, (uint32_t) id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_find_multiple_context_and_send_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int8_t app_flag, char *str, int8_t len, int8_t tracestatus, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int count = 0; DltDaemonContext *context = NULL; char src_str[DLT_ID_SIZE + 1] = { 0 }; int ret = 0; DltDaemonRegisteredUsers *user_list = NULL; if (daemon == 0) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return; } user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; for (count = 0; count < user_list->num_contexts; count++) { context = &(user_list->contexts[count]); if (context) { if (app_flag == 1) strncpy(src_str, context->apid, DLT_ID_SIZE); else strncpy(src_str, context->ctid, DLT_ID_SIZE); ret = strncmp(src_str, str, len); if (ret == 0) dlt_daemon_send_trace_status(sock, daemon, daemon_local, context, tracestatus, verbose); else if ((ret > 0) && (app_flag == 1)) break; else continue; } } } void dlt_daemon_control_set_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); char apid[DLT_ID_SIZE + 1] = { 0 }; char ctid[DLT_ID_SIZE + 1] = { 0 }; DltServiceSetLogLevel *req = NULL; DltDaemonContext *context = NULL; int8_t apid_length = 0; int8_t ctid_length = 0; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetLogLevel)) < 0) return; req = (DltServiceSetLogLevel *)(msg->databuffer); if (daemon_local->flags.enforceContextLLAndTS) req->log_level = (uint8_t) getStatus(req->log_level, daemon_local->flags.contextTraceStatus); dlt_set_id(apid, req->apid); dlt_set_id(ctid, req->ctid); apid_length = (int8_t) strlen(apid); ctid_length = (int8_t) strlen(ctid); if ((apid_length != 0) && (apid[apid_length - 1] == '*') && (ctid[0] == 0)) { /*apid provided having '*' in it and ctid is null*/ dlt_daemon_find_multiple_context_and_send_trace_status(sock, daemon, daemon_local, 1, apid, (int8_t) (apid_length - 1), (int8_t) req->log_level, verbose); } else if ((ctid_length != 0) && (ctid[ctid_length - 1] == '*') && (apid[0] == 0)) /*ctid provided is having '*' in it and apid is null*/ { dlt_daemon_find_multiple_context_and_send_trace_status(sock, daemon, daemon_local, 0, ctid, (int8_t) (ctid_length - 1), (int8_t) req->log_level, verbose); } else if ((apid_length != 0) && (apid[apid_length - 1] != '*') && (ctid[0] == 0)) /*only app id case*/ { dlt_daemon_find_multiple_context_and_send_trace_status(sock, daemon, daemon_local, 1, apid, DLT_ID_SIZE, (int8_t) req->log_level, verbose); } else if ((ctid_length != 0) && (ctid[ctid_length - 1] != '*') && (apid[0] == 0)) /*only context id case*/ { dlt_daemon_find_multiple_context_and_send_trace_status(sock, daemon, daemon_local, 0, ctid, DLT_ID_SIZE, (int8_t) req->log_level, verbose); } else { context = dlt_daemon_context_find(daemon, apid, ctid, daemon->ecuid, verbose); /* Set trace status */ if (context != 0) { dlt_daemon_send_trace_status(sock, daemon, daemon_local, context, (int8_t) req->log_level, verbose); } else { dlt_vlog(LOG_ERR, "Could not set trace status: %d. Context [%.4s:%.4s] not found:", req->log_level, apid, ctid); dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_SET_LOG_LEVEL, DLT_SERVICE_RESPONSE_ERROR, verbose); } } } void dlt_daemon_control_set_default_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); DltServiceSetDefaultLogLevel *req; uint32_t id = DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetDefaultLogLevel)) < 0) return; req = (DltServiceSetDefaultLogLevel *)(msg->databuffer); /* No endianess conversion necessary */ if (/*(req->log_level>=0) &&*/ (req->log_level <= DLT_LOG_VERBOSE)) { if (daemon_local->flags.enforceContextLLAndTS) daemon->default_log_level = getStatus(req->log_level, daemon_local->flags.contextLogLevel); else daemon->default_log_level = (int8_t) req->log_level; /* No endianess conversion necessary */ /* Send Update to all contexts using the default log level */ dlt_daemon_user_send_default_update(daemon, verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_control_set_all_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); DltServiceSetDefaultLogLevel *req = NULL; uint32_t id = DLT_SERVICE_ID_SET_ALL_LOG_LEVEL; int8_t loglevel = 0; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return; } if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetDefaultLogLevel)) < 0) return; req = (DltServiceSetDefaultLogLevel *)(msg->databuffer); /* No endianess conversion necessary */ if ((req != NULL) && ((req->log_level <= DLT_LOG_VERBOSE) || (req->log_level == (uint8_t)DLT_LOG_DEFAULT))) { loglevel = (int8_t) req->log_level; /* Send Update to all contexts using the new log level */ dlt_daemon_user_send_all_log_level_update( daemon, daemon_local->flags.enforceContextLLAndTS, (int8_t)daemon_local->flags.contextLogLevel, loglevel, verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_control_set_default_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); /* Payload of request message */ DltServiceSetDefaultLogLevel *req; uint32_t id = DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetDefaultLogLevel)) < 0) return; req = (DltServiceSetDefaultLogLevel *)(msg->databuffer); /* No endianess conversion necessary */ if ((req->log_level == DLT_TRACE_STATUS_OFF) || (req->log_level == DLT_TRACE_STATUS_ON)) { if (daemon_local->flags.enforceContextLLAndTS) daemon->default_trace_status = getStatus(req->log_level, daemon_local->flags.contextTraceStatus); else daemon->default_trace_status = (int8_t) req->log_level; /* No endianess conversion necessary*/ /* Send Update to all contexts using the default trace status */ dlt_daemon_user_send_default_update(daemon, verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_control_set_all_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); DltServiceSetDefaultLogLevel *req = NULL; uint32_t id = DLT_SERVICE_ID_SET_ALL_TRACE_STATUS; int8_t tracestatus = 0; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return; } if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetDefaultLogLevel)) < 0) return; req = (DltServiceSetDefaultLogLevel *)(msg->databuffer); /* No endianess conversion necessary */ if ((req != NULL) && ((req->log_level <= DLT_TRACE_STATUS_ON) || (req->log_level == (uint8_t)DLT_TRACE_STATUS_DEFAULT))) { if (daemon_local->flags.enforceContextLLAndTS) tracestatus = getStatus(req->log_level, daemon_local->flags.contextTraceStatus); else tracestatus = (int8_t) req->log_level; /* No endianess conversion necessary */ /* Send Update to all contexts using the new log level */ dlt_daemon_user_send_all_trace_status_update(daemon, tracestatus, verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_control_set_timing_packets(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); DltServiceSetVerboseMode *req; /* request uses same struct as set verbose mode */ uint32_t id = DLT_SERVICE_ID_SET_TIMING_PACKETS; if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceSetVerboseMode)) < 0) return; req = (DltServiceSetVerboseMode *)(msg->databuffer); if ((req->new_status == 0) || (req->new_status == 1)) { daemon->timingpackets = req->new_status; dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_control_message_time(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { DltMessage msg; int32_t len; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == 0) return; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return; /* send message */ /* prepare storage header */ msg.storageheader = (DltStorageHeader *)msg.headerbuffer; dlt_set_storageheader(msg.storageheader, daemon->ecuid); /* prepare standard header */ msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1; #if (BYTE_ORDER == BIG_ENDIAN) msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF); #endif msg.standardheader->mcnt = 0; /* Set header extra parameters */ dlt_set_id(msg.headerextra.ecu, daemon->ecuid); msg.headerextra.tmsp = dlt_uptime(); dlt_message_set_extraparameters(&msg, verbose); /* prepare extended header */ msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); msg.extendedheader->msin = DLT_MSIN_CONTROL_TIME; msg.extendedheader->noar = 0; /* number of arguments */ dlt_set_id(msg.extendedheader->apid, ""); /* application id */ dlt_set_id(msg.extendedheader->ctid, ""); /* context id */ /* prepare length information */ msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); len = (int32_t) (msg.headersize - sizeof(DltStorageHeader) + msg.datasize); if (len > UINT16_MAX) { dlt_log(LOG_WARNING, "Huge control message discarded!\n"); /* free message */ dlt_message_free(&msg, 0); return; } msg.standardheader->len = DLT_HTOBE_16(((uint16_t)len)); /* Send message, ignore return value */ dlt_daemon_client_send(sock, daemon, daemon_local, msg.headerbuffer, sizeof(DltStorageHeader), msg.headerbuffer + sizeof(DltStorageHeader), (int) msg.headersize - (int) sizeof(DltStorageHeader), msg.databuffer, (int) msg.datasize, verbose); /* free message */ dlt_message_free(&msg, 0); } int dlt_daemon_process_one_s_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { uint64_t expir = 0; ssize_t res = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon_local == NULL) || (daemon == NULL) || (receiver == NULL)) { dlt_vlog(LOG_ERR, "%s: invalid parameters", __func__); return -1; } res = read(receiver->fd, &expir, sizeof(expir)); if (res < 0) { dlt_vlog(LOG_WARNING, "%s: Fail to read timer (%s)\n", __func__, strerror(errno)); /* Activity received on timer_wd, but unable to read the fd: * let's go on sending notification */ } if ((daemon->state == DLT_DAEMON_STATE_SEND_BUFFER) || (daemon->state == DLT_DAEMON_STATE_BUFFER_FULL)) { if (dlt_daemon_send_ringbuffer_to_client(daemon, daemon_local, daemon_local->flags.vflag)) dlt_log(LOG_DEBUG, "Can't send contents of ring buffer to clients\n"); } if ((daemon->timingpackets) && (daemon->state == DLT_DAEMON_STATE_SEND_DIRECT)) dlt_daemon_control_message_time(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag); dlt_log(LOG_DEBUG, "Timer timingpacket\n"); return 0; } int dlt_daemon_process_sixty_s_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { uint64_t expir = 0; ssize_t res = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon_local == NULL) || (daemon == NULL) || (receiver == NULL)) { dlt_vlog(LOG_ERR, "%s: invalid parameters", __func__); return -1; } res = read(receiver->fd, &expir, sizeof(expir)); if (res < 0) { dlt_vlog(LOG_WARNING, "%s: Fail to read timer (%s)\n", __func__, strerror(errno)); /* Activity received on timer_wd, but unable to read the fd: * let's go on sending notification */ } if (daemon_local->flags.sendECUSoftwareVersion > 0) dlt_daemon_control_get_software_version(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag); if (daemon_local->flags.sendTimezone > 0) { /* send timezone information */ time_t t = time(NULL); struct tm lt; /*Added memset to avoid compiler warning for near initialization */ memset((void *)<, 0, sizeof(lt)); tzset(); localtime_r(&t, <); dlt_daemon_control_message_timezone(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag); } dlt_log(LOG_DEBUG, "Timer ecuversion\n"); return 0; } #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE int dlt_daemon_process_systemd_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { uint64_t expir = 0; ssize_t res = -1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon_local == NULL) || (daemon == NULL) || (receiver == NULL)) { dlt_vlog(LOG_ERR, "%s: invalid parameters", __func__); return res; } res = read(receiver->fd, &expir, sizeof(expir)); if (res < 0) { dlt_vlog(LOG_WARNING, "Failed to read timer_wd; %s\n", strerror(errno)); /* Activity received on timer_wd, but unable to read the fd: * let's go on sending notification */ } #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE if (!daemon->received_message_since_last_watchdog_interval) { dlt_log(LOG_WARNING, "No new messages received since last watchdog timer run\n"); return 0; } daemon->received_message_since_last_watchdog_interval = 0; #endif if (sd_notify(0, "WATCHDOG=1") < 0) dlt_log(LOG_CRIT, "Could not reset systemd watchdog\n"); dlt_log(LOG_DEBUG, "Timer watchdog\n"); return 0; } #else int dlt_daemon_process_systemd_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { (void)daemon; (void)daemon_local; (void)receiver; (void)verbose; dlt_log(LOG_DEBUG, "Timer watchdog not enabled\n"); return -1; } #endif void dlt_daemon_control_service_logstorage(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { DltServiceOfflineLogstorage *req; int ret; unsigned int connection_type = 0; DltLogStorage *device = NULL; int device_index = -1; uint32_t i = 0; int tmp_errno = 0; struct stat daemon_mpoint_st = {0}; int daemon_st_status = 0; struct stat req_mpoint_st = {0}; int req_st_status = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (msg == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__); return; } if ((daemon_local->flags.offlineLogstorageMaxDevices <= 0) || (msg->databuffer == NULL)) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); dlt_log(LOG_INFO, "Logstorage functionality not enabled or MAX device set is 0\n"); return; } if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceOfflineLogstorage)) < 0) return; req = (DltServiceOfflineLogstorage *)(msg->databuffer); if(req->connection_type != DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) { req_st_status = stat(req->mount_point, &req_mpoint_st); tmp_errno = errno; if (req_st_status < 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); dlt_vlog(LOG_WARNING, "%s: Failed to stat requested mount point [%s] with error [%s]\n", __func__, req->mount_point, strerror(tmp_errno)); return; } } for (i = 0; i < (uint32_t) daemon_local->flags.offlineLogstorageMaxDevices; i++) { connection_type = daemon->storage_handle[i].connection_type; memset(&daemon_mpoint_st, 0, sizeof(struct stat)); if (strlen(daemon->storage_handle[i].device_mount_point) > 1) { daemon_st_status = stat(daemon->storage_handle[i].device_mount_point, &daemon_mpoint_st); tmp_errno = errno; if (daemon_st_status < 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); dlt_vlog(LOG_WARNING, "%s: Failed to stat daemon mount point [%s] with error [%s]\n", __func__, daemon->storage_handle[i].device_mount_point, strerror(tmp_errno)); return; } /* Check if the requested device path is already used as log storage device */ if (req_mpoint_st.st_dev == daemon_mpoint_st.st_dev && req_mpoint_st.st_ino == daemon_mpoint_st.st_ino) { device_index = (int) i; break; } } /* Get first available device index here */ if ((connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) && (device_index == -1)) device_index = (int) i; } /* It might be possible to sync all caches of all devices */ if ((req->connection_type == DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) && (strlen(req->mount_point) == 0)) { /* It is expected to receive an empty mount point to sync all Logstorage * devices in this case. */ } else if (device_index == -1) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); dlt_log(LOG_WARNING, "MAX devices already in use \n"); return; } /* Check for device connection request from log storage ctrl app */ device = &daemon->storage_handle[device_index]; if (req->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { ret = dlt_logstorage_device_connected(device, req->mount_point); if (ret == 1) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_WARNING, verbose); return; } else if (ret != 0) { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_OK, verbose); /* Update maintain logstorage loglevel if necessary */ if (daemon->storage_handle[device_index].maintain_logstorage_loglevel != DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_UNDEF) { daemon->maintain_logstorage_loglevel = daemon->storage_handle[device_index].maintain_logstorage_loglevel; } /* Check if log level of running application needs an update */ dlt_daemon_logstorage_update_application_loglevel(daemon, daemon_local, device_index, verbose); } /* Check for device disconnection request from log storage ctrl app */ else if (req->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED) { /* Check if log level of running application needs to be reset */ dlt_daemon_logstorage_reset_application_loglevel( daemon, daemon_local, device_index, (int) daemon_local->flags.offlineLogstorageMaxDevices, verbose); dlt_logstorage_device_disconnected(&(daemon->storage_handle[device_index]), DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_OK, verbose); } /* Check for cache synchronization request from log storage ctrl app */ else if (req->connection_type == DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) { ret = 0; if (device_index == -1) { /* sync all Logstorage devices */ for (i = 0; i < (uint32_t) daemon_local->flags.offlineLogstorageMaxDevices; i++) if (daemon->storage_handle[i].connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) ret = dlt_daemon_logstorage_sync_cache( daemon, daemon_local, daemon->storage_handle[i].device_mount_point, verbose); } else { /* trigger logstorage to sync caches */ ret = dlt_daemon_logstorage_sync_cache(daemon, daemon_local, req->mount_point, verbose); } if (ret == 0) dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_OK, verbose); else dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); } else { dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); } } void dlt_daemon_control_passive_node_connect(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); DltServicePassiveNodeConnect *req; uint32_t id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECT; if ((daemon == NULL) || (daemon_local == NULL) || (msg == NULL) || (msg->databuffer == NULL)) return; /* return error, if gateway mode not enabled*/ if (daemon_local->flags.gatewayMode == 0) { dlt_log(LOG_WARNING, "Received passive node connection status request, " "but GatewayMode is disabled\n"); dlt_daemon_control_service_response( sock, daemon, daemon_local, DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServicePassiveNodeConnect)) < 0) return; req = (DltServicePassiveNodeConnect *)msg->databuffer; if (dlt_gateway_process_on_demand_request(&daemon_local->pGateway, daemon_local, req->node_id, (int) req->connection_status, verbose) < 0) dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_ERROR, verbose); else dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } void dlt_daemon_control_passive_node_connect_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { DltMessage msg; DltServicePassiveNodeConnectionInfo *resp; DltGatewayConnection *con = NULL; unsigned int i = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL)) return; if (dlt_message_init(&msg, verbose) == -1) return; /* return error, if gateway mode not enabled*/ if (daemon_local->flags.gatewayMode == 0) { dlt_log(LOG_WARNING, "Received passive node connection status request, " "but GatewayMode is disabled\n"); dlt_daemon_control_service_response( sock, daemon, daemon_local, DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS, DLT_SERVICE_RESPONSE_ERROR, verbose); return; } /* prepare payload of data */ msg.datasize = sizeof(DltServicePassiveNodeConnectionInfo); if (msg.databuffer && (msg.databuffersize < msg.datasize)) msg.databuffer = NULL; if (msg.databuffer == NULL) { msg.databuffer = (uint8_t *)malloc(msg.datasize); if (msg.databuffer == NULL) { dlt_log(LOG_CRIT, "Cannot allocate memory for message response\n"); return; } msg.databuffersize = msg.datasize; } resp = (DltServicePassiveNodeConnectionInfo *)msg.databuffer; memset(resp, 0, msg.datasize); resp->service_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS; resp->status = DLT_SERVICE_RESPONSE_OK; resp->num_connections = (uint32_t) daemon_local->pGateway.num_connections; for (i = 0; i < resp->num_connections; i++) { if ((i * DLT_ID_SIZE) > DLT_ENTRY_MAX) { dlt_log(LOG_ERR, "Maximal message size reached. Skip further information\n"); break; } con = &daemon_local->pGateway.connections[i]; if (con == NULL) { dlt_log(LOG_CRIT, "Passive node connection structure is NULL\n"); dlt_daemon_control_service_response( sock, daemon, daemon_local, DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS, DLT_SERVICE_RESPONSE_ERROR, verbose); /* free message */ dlt_message_free(&msg, verbose); return; } resp->connection_status[i] = con->status; memcpy(&resp->node_id[i * DLT_ID_SIZE], con->ecuid, DLT_ID_SIZE); } dlt_daemon_client_send_control_message(sock, daemon, daemon_local, &msg, "", "", verbose); /* free message */ dlt_message_free(&msg, verbose); } dlt-daemon-2.18.10/src/daemon/dlt_daemon_client.h000066400000000000000000000465071446635226000216020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_client.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_client.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #ifndef DLT_DAEMON_CLIENT_H #define DLT_DAEMON_CLIENT_H #include /* for NAME_MAX */ #include "dlt_daemon_common.h" #include "dlt_user_shared.h" #include "dlt_user_shared_cfg.h" #include #include /** * Send out message to client or store message in offline trace. * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param storage_header pointer to data * @param storage_header_size size of data * @param data1 pointer to data * @param size1 size of data * @param data2 pointer to data * @param size2 size of data * @param verbose if set to true verbose information is printed out. * @return unequal 0 if there is an error or buffer is full */ int dlt_daemon_client_send(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, void *storage_header, int storage_header_size, void *data1, int size1, void *data2, int size2, int verbose); /** * Send out message to all client or store message in offline trace. * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. * @return 0 if success, less than 0 if there is an error or buffer is full */ int dlt_daemon_client_send_message_to_all_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Send out response message to dlt client * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to response message * @param apid pointer to application id to be used in response message * @param ctid pointer to context id to be used in response message * @param verbose if set to true verbose information is printed out. * @return -1 if there is an error or buffer is full */ int dlt_daemon_client_send_control_message(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, char *apid, char *ctid, int verbose); /** * Process and generate response to received get log info control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_get_log_info(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received get software version control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_get_software_version(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Process and generate response to received get default log level control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_get_default_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Process and generate response to message buffer overflow control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param overflow_counter Overflow counter * @param apid Application ID * @param verbose if set to true verbose information is printed out. * @return -1 if there is an error or buffer overflow, else 0 */ int dlt_daemon_control_message_buffer_overflow(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, unsigned int overflow_counter, char *apid, int verbose); /** * Generate response to control message from dlt client * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param service_id service id of control message * @param status status of response (e.g. ok, not supported, error) * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_service_response(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, uint32_t service_id, int8_t status, int verbose); /** * Send control message unregister context (add on to AUTOSAR standard) * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param apid application id to be unregisteres * @param ctid context id to be unregistered * @param comid Communication id where apid is unregistered * @param verbose if set to true verbose information is printed out. */ int dlt_daemon_control_message_unregister_context(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, char *apid, char *ctid, char *comid, int verbose); /** * Send control message connection info (add on to AUTOSAR standard) * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param state state of connection * @param comid Communication id where connection state changed * @param verbose if set to true verbose information is printed out. */ int dlt_daemon_control_message_connection_info(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, uint8_t state, char *comid, int verbose); /** * Send control message timezone (add on to AUTOSAR standard) * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. */ int dlt_daemon_control_message_timezone(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Send control message marker (add on to AUTOSAR standard) * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. */ int dlt_daemon_control_message_marker(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Process received control message from dlt client * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ int dlt_daemon_client_process_control(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received sw injection control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received sw injection control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_callsw_cinjection(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received set log level control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received set trace status control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received set default log level control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_default_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received set all log level control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_all_log_level(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received set default trace status control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_default_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received set all trace status control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_all_trace_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to set timing packets control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_set_timing_packets(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Send time control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_message_time(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Service offline logstorage command request * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_service_logstorage(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received passive node connect control * message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param msg pointer to received control message * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_passive_node_connect(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose); /** * Process and generate response to received passive node connection status * control message * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure * @param daemon_local pointer to dlt daemon local structure * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_passive_node_connect_status(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); #endif /* DLT_DAEMON_CLIENT_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_common.c000066400000000000000000001711421446635226000216010ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_common.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_common.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include #include #include #include #include #include #include #include #include /* send() */ #include "dlt_types.h" #include "dlt_daemon_common.h" #include "dlt_daemon_common_cfg.h" #include "dlt_user_shared.h" #include "dlt_user_shared_cfg.h" #include "dlt-daemon.h" #include "dlt_daemon_socket.h" #include "dlt_daemon_serial.h" char *app_recv_buffer = NULL; /* pointer to receiver buffer for application msges */ static int dlt_daemon_cmp_apid(const void *m1, const void *m2) { if ((m1 == NULL) || (m2 == NULL)) return -1; DltDaemonApplication *mi1 = (DltDaemonApplication *)m1; DltDaemonApplication *mi2 = (DltDaemonApplication *)m2; return memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE); } static int dlt_daemon_cmp_apid_ctid(const void *m1, const void *m2) { if ((m1 == NULL) || (m2 == NULL)) return -1; int ret, cmp; DltDaemonContext *mi1 = (DltDaemonContext *)m1; DltDaemonContext *mi2 = (DltDaemonContext *)m2; cmp = memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE); if (cmp < 0) ret = -1; else if (cmp == 0) ret = memcmp(mi1->ctid, mi2->ctid, DLT_ID_SIZE); else ret = 1; return ret; } DltDaemonRegisteredUsers *dlt_daemon_find_users_list(DltDaemon *daemon, char *ecu, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int i = 0; if ((daemon == NULL) || (ecu == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameters", __func__); return (DltDaemonRegisteredUsers *)NULL; } for (i = 0; i < daemon->num_user_lists; i++) if (strncmp(ecu, daemon->user_list[i].ecu, DLT_ID_SIZE) == 0) return &daemon->user_list[i]; dlt_vlog(LOG_ERR, "Cannot find user list for ECU: %4s\n", ecu); return (DltDaemonRegisteredUsers *)NULL; } #ifdef DLT_LOG_LEVEL_APP_CONFIG static int dlt_daemon_cmp_log_settings(const void *lhs, const void *rhs) { if ((lhs == NULL) || (rhs == NULL)) return -1; DltDaemonContextLogSettings *settings1 = (DltDaemonContextLogSettings *)lhs; DltDaemonContextLogSettings *settings2 = (DltDaemonContextLogSettings *)rhs; int cmp = memcmp(settings1->apid, settings2->apid, DLT_ID_SIZE); if (cmp < 0) return -1; else if (cmp == 0) return memcmp(settings1->ctid, settings2->ctid, DLT_ID_SIZE); else return 1; } /** * Find configuration for app/ctx id specific log settings configuration * @param daemon pointer to dlt daemon struct * @param apid application id to use * @param ctid context id to use, can be NULL * @return pointer to log settings if found, otherwise NULL */ DltDaemonContextLogSettings *dlt_daemon_find_configured_app_id_ctx_id_settings( const DltDaemon *daemon, const char *apid, const char *ctid) { DltDaemonContextLogSettings *app_id_settings = NULL; for (int i = 0; i < daemon->num_app_id_log_level_settings; ++i) { DltDaemonContextLogSettings *settings = &daemon->app_id_log_level_settings[i]; if (strncmp(apid, settings->apid, DLT_ID_SIZE) != 0) { if (app_id_settings != NULL) return app_id_settings; continue; } if (strlen(settings->ctid) == 0) { app_id_settings = settings; } if (ctid == NULL || strlen(ctid) == 0) { if (app_id_settings != NULL) { return app_id_settings; } } else { if (strncmp(ctid, settings->ctid, DLT_ID_SIZE) == 0) { return settings; } } } return app_id_settings; } /** * Find configured log levels in a given DltDaemonApplication for the passed context id. * @param app The application settings which contain the previously loaded ap id settings * @param ctid The context id to find. * @return Pointer to DltDaemonApplicationLogSettings containing the log level * for the requested application or NULL if none found. */ DltDaemonContextLogSettings *dlt_daemon_find_app_log_level_config( const DltDaemonApplication *const app, const char *const ctid) { if (NULL == ctid) return NULL; DltDaemonContextLogSettings settings; memcpy(settings.apid, app->apid, DLT_ID_SIZE); memcpy(settings.ctid, ctid, DLT_ID_SIZE); DltDaemonContextLogSettings* log_settings = NULL; log_settings = (DltDaemonContextLogSettings *)bsearch( &settings, app->context_log_level_settings, (size_t)app->num_context_log_level_settings, sizeof(DltDaemonContextLogSettings), dlt_daemon_cmp_log_settings); return log_settings; } #endif int dlt_daemon_init_runtime_configuration(DltDaemon *daemon, const char *runtime_directory, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); size_t append_length = 0; if (daemon == NULL) return DLT_RETURN_ERROR; /* Default */ daemon->mode = DLT_USER_MODE_EXTERNAL; if (runtime_directory == NULL) return DLT_RETURN_ERROR; /* prepare filenames for configuration */ append_length = PATH_MAX - sizeof(DLT_RUNTIME_APPLICATION_CFG); if (runtime_directory[0]) { strncpy(daemon->runtime_application_cfg, runtime_directory, append_length); daemon->runtime_application_cfg[append_length] = 0; } else { strncpy(daemon->runtime_application_cfg, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length); daemon->runtime_application_cfg[append_length] = 0; } strcat(daemon->runtime_application_cfg, DLT_RUNTIME_APPLICATION_CFG); /* strcat uncritical here, because max length already checked */ append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONTEXT_CFG); if (runtime_directory[0]) { strncpy(daemon->runtime_context_cfg, runtime_directory, append_length); daemon->runtime_context_cfg[append_length] = 0; } else { strncpy(daemon->runtime_context_cfg, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length); daemon->runtime_context_cfg[append_length] = 0; } strcat(daemon->runtime_context_cfg, DLT_RUNTIME_CONTEXT_CFG); /* strcat uncritical here, because max length already checked */ append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONFIGURATION); if (runtime_directory[0]) { strncpy(daemon->runtime_configuration, runtime_directory, append_length); daemon->runtime_configuration[append_length] = 0; } else { strncpy(daemon->runtime_configuration, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length); daemon->runtime_configuration[append_length] = 0; } strcat(daemon->runtime_configuration, DLT_RUNTIME_CONFIGURATION); /* strcat uncritical here, because max length already checked */ return DLT_RETURN_OK; } int dlt_daemon_init(DltDaemon *daemon, unsigned long RingbufferMinSize, unsigned long RingbufferMaxSize, unsigned long RingbufferStepSize, const char *runtime_directory, int InitialContextLogLevel, int InitialContextTraceStatus, int ForceLLTS, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (runtime_directory == NULL)) return -1; daemon->user_list = NULL; daemon->num_user_lists = 0; daemon->default_log_level = (int8_t) InitialContextLogLevel; daemon->default_trace_status = (int8_t) InitialContextTraceStatus; daemon->force_ll_ts = (int8_t) ForceLLTS; daemon->overflow_counter = 0; daemon->runtime_context_cfg_loaded = 0; daemon->connectionState = 0; /* no logger connected */ daemon->state = DLT_DAEMON_STATE_INIT; /* initial logging state */ daemon->sendserialheader = 0; daemon->timingpackets = 0; dlt_set_id(daemon->ecuid, ""); /* initialize ring buffer for client connection */ dlt_vlog(LOG_INFO, "Ringbuffer configuration: %lu/%lu/%lu\n", RingbufferMinSize, RingbufferMaxSize, RingbufferStepSize); if (dlt_buffer_init_dynamic(&(daemon->client_ringbuffer), (uint32_t) RingbufferMinSize, (uint32_t) RingbufferMaxSize, (uint32_t) RingbufferStepSize) < DLT_RETURN_OK) return -1; daemon->storage_handle = NULL; #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE daemon->received_message_since_last_watchdog_interval = 0; #endif return 0; } int dlt_daemon_free(DltDaemon *daemon, int verbose) { int i = 0; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon->user_list == NULL)) return -1; /* free all registered user information */ for (i = 0; i < daemon->num_user_lists; i++) { user_list = &daemon->user_list[i]; if (user_list != NULL) { /* ignore return values */ dlt_daemon_contexts_clear(daemon, user_list->ecu, verbose); dlt_daemon_applications_clear(daemon, user_list->ecu, verbose); } } free(daemon->user_list); #ifdef DLT_LOG_LEVEL_APP_CONFIG if (daemon->app_id_log_level_settings != NULL) { free(daemon->app_id_log_level_settings); } #endif if (app_recv_buffer) free(app_recv_buffer); /* free ringbuffer */ dlt_buffer_free_dynamic(&(daemon->client_ringbuffer)); return 0; } int dlt_daemon_init_user_information(DltDaemon *daemon, DltGateway *gateway, int gateway_mode, int verbose) { int nodes = 1; int i = 1; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || ((gateway_mode == 1) && (gateway == NULL))) return DLT_RETURN_ERROR; if (gateway_mode == 0) { /* initialize application list */ daemon->user_list = calloc((size_t) nodes, sizeof(DltDaemonRegisteredUsers)); if (daemon->user_list == NULL) { dlt_log(LOG_ERR, "Allocating memory for user information"); return DLT_RETURN_ERROR; } dlt_set_id(daemon->user_list[0].ecu, daemon->ecuid); daemon->num_user_lists = 1; } else { /* gateway is active */ nodes += gateway->num_connections; /* initialize application list */ daemon->user_list = calloc((size_t) nodes, sizeof(DltDaemonRegisteredUsers)); if (daemon->user_list == NULL) { dlt_log(LOG_ERR, "Allocating memory for user information"); return DLT_RETURN_ERROR; } dlt_set_id(daemon->user_list[0].ecu, daemon->ecuid); daemon->num_user_lists = nodes; for (i = 1; i < nodes; i++) dlt_set_id(daemon->user_list[i].ecu, gateway->connections[i - 1].ecuid); } return DLT_RETURN_OK; } int dlt_daemon_applications_invalidate_fd(DltDaemon *daemon, char *ecu, int fd, int verbose) { int i; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (ecu == NULL)) return DLT_RETURN_ERROR; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list != NULL) { for (i = 0; i < user_list->num_applications; i++) if (user_list->applications[i].user_handle == fd) user_list->applications[i].user_handle = DLT_FD_INIT; return DLT_RETURN_OK; } return DLT_RETURN_ERROR; } int dlt_daemon_applications_clear(DltDaemon *daemon, char *ecu, int verbose) { int i; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon->user_list == NULL) || (ecu == NULL)) return DLT_RETURN_WRONG_PARAMETER; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list == NULL) return DLT_RETURN_ERROR; for (i = 0; i < user_list->num_applications; i++) if (user_list->applications[i].application_description != NULL) { #ifdef DLT_LOG_LEVEL_APP_CONFIG if (user_list->applications[i].context_log_level_settings) free(user_list->applications[i].context_log_level_settings); #endif free(user_list->applications[i].application_description); user_list->applications[i].application_description = NULL; } if (user_list->applications != NULL) free(user_list->applications); user_list->applications = NULL; user_list->num_applications = 0; return 0; } static void dlt_daemon_application_reset_user_handle(DltDaemon *daemon, DltDaemonApplication *application, int verbose) { DltDaemonRegisteredUsers *user_list; DltDaemonContext *context; int i; if (application->user_handle == DLT_FD_INIT) return; user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list != NULL) { for (i = 0; i < user_list->num_contexts; i++) { context = &user_list->contexts[i]; if (context->user_handle == application->user_handle) context->user_handle = DLT_FD_INIT; } } if (application->owns_user_handle) close(application->user_handle); application->user_handle = DLT_FD_INIT; application->owns_user_handle = false; } DltDaemonApplication *dlt_daemon_application_add(DltDaemon *daemon, char *apid, pid_t pid, char *description, int fd, char *ecu, int verbose) { DltDaemonApplication *application; DltDaemonApplication *old; int new_application; int dlt_user_handle; bool owns_user_handle; DltDaemonRegisteredUsers *user_list = NULL; #ifdef DLT_DAEMON_USE_FIFO_IPC (void)fd; /* To avoid compiler warning : unused variable */ char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE]; #endif if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') || (ecu == NULL)) return (DltDaemonApplication *)NULL; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list == NULL) return (DltDaemonApplication *)NULL; if (user_list->applications == NULL) { user_list->applications = (DltDaemonApplication *) malloc(sizeof(DltDaemonApplication) * DLT_DAEMON_APPL_ALLOC_SIZE); if (user_list->applications == NULL) return (DltDaemonApplication *)NULL; } new_application = 0; /* Check if application [apid] is already available */ application = dlt_daemon_application_find(daemon, apid, ecu, verbose); if (application == NULL) { user_list->num_applications += 1; if (user_list->num_applications != 0) { if ((user_list->num_applications % DLT_DAEMON_APPL_ALLOC_SIZE) == 0) { /* allocate memory in steps of DLT_DAEMON_APPL_ALLOC_SIZE, e.g. 100 */ old = user_list->applications; user_list->applications = (DltDaemonApplication *) malloc(sizeof(DltDaemonApplication) * ((user_list->num_applications / DLT_DAEMON_APPL_ALLOC_SIZE) + 1) * DLT_DAEMON_APPL_ALLOC_SIZE); if (user_list->applications == NULL) { user_list->applications = old; user_list->num_applications -= 1; return (DltDaemonApplication *)NULL; } memcpy(user_list->applications, old, sizeof(DltDaemonApplication) * user_list->num_applications); free(old); } } application = &(user_list->applications[user_list->num_applications - 1]); dlt_set_id(application->apid, apid); application->pid = 0; application->application_description = NULL; application->num_contexts = 0; application->user_handle = DLT_FD_INIT; application->owns_user_handle = false; new_application = 1; } else if ((pid != application->pid) && (application->pid != 0)) { dlt_vlog(LOG_WARNING, "Duplicate registration of ApplicationID: '%.4s'; registering from PID %d, existing from PID %d\n", apid, pid, application->pid); } /* Store application description and pid of application */ if (application->application_description) { free(application->application_description); application->application_description = NULL; } if (description != NULL) { application->application_description = malloc(strlen(description) + 1); if (application->application_description) { memcpy(application->application_description, description, strlen(description) + 1); } else { dlt_log(LOG_ERR, "Cannot allocate memory to store application description\n"); free(application); return (DltDaemonApplication *)NULL; } } if (application->pid != pid) { dlt_daemon_application_reset_user_handle(daemon, application, verbose); application->pid = 0; } /* open user pipe only if it is not yet opened */ if ((application->user_handle == DLT_FD_INIT) && (pid != 0)) { dlt_user_handle = DLT_FD_INIT; owns_user_handle = false; #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE if (fd >= DLT_FD_MINIMUM) { dlt_user_handle = fd; owns_user_handle = false; } #endif #ifdef DLT_DAEMON_USE_FIFO_IPC if (dlt_user_handle < DLT_FD_MINIMUM) { snprintf(filename, DLT_DAEMON_COMMON_TEXTBUFSIZE, "%s/dltpipes/dlt%d", dltFifoBaseDir, pid); dlt_user_handle = open(filename, O_WRONLY | O_NONBLOCK); if (dlt_user_handle < 0) { int prio = (errno == ENOENT) ? LOG_INFO : LOG_WARNING; dlt_vlog(prio, "open() failed to %s, errno=%d (%s)!\n", filename, errno, strerror(errno)); } else { owns_user_handle = true; } } #endif /* check if file descriptor was already used, and make it invalid if it * is reused. This prevents sending messages to wrong file descriptor */ dlt_daemon_applications_invalidate_fd(daemon, ecu, dlt_user_handle, verbose); dlt_daemon_contexts_invalidate_fd(daemon, ecu, dlt_user_handle, verbose); application->user_handle = dlt_user_handle; application->owns_user_handle = owns_user_handle; application->pid = pid; } /* Sort */ if (new_application) { qsort(user_list->applications, (size_t) user_list->num_applications, sizeof(DltDaemonApplication), dlt_daemon_cmp_apid); /* Find new position of application with apid*/ application = dlt_daemon_application_find(daemon, apid, ecu, verbose); } #ifdef DLT_LOG_LEVEL_APP_CONFIG application->num_context_log_level_settings = 0; application->context_log_level_settings = NULL; #endif return application; } int dlt_daemon_application_del(DltDaemon *daemon, DltDaemonApplication *application, char *ecu, int verbose) { int pos; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (application == NULL) || (ecu == NULL)) return -1; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list == NULL) return -1; if (user_list->num_applications > 0) { dlt_daemon_application_reset_user_handle(daemon, application, verbose); /* Free description of application to be deleted */ if (application->application_description) { free(application->application_description); application->application_description = NULL; } pos = (int) (application - (user_list->applications)); /* move all applications above pos to pos */ memmove(&(user_list->applications[pos]), &(user_list->applications[pos + 1]), sizeof(DltDaemonApplication) * ((user_list->num_applications - 1) - pos)); /* Clear last application */ memset(&(user_list->applications[user_list->num_applications - 1]), 0, sizeof(DltDaemonApplication)); user_list->num_applications--; } return 0; } DltDaemonApplication *dlt_daemon_application_find(DltDaemon *daemon, char *apid, char *ecu, int verbose) { DltDaemonApplication application; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon->user_list == NULL) || (apid == NULL) || (apid[0] == '\0') || (ecu == NULL)) return (DltDaemonApplication *)NULL; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if ((user_list == NULL) || (user_list->num_applications == 0)) return (DltDaemonApplication *)NULL; /* Check, if apid is smaller than smallest apid or greater than greatest apid */ if ((memcmp(apid, user_list->applications[0].apid, DLT_ID_SIZE) < 0) || (memcmp(apid, user_list->applications[user_list->num_applications - 1].apid, DLT_ID_SIZE) > 0)) return (DltDaemonApplication *)NULL; dlt_set_id(application.apid, apid); return (DltDaemonApplication *)bsearch(&application, user_list->applications, (size_t) user_list->num_applications, sizeof(DltDaemonApplication), dlt_daemon_cmp_apid); } int dlt_daemon_applications_load(DltDaemon *daemon, const char *filename, int verbose) { FILE *fd; ID4 apid; char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE]; char *ret; char *pb; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0')) return -1; fd = fopen(filename, "r"); if (fd == NULL) { dlt_vlog(LOG_WARNING, "%s: cannot open file %s: %s\n", __func__, filename, strerror(errno)); return -1; } while (!feof(fd)) { /* Clear buf */ memset(buf, 0, sizeof(buf)); /* Get line */ ret = fgets(buf, sizeof(buf), fd); if (NULL == ret) { /* fgets always null pointer if the last byte of the file is a new line * We need to check here if there was an error or was it feof.*/ if (ferror(fd)) { dlt_vlog(LOG_WARNING, "%s: fgets(buf,sizeof(buf),fd) returned NULL. %s\n", __func__, strerror(errno)); fclose(fd); return -1; } else if (feof(fd)) { fclose(fd); return 0; } else { dlt_vlog(LOG_WARNING, "%s: fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n", __func__); fclose(fd); return -1; } } if (strcmp(buf, "") != 0) { /* Split line */ pb = strtok(buf, ":"); if (pb != NULL) { dlt_set_id(apid, pb); pb = strtok(NULL, ":"); if (pb != NULL) { /* pb contains now the description */ /* pid is unknown at loading time */ if (dlt_daemon_application_add(daemon, apid, 0, pb, -1, daemon->ecuid, verbose) == 0) { dlt_vlog(LOG_WARNING, "%s: dlt_daemon_application_add failed for %4s\n", __func__, apid); fclose(fd); return -1; } } } } } fclose(fd); return 0; } int dlt_daemon_applications_save(DltDaemon *daemon, const char *filename, int verbose) { FILE *fd; int i; char apid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */ DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0')) return -1; memset(apid, 0, sizeof(apid)); user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return -1; if ((user_list->applications != NULL) && (user_list->num_applications > 0)) { fd = fopen(filename, "w"); if (fd != NULL) { for (i = 0; i < user_list->num_applications; i++) { dlt_set_id(apid, user_list->applications[i].apid); if ((user_list->applications[i].application_description) && (user_list->applications[i].application_description[0] != '\0')) fprintf(fd, "%s:%s:\n", apid, user_list->applications[i].application_description); else fprintf(fd, "%s::\n", apid); } fclose(fd); } else { dlt_vlog(LOG_ERR, "%s: open %s failed! No application information stored.\n", __func__, filename); } } return 0; } DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon, char *apid, char *ctid, int8_t log_level, int8_t trace_status, int log_level_pos, int user_handle, char *description, char *ecu, int verbose) { DltDaemonApplication *application; DltDaemonContext *context; DltDaemonContext *old; int new_context = 0; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') || (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL)) return (DltDaemonContext *)NULL; if ((log_level < DLT_LOG_DEFAULT) || (log_level > DLT_LOG_VERBOSE)) return (DltDaemonContext *)NULL; if ((trace_status < DLT_TRACE_STATUS_DEFAULT) || (trace_status > DLT_TRACE_STATUS_ON)) return (DltDaemonContext *)NULL; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list == NULL) return (DltDaemonContext *)NULL; if (user_list->contexts == NULL) { user_list->contexts = (DltDaemonContext *)malloc(sizeof(DltDaemonContext) * DLT_DAEMON_CONTEXT_ALLOC_SIZE); if (user_list->contexts == NULL) return (DltDaemonContext *)NULL; } /* Check if application [apid] is available */ application = dlt_daemon_application_find(daemon, apid, ecu, verbose); if (application == NULL) return (DltDaemonContext *)NULL; /* Check if context [apid, ctid] is already available */ context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose); if (context == NULL) { user_list->num_contexts += 1; if (user_list->num_contexts != 0) { if ((user_list->num_contexts % DLT_DAEMON_CONTEXT_ALLOC_SIZE) == 0) { /* allocate memory for context in steps of DLT_DAEMON_CONTEXT_ALLOC_SIZE, e.g 100 */ old = user_list->contexts; user_list->contexts = (DltDaemonContext *)malloc((size_t) sizeof(DltDaemonContext) * ((user_list->num_contexts / DLT_DAEMON_CONTEXT_ALLOC_SIZE) + 1) * DLT_DAEMON_CONTEXT_ALLOC_SIZE); if (user_list->contexts == NULL) { user_list->contexts = old; user_list->num_contexts -= 1; return (DltDaemonContext *)NULL; } memcpy(user_list->contexts, old, (size_t) sizeof(DltDaemonContext) * user_list->num_contexts); free(old); } } context = &(user_list->contexts[user_list->num_contexts - 1]); dlt_set_id(context->apid, apid); dlt_set_id(context->ctid, ctid); context->context_description = NULL; application->num_contexts++; new_context = 1; } /* Set context description */ if (context->context_description) { free(context->context_description); context->context_description = NULL; } if (description != NULL) { context->context_description = malloc(strlen(description) + 1); if (context->context_description) { memcpy(context->context_description, description, strlen(description) + 1); } } #ifdef DLT_LOG_LEVEL_APP_CONFIG /* configure initial log level */ DltDaemonContextLogSettings *settings = NULL; settings = dlt_daemon_find_configured_app_id_ctx_id_settings( daemon, context->apid, ctid); if (settings != NULL) { /* set log level */ log_level = settings->log_level; DltDaemonContextLogSettings *ct_settings = NULL; ct_settings = dlt_daemon_find_app_log_level_config(application, ctid); /* ct_settings != null: context and app id combination already exists */ if (ct_settings == NULL) { /* copy the configuration into the DltDaemonApplication for faster access later */ DltDaemonContextLogSettings *tmp = realloc(application->context_log_level_settings, (++application->num_context_log_level_settings) * sizeof(DltDaemonContextLogSettings)); application->context_log_level_settings = tmp; ct_settings = &application->context_log_level_settings[application->num_context_log_level_settings - 1]; memcpy(ct_settings, settings, sizeof(DltDaemonContextLogSettings)); memcpy(ct_settings->ctid, ctid, DLT_ID_SIZE); } } #endif if ((strncmp(daemon->ecuid, ecu, DLT_ID_SIZE) == 0) && (daemon->force_ll_ts)) { #ifdef DLT_LOG_LEVEL_APP_CONFIG if (log_level > daemon->default_log_level && settings == NULL) #else if (log_level > daemon->default_log_level) #endif log_level = daemon->default_log_level; if (trace_status > daemon->default_trace_status) trace_status = daemon->default_trace_status; dlt_vlog(LOG_NOTICE, "Adapting ll_ts for context: %.4s:%.4s with %i %i\n", apid, ctid, log_level, trace_status); } /* Store log level and trace status, * if this is a new context, or * if this is an old context and the runtime cfg was not loaded */ if ((new_context == 1) || ((new_context == 0) && (daemon->runtime_context_cfg_loaded == 0))) { context->log_level = log_level; context->trace_status = trace_status; } context->log_level_pos = log_level_pos; context->user_handle = user_handle; /* In case a context is loaded from runtime config file, * the user_handle is 0 and we mark that context as predefined. */ if (context->user_handle == 0) context->predefined = true; else context->predefined = false; /* Sort */ if (new_context) { qsort(user_list->contexts, (size_t) user_list->num_contexts, sizeof(DltDaemonContext), dlt_daemon_cmp_apid_ctid); /* Find new position of context with apid, ctid */ context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose); } return context; } #ifdef DLT_LOG_LEVEL_APP_CONFIG static void dlt_daemon_free_context_log_settings( DltDaemonApplication *application, DltDaemonContext *context) { DltDaemonContextLogSettings *ct_settings; int i; int skipped = 0; ct_settings = dlt_daemon_find_app_log_level_config(application, context->ctid); if (ct_settings == NULL) { return; } /* move all data forward */ for (i = 0; i < application->num_context_log_level_settings; ++i) { /* skip given context to delete it */ if (i + skipped < application->num_context_log_level_settings && strncmp(application->context_log_level_settings[i+skipped].ctid, context->ctid, DLT_ID_SIZE) == 0) { ++skipped; continue; } memcpy(&application->context_log_level_settings[i-skipped], &application->context_log_level_settings[i], sizeof(DltDaemonContextLogSettings)); } application->num_context_log_level_settings -= skipped; /* if size is equal to zero, and ptr is not NULL, then realloc is equivalent to free(ptr) */ application->context_log_level_settings = realloc(application->context_log_level_settings, sizeof(DltDaemonContextLogSettings) * (application->num_context_log_level_settings)); } #endif int dlt_daemon_context_del(DltDaemon *daemon, DltDaemonContext *context, char *ecu, int verbose) { int pos; DltDaemonApplication *application; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (context == NULL) || (ecu == NULL)) return -1; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list == NULL) return -1; if (user_list->num_contexts > 0) { application = dlt_daemon_application_find(daemon, context->apid, ecu, verbose); #ifdef DLT_LOG_LEVEL_APP_CONFIG dlt_daemon_free_context_log_settings(application, context); #endif /* Free description of context to be deleted */ if (context->context_description) { free(context->context_description); context->context_description = NULL; } pos = (int) (context - (user_list->contexts)); /* move all contexts above pos to pos */ memmove(&(user_list->contexts[pos]), &(user_list->contexts[pos + 1]), sizeof(DltDaemonContext) * ((user_list->num_contexts - 1) - pos)); /* Clear last context */ memset(&(user_list->contexts[user_list->num_contexts - 1]), 0, sizeof(DltDaemonContext)); user_list->num_contexts--; /* Check if application [apid] is available */ if (application != NULL) application->num_contexts--; } return 0; } DltDaemonContext *dlt_daemon_context_find(DltDaemon *daemon, char *apid, char *ctid, char *ecu, int verbose) { DltDaemonContext context; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') || (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL)) return (DltDaemonContext *)NULL; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if ((user_list == NULL) || (user_list->num_contexts == 0)) return (DltDaemonContext *)NULL; /* Check, if apid is smaller than smallest apid or greater than greatest apid */ if ((memcmp(apid, user_list->contexts[0].apid, DLT_ID_SIZE) < 0) || (memcmp(apid, user_list->contexts[user_list->num_contexts - 1].apid, DLT_ID_SIZE) > 0)) return (DltDaemonContext *)NULL; dlt_set_id(context.apid, apid); dlt_set_id(context.ctid, ctid); return (DltDaemonContext *)bsearch(&context, user_list->contexts, (size_t) user_list->num_contexts, sizeof(DltDaemonContext), dlt_daemon_cmp_apid_ctid); } int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon, char *ecu, int fd, int verbose) { int i; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (ecu == NULL)) return -1; user_list = dlt_daemon_find_users_list(daemon, ecu, verbose); if (user_list != NULL) { for (i = 0; i < user_list->num_contexts; i++) if (user_list->contexts[i].user_handle == fd) user_list->contexts[i].user_handle = DLT_FD_INIT; return 0; } return -1; } int dlt_daemon_contexts_clear(DltDaemon *daemon, char *ecu, int verbose) { int i; DltDaemonRegisteredUsers *users = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (ecu == NULL)) return DLT_RETURN_WRONG_PARAMETER; users = dlt_daemon_find_users_list(daemon, ecu, verbose); if (users == NULL) return DLT_RETURN_ERROR; for (i = 0; i < users->num_contexts; i++) if (users->contexts[i].context_description != NULL) { free(users->contexts[i].context_description); users->contexts[i].context_description = NULL; } if (users->contexts) { free(users->contexts); users->contexts = NULL; } for (i = 0; i < users->num_applications; i++) users->applications[i].num_contexts = 0; users->num_contexts = 0; return 0; } int dlt_daemon_contexts_load(DltDaemon *daemon, const char *filename, int verbose) { FILE *fd; ID4 apid, ctid; char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE]; char *ret; char *pb; int ll, ts; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0')) return -1; fd = fopen(filename, "r"); if (fd == NULL) { dlt_vlog(LOG_WARNING, "DLT runtime-context load, cannot open file %s: %s\n", filename, strerror(errno)); return -1; } while (!feof(fd)) { /* Clear buf */ memset(buf, 0, sizeof(buf)); /* Get line */ ret = fgets(buf, sizeof(buf), fd); if (NULL == ret) { /* fgets always returns null pointer if the last byte of the file is a new line. * We need to check here if there was an error or was it feof.*/ if (ferror(fd)) { dlt_vlog(LOG_WARNING, "%s fgets(buf,sizeof(buf),fd) returned NULL. %s\n", __func__, strerror(errno)); fclose(fd); return -1; } else if (feof(fd)) { fclose(fd); return 0; } else { dlt_vlog(LOG_WARNING, "%s fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n", __func__); fclose(fd); return -1; } } if (strcmp(buf, "") != 0) { /* Split line */ pb = strtok(buf, ":"); if (pb != NULL) { dlt_set_id(apid, pb); pb = strtok(NULL, ":"); if (pb != NULL) { dlt_set_id(ctid, pb); pb = strtok(NULL, ":"); if (pb != NULL) { sscanf(pb, "%d", &ll); pb = strtok(NULL, ":"); if (pb != NULL) { sscanf(pb, "%d", &ts); pb = strtok(NULL, ":"); if (pb != NULL) { /* pb contains now the description */ /* log_level_pos, and user_handle are unknown at loading time */ if (dlt_daemon_context_add(daemon, apid, ctid, (int8_t)ll, (int8_t)ts, 0, 0, pb, daemon->ecuid, verbose) == NULL) { dlt_vlog(LOG_WARNING, "%s dlt_daemon_context_add failed\n", __func__); fclose(fd); return -1; } } } } } } } } fclose(fd); return 0; } int dlt_daemon_contexts_save(DltDaemon *daemon, const char *filename, int verbose) { FILE *fd; int i; char apid[DLT_ID_SIZE + 1], ctid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */ DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0')) return -1; user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return -1; memset(apid, 0, sizeof(apid)); memset(ctid, 0, sizeof(ctid)); if ((user_list->contexts) && (user_list->num_contexts > 0)) { fd = fopen(filename, "w"); if (fd != NULL) { for (i = 0; i < user_list->num_contexts; i++) { dlt_set_id(apid, user_list->contexts[i].apid); dlt_set_id(ctid, user_list->contexts[i].ctid); if ((user_list->contexts[i].context_description) && (user_list->contexts[i].context_description[0] != '\0')) fprintf(fd, "%s:%s:%d:%d:%s:\n", apid, ctid, (int)(user_list->contexts[i].log_level), (int)(user_list->contexts[i].trace_status), user_list->contexts[i].context_description); else fprintf(fd, "%s:%s:%d:%d::\n", apid, ctid, (int)(user_list->contexts[i].log_level), (int)(user_list->contexts[i].trace_status)); } fclose(fd); } else { dlt_vlog(LOG_ERR, "%s: Cannot open %s. No context information stored\n", __func__, filename); } } return 0; } int dlt_daemon_configuration_save(DltDaemon *daemon, const char *filename, int verbose) { FILE *fd; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0')) return -1; fd = fopen(filename, "w"); if (fd != NULL) { fprintf(fd, "# 0 = off, 1 = external, 2 = internal, 3 = both\n"); fprintf(fd, "LoggingMode = %d\n", daemon->mode); fclose(fd); } return 0; } int dlt_daemon_configuration_load(DltDaemon *daemon, const char *filename, int verbose) { if ((daemon == NULL) || (filename == NULL)) return -1; FILE *pFile; char line[1024]; char token[1024]; char value[1024]; char *pch; PRINT_FUNCTION_VERBOSE(verbose); pFile = fopen (filename, "r"); if (pFile != NULL) { while (1) { /* fetch line from configuration file */ if (fgets (line, 1024, pFile) != NULL) { pch = strtok (line, " =\r\n"); token[0] = 0; value[0] = 0; while (pch != NULL) { if (strcmp(pch, "#") == 0) break; if (token[0] == 0) { strncpy(token, pch, sizeof(token) - 1); token[sizeof(token) - 1] = 0; } else { strncpy(value, pch, sizeof(value) - 1); value[sizeof(value) - 1] = 0; break; } pch = strtok (NULL, " =\r\n"); } if (token[0] && value[0]) { /* parse arguments here */ if (strcmp(token, "LoggingMode") == 0) { daemon->mode = atoi(value); dlt_vlog(LOG_INFO, "Runtime Option: %s=%d\n", token, daemon->mode); } else { dlt_vlog(LOG_WARNING, "Unknown option: %s=%s\n", token, value); } } } else { break; } } fclose (pFile); } else { dlt_vlog(LOG_INFO, "Cannot open configuration file: %s\n", filename); } return 0; } int dlt_daemon_user_send_log_level(DltDaemon *daemon, DltDaemonContext *context, int verbose) { DltUserHeader userheader; DltUserControlMsgLogLevel usercontext; DltReturnValue ret; DltDaemonApplication *app; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (context == NULL)) { dlt_vlog(LOG_ERR, "NULL parameter in %s", __func__); return -1; } if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_LEVEL) < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "Failed to set userheader in %s", __func__); return -1; } if ((context->storage_log_level != DLT_LOG_DEFAULT) && (daemon->maintain_logstorage_loglevel != DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_OFF)) usercontext.log_level = (uint8_t) (context->log_level > context->storage_log_level ? context->log_level : context->storage_log_level); else /* Storage log level is not updated (is DEFAULT) then no device is yet connected so ignore */ usercontext.log_level = (uint8_t) ((context->log_level == DLT_LOG_DEFAULT) ? daemon->default_log_level : context->log_level); usercontext.trace_status = (uint8_t) ((context->trace_status == DLT_TRACE_STATUS_DEFAULT) ? daemon->default_trace_status : context->trace_status); usercontext.log_level_pos = context->log_level_pos; dlt_vlog(LOG_NOTICE, "Send log-level to context: %.4s:%.4s [%i -> %i] [%i -> %i]\n", context->apid, context->ctid, context->log_level, usercontext.log_level, context->trace_status, usercontext.trace_status); /* log to FIFO */ errno = 0; ret = dlt_user_log_out2_with_timeout(context->user_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgLogLevel)); if (ret < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "Failed to send data to application in %s: %s", __func__, errno != 0 ? strerror(errno) : "Unknown error"); if (errno == EPIPE) { app = dlt_daemon_application_find(daemon, context->apid, daemon->ecuid, verbose); if (app != NULL) dlt_daemon_application_reset_user_handle(daemon, app, verbose); } } return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR; } int dlt_daemon_user_send_log_state(DltDaemon *daemon, DltDaemonApplication *app, int verbose) { DltUserHeader userheader; DltUserControlMsgLogState logstate; DltReturnValue ret; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (app == NULL)) return -1; if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_STATE) < DLT_RETURN_OK) return -1; logstate.log_state = daemon->connectionState; /* log to FIFO */ ret = dlt_user_log_out2_with_timeout(app->user_handle, &(userheader), sizeof(DltUserHeader), &(logstate), sizeof(DltUserControlMsgLogState)); if (ret < DLT_RETURN_OK) { if (errno == EPIPE) dlt_daemon_application_reset_user_handle(daemon, app, verbose); } return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR; } void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon, const char *filename, const char *filename1, int InitialContextLogLevel, int InitialContextTraceStatus, int InitialEnforceLlTsStatus, int verbose) { FILE *fd; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (filename == NULL) || (filename1 == NULL)) { dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n"); return; } if ((filename[0] == '\0') || (filename1[0] == '\0')) { dlt_log(LOG_WARNING, "Wrong parameter: Empty string\n"); return; } /* Check for runtime cfg file and delete it, if available */ fd = fopen(filename, "r"); if (fd != NULL) { /* Close and delete file */ fclose(fd); unlink(filename); } fd = fopen(filename1, "r"); if (fd != NULL) { /* Close and delete file */ fclose(fd); unlink(filename1); } daemon->default_log_level = (int8_t) InitialContextLogLevel; daemon->default_trace_status = (int8_t) InitialContextTraceStatus; daemon->force_ll_ts = (int8_t) InitialEnforceLlTsStatus; /* Reset all other things (log level, trace status, etc. * to default values */ /* Inform user libraries about changed default log level/trace status */ dlt_daemon_user_send_default_update(daemon, verbose); } void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose) { int32_t count; DltDaemonContext *context; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == NULL) { dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n"); return; } user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; for (count = 0; count < user_list->num_contexts; count++) { context = &(user_list->contexts[count]); if (context != NULL) { if ((context->log_level == DLT_LOG_DEFAULT) || (context->trace_status == DLT_TRACE_STATUS_DEFAULT)) { if (context->user_handle >= DLT_FD_MINIMUM) if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) dlt_vlog(LOG_WARNING, "Cannot update default of %.4s:%.4s\n", context->apid, context->ctid); } } } } void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, int enforce_context_ll_and_ts, int8_t context_log_level, int8_t log_level, int verbose) { int32_t count = 0; DltDaemonContext *context = NULL; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == NULL) return; user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; for (count = 0; count < user_list->num_contexts; count++) { context = &(user_list->contexts[count]); if (context) { if (context->user_handle >= DLT_FD_MINIMUM) { context->log_level = log_level; if (enforce_context_ll_and_ts) { #ifdef DLT_LOG_LEVEL_APP_CONFIG DltDaemonContextLogSettings *settings = dlt_daemon_find_configured_app_id_ctx_id_settings( daemon, context->apid, context->ctid); if (settings != NULL) { if (log_level > settings->log_level) { context->log_level = settings->log_level; } } else #endif if (log_level > context_log_level) { context->log_level = (int8_t)context_log_level; } } if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) dlt_vlog(LOG_WARNING, "Cannot send log level %.4s:%.4s -> %i\n", context->apid, context->ctid, context->log_level); } } } } void dlt_daemon_user_send_all_trace_status_update(DltDaemon *daemon, int8_t trace_status, int verbose) { int32_t count = 0; DltDaemonContext *context = NULL; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == NULL) return; user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; dlt_vlog(LOG_NOTICE, "All trace status is updated -> %i\n", trace_status); for (count = 0; count < user_list->num_contexts; count++) { context = &(user_list->contexts[count]); if (context) { if (context->user_handle >= DLT_FD_MINIMUM) { context->trace_status = trace_status; if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) dlt_vlog(LOG_WARNING, "Cannot send trace status %.4s:%.4s -> %i\n", context->apid, context->ctid, context->trace_status); } } } } void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose) { int32_t count; DltDaemonApplication *app; DltDaemonRegisteredUsers *user_list = NULL; PRINT_FUNCTION_VERBOSE(verbose); if (daemon == NULL) { dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n"); return; } user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); if (user_list == NULL) return; for (count = 0; count < user_list->num_applications; count++) { app = &(user_list->applications[count]); if (app != NULL) { if (app->user_handle >= DLT_FD_MINIMUM) if (dlt_daemon_user_send_log_state(daemon, app, verbose) == -1) dlt_vlog(LOG_WARNING, "Cannot send log state to Apid: %.4s, PID: %d\n", app->apid, app->pid); } } } void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState) { switch (newState) { case DLT_DAEMON_STATE_INIT: dlt_log(LOG_INFO, "Switched to init state.\n"); daemon->state = DLT_DAEMON_STATE_INIT; break; case DLT_DAEMON_STATE_BUFFER: dlt_log(LOG_INFO, "Switched to buffer state for socket connections.\n"); daemon->state = DLT_DAEMON_STATE_BUFFER; break; case DLT_DAEMON_STATE_BUFFER_FULL: dlt_log(LOG_INFO, "Switched to buffer full state.\n"); daemon->state = DLT_DAEMON_STATE_BUFFER_FULL; break; case DLT_DAEMON_STATE_SEND_BUFFER: dlt_log(LOG_INFO, "Switched to send buffer state for socket connections.\n"); daemon->state = DLT_DAEMON_STATE_SEND_BUFFER; break; case DLT_DAEMON_STATE_SEND_DIRECT: dlt_log(LOG_INFO, "Switched to send direct state.\n"); daemon->state = DLT_DAEMON_STATE_SEND_DIRECT; break; } } dlt-daemon-2.18.10/src/daemon/dlt_daemon_common.h000066400000000000000000000641221446635226000216050ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_common.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_common.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 15.02.2010 initial */ #ifndef DLT_DAEMON_COMMON_H # define DLT_DAEMON_COMMON_H /** * \defgroup daemonapi DLT Daemon API * \addtogroup daemonapi \{ */ # include # include # include # include "dlt_common.h" # include "dlt_user.h" # include "dlt_offline_logstorage.h" # include "dlt_gateway_types.h" # ifdef __cplusplus extern "C" { # endif # define DLT_DAEMON_RINGBUFFER_MIN_SIZE 500000/**< Ring buffer size for storing log messages while no client is connected */ # define DLT_DAEMON_RINGBUFFER_MAX_SIZE 10000000/**< Ring buffer size for storing log messages while no client is connected */ # define DLT_DAEMON_RINGBUFFER_STEP_SIZE 500000/**< Ring buffer size for storing log messages while no client is connected */ #define DLT_DAEMON_SEND_TO_ALL -3 /**< Constant value to identify the command "send to all" */ #define DLT_DAEMON_SEND_FORCE -4 /**< Constant value to identify the command "send force to all" */ /* UDPMulticart Default IP and Port */ # ifdef UDP_CONNECTION_SUPPORT # define MULTICASTIPADDRESS "225.0.0.37" # define MULTICASTIPPORT 3491 # define MULTICASTIP_MAX_SIZE 256 # define MULTICAST_CONNECTION_DISABLED 0 # define MULTICAST_CONNECTION_ENABLED 1 # endif /** * Definitions of DLT daemon logging states */ typedef enum { DLT_DAEMON_STATE_INIT = 0, /**< Initial state */ DLT_DAEMON_STATE_BUFFER = 1, /**< logging is buffered until external logger is connected or internal logging is activated */ DLT_DAEMON_STATE_BUFFER_FULL = 2, /**< then internal buffer is full, wait for connect from client */ DLT_DAEMON_STATE_SEND_BUFFER = 3, /**< external logger is connected, but buffer is still not empty or external logger queue is full */ DLT_DAEMON_STATE_SEND_DIRECT = 4 /**< External logger is connected or internal logging is active, and buffer is empty */ } DltDaemonState; #ifdef DLT_LOG_LEVEL_APP_CONFIG /* * The parameter of level per app and context id settings */ typedef struct { char apid[DLT_ID_SIZE]; /**< Application id for which the settings are valid */ char ctid[DLT_ID_SIZE]; /**< Context id for which the settings are valid, empty if valid for all ap ids */ DltLogLevelType log_level; /**< Log level to use */ } DltDaemonContextLogSettings; #endif /** * The parameters of a daemon application. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ pid_t pid; /**< process id of user application */ int user_handle; /**< connection handle for connection to user application */ bool owns_user_handle; /**< user_handle should be closed when reset */ char *application_description; /**< context description */ int num_contexts; /**< number of contexts for this application */ #ifdef DLT_LOG_LEVEL_APP_CONFIG DltDaemonContextLogSettings *context_log_level_settings; int num_context_log_level_settings; #endif } DltDaemonApplication; /** * The parameters of a daemon context. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ int8_t log_level; /**< the current log level of the context */ int8_t trace_status; /**< the current trace status of the context */ int log_level_pos; /**< offset of context in context field on user application */ int user_handle; /**< connection handle for connection to user application */ char *context_description; /**< context description */ int8_t storage_log_level; /**< log level set for offline logstorage */ bool predefined; /**< set to true if this context is predefined by runtime configuration file */ } DltDaemonContext; /* * The parameter of registered users list */ typedef struct { DltDaemonApplication *applications; /**< Pointer to applications */ int num_applications; /**< Number of available application */ DltDaemonContext *contexts; /**< Pointer to contexts */ int num_contexts; /**< Total number of all contexts in all applications in this list */ char ecu[DLT_ID_SIZE]; /**< ECU ID of where contexts are registered */ } DltDaemonRegisteredUsers; /** * The parameters of a daemon. */ typedef struct { DltDaemonRegisteredUsers *user_list; /**< registered users per ECU */ int num_user_lists; /** < number of context lists */ int8_t default_log_level; /**< Default log level (of daemon) */ int8_t default_trace_status; /**< Default trace status (of daemon) */ int8_t force_ll_ts; /**< Enforce ll and ts to not exceed default_log_level, default_trace_status */ unsigned int overflow_counter; /**< counts the number of lost messages. */ int runtime_context_cfg_loaded; /**< Set to one, if runtime context configuration has been loaded, zero otherwise */ char ecuid[DLT_ID_SIZE]; /**< ECU ID of daemon */ int sendserialheader; /**< 1: send serial header; 0 don't send serial header */ int timingpackets; /**< 1: send continous timing packets; 0 don't send continous timing packets */ DltBuffer client_ringbuffer; /**< Ring-buffer for storing received logs while no client connection is available */ char runtime_application_cfg[PATH_MAX + 1]; /**< Path and filename of persistent application configuration. Set to path max, as it specifies a full path*/ char runtime_context_cfg[PATH_MAX + 1]; /**< Path and filename of persistent context configuration */ char runtime_configuration[PATH_MAX + 1]; /**< Path and filename of persistent configuration */ DltUserLogMode mode; /**< Mode used for tracing: off, external, internal, both */ char connectionState; /**< state for tracing: 0 = no client connected, 1 = client connected */ char *ECUVersionString; /**< Version string to send to client. Loaded from a file at startup. May be null. */ DltDaemonState state; /**< the current logging state of dlt daemon. */ DltLogStorage *storage_handle; int maintain_logstorage_loglevel; /* Permission to maintain the logstorage loglevel*/ #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE int received_message_since_last_watchdog_interval; #endif #ifdef DLT_LOG_LEVEL_APP_CONFIG DltDaemonContextLogSettings *app_id_log_level_settings; /**< Settings for app id specific log levels */ int num_app_id_log_level_settings; /** < count of log level settings */ #endif } DltDaemon; /** * Initialise the dlt daemon structure * This function must be called before using further dlt daemon structure * @param daemon pointer to dlt daemon structure * @param RingbufferMinSize ringbuffer size * @param RingbufferMaxSize ringbuffer size * @param RingbufferStepSize ringbuffer size * @param runtime_directory Directory of persistent configuration * @param InitialContextLogLevel loglevel to be sent to context when those register with loglevel default, read from dlt.conf * @param InitialContextTraceStatus tracestatus to be sent to context when those register with tracestatus default, read from dlt.conf * @param ForceLLTS force default log-level * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_init(DltDaemon *daemon, unsigned long RingbufferMinSize, unsigned long RingbufferMaxSize, unsigned long RingbufferStepSize, const char *runtime_directory, int InitialContextLogLevel, int InitialContextTraceStatus, int ForceLLTS, int verbose); /** * De-Initialise the dlt daemon structure * @param daemon pointer to dlt daemon structure * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_free(DltDaemon *daemon, int verbose); /** * Initialize data structures to store information about applications running on same * or passive node. * @param daemon pointer to dlt daemon structure * @param gateway pointer to dlt gateway structure * @param gateway_mode mode of dlt daemon, specified in dlt.conf * @param verbose if set to true verbose information is printed out * @return DLT_RETURN_OK on success, DLT_RETURN_ERROR otherwise */ int dlt_daemon_init_user_information(DltDaemon *daemon, DltGateway *gateway, int gateway_mode, int verbose); /** * Find information about application/contexts for a specific ECU * @param daemon pointer to dlt daemon structure * @param ecu pointer to node name * @param verbose if set to true verbose information is printed out * @return pointer to user list, NULL otherwise */ DltDaemonRegisteredUsers *dlt_daemon_find_users_list(DltDaemon *daemon, char *ecu, int verbose); #ifdef DLT_LOG_LEVEL_APP_CONFIG /** * Find configuration for app/ctx id specific log settings configuration * @param daemon pointer to dlt daemon struct * @param apid application id to use * @param ctid context id to use, can be NULL * @return pointer to log settings if found, otherwise NULL */ DltDaemonContextLogSettings *dlt_daemon_find_configured_app_id_ctx_id_settings( const DltDaemon *daemon, const char *apid, const char *ctid); /** * Find configured log levels in a given DltDaemonApplication for the passed context id. * @param app The application settings which contain the previously loaded ap id settings * @param ctid The context id to find. * @return Pointer to DltDaemonApplicationLogSettings containing the log level * for the requested application or NULL if none found. */ DltDaemonContextLogSettings *dlt_daemon_find_app_log_level_config( const DltDaemonApplication *app, const char *ctid); #endif /** * Init the user saved configurations to daemon. * Since the order of loading runtime config could be different, * this function won't be the place to do that. * This is just for preparation of real load later. * @param daemon pointer to dlt daemon structure * @param runtime_directory directory path * @param verbose if set to true verbose information is printed out * @return DLT_RETURN_OK on success, DLT_RETURN_ERROR otherwise */ int dlt_daemon_init_runtime_configuration(DltDaemon *daemon, const char *runtime_directory, int verbose); /** * Add (new) application to internal application management * @param daemon pointer to dlt daemon structure * @param apid pointer to application id * @param pid process id of user application * @param description description of application * @param fd file descriptor of application * @param ecu pointer to ecu id of node to add applications * @param verbose if set to true verbose information is printed out. * @return Pointer to added context, null pointer on error */ DltDaemonApplication *dlt_daemon_application_add(DltDaemon *daemon, char *apid, pid_t pid, char *description, int fd, char *ecu, int verbose); /** * Delete application from internal application management * @param daemon pointer to dlt daemon structure * @param application pointer to application to be deleted * @param ecu pointer to ecu id of node to delete applications * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_application_del(DltDaemon *daemon, DltDaemonApplication *application, char *ecu, int verbose); /** * Find application with specific application id * @param daemon pointer to dlt daemon structure * @param apid pointer to application id * @param ecu pointer to ecu id of node to clear applications * @param verbose if set to true verbose information is printed out. * @return Pointer to application, null pointer on error or not found */ DltDaemonApplication *dlt_daemon_application_find(DltDaemon *daemon, char *apid, char *ecu, int verbose); /** * Load applications from file to internal context management * @param daemon pointer to dlt daemon structure * @param filename name of file to be used for loading * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_applications_load(DltDaemon *daemon, const char *filename, int verbose); /** * Save applications from internal context management to file * @param daemon pointer to dlt daemon structure * @param filename name of file to be used for saving * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_applications_save(DltDaemon *daemon, const char *filename, int verbose); /** * Invalidate all applications fd, if fd is reused * @param daemon pointer to dlt daemon structure * @param ecu node these applications running on. * @param fd file descriptor * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_applications_invalidate_fd(DltDaemon *daemon, char *ecu, int fd, int verbose); /** * Clear all applications in internal application management of specific ecu * @param daemon pointer to dlt daemon structure * @param ecu pointer to ecu id of node to clear applications * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_applications_clear(DltDaemon *daemon, char *ecu, int verbose); /** * Add (new) context to internal context management * @param daemon pointer to dlt daemon structure * @param apid pointer to application id * @param ctid pointer to context id * @param log_level log level of context * @param trace_status trace status of context * @param log_level_pos offset of context in context field on user application * @param user_handle connection handle for connection to user application * @param description description of context * @param ecu pointer to ecu id of node to add application * @param verbose if set to true verbose information is printed out. * @return Pointer to added context, null pointer on error */ DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon, char *apid, char *ctid, int8_t log_level, int8_t trace_status, int log_level_pos, int user_handle, char *description, char *ecu, int verbose); /** * Delete context from internal context management * @param daemon pointer to dlt daemon structure * @param context pointer to context to be deleted * @param ecu pointer to ecu id of node to delete application * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_context_del(DltDaemon *daemon, DltDaemonContext *context, char *ecu, int verbose); /** * Find context with specific application id and context id * @param daemon pointer to dlt daemon structure * @param apid pointer to application id * @param ctid pointer to context id * @param ecu pointer to ecu id of node to clear applications * @param verbose if set to true verbose information is printed out. * @return Pointer to context, null pointer on error or not found */ DltDaemonContext *dlt_daemon_context_find(DltDaemon *daemon, char *apid, char *ctid, char *ecu, int verbose); /** * Invalidate all contexts fd, if fd is reused * @param daemon pointer to dlt daemon structure * @param ecu node these contexts running on. * @param fd file descriptor * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon, char *ecu, int fd, int verbose); /** * Clear all contexts in internal context management of specific ecu * @param daemon pointer to dlt daemon structure * @param ecu pointer to ecu id of node to clear contexts * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_contexts_clear(DltDaemon *daemon, char *ecu, int verbose); /** * Load contexts from file to internal context management * @param daemon pointer to dlt daemon structure * @param filename name of file to be used for loading * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_contexts_load(DltDaemon *daemon, const char *filename, int verbose); /** * Save contexts from internal context management to file * @param daemon pointer to dlt daemon structure * @param filename name of file to be used for saving * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_contexts_save(DltDaemon *daemon, const char *filename, int verbose); /** * Load persistant configuration * @param daemon pointer to dlt daemon structure * @param filename name of file to be used for loading * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_configuration_load(DltDaemon *daemon, const char *filename, int verbose); /** * Save configuration persistantly * @param daemon pointer to dlt daemon structure * @param filename name of file to be used for saving * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_configuration_save(DltDaemon *daemon, const char *filename, int verbose); /** * Send user message DLT_USER_MESSAGE_LOG_LEVEL to user application * @param daemon pointer to dlt daemon structure * @param context pointer to context for response * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_user_send_log_level(DltDaemon *daemon, DltDaemonContext *context, int verbose); /** * Send user message DLT_USER_MESSAGE_LOG_STATE to user application * @param daemon pointer to dlt daemon structure * @param app pointer to application for response * @param verbose if set to true verbose information is printed out. * @return negative value if there was an error */ int dlt_daemon_user_send_log_state(DltDaemon *daemon, DltDaemonApplication *app, int verbose); /** * Send user messages to all user applications using default context, or trace status * to update those values * @param daemon pointer to dlt daemon structure * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose); /** * Send user messages to all user applications context to update with the new log level * @param daemon pointer to dlt daemon structure * @param enforce_context_ll_and_ts defines if enforcement of log levels is on * @param context_log_level the log level of the context * @param log_level new log level to be set * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, int enforce_context_ll_and_ts, int8_t context_log_level, int8_t log_level, int verbose); /** * Send user messages to all user applications context to update with the new trace status * @param daemon pointer to dlt daemon structure * @param trace_status new trace status to be set * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_user_send_all_trace_status_update(DltDaemon *daemon, int8_t trace_status, int verbose); /** * Send user messages to all user applications the log status * everytime the client is connected or disconnected. * @param daemon pointer to dlt daemon structure * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose); /** * Process reset to factory default control message * @param daemon pointer to dlt daemon structure * @param filename name of file containing the runtime defaults for applications * @param filename1 name of file containing the runtime defaults for contexts * @param InitialContextLogLevel loglevel to be sent to context when those register with loglevel default, read from dlt.conf * @param InitialContextTraceStatus tracestatus to be sent to context when those register with tracestatus default, read from dlt.conf * @param InitialEnforceLlTsStatus force default log-level * @param verbose if set to true verbose information is printed out. */ void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon, const char *filename, const char *filename1, int InitialContextLogLevel, int InitialContextTraceStatus, int InitialEnforceLlTsStatus, int verbose); /** * Change the logging state of dlt daemon * @param daemon pointer to dlt daemon structure * @param newState the requested new state */ void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState); # ifdef __cplusplus } # endif /** \} */ #endif /* DLT_DAEMON_COMMON_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_common_cfg.h000066400000000000000000000130501446635226000224160ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_common_cfg.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_common_cfg.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_DAEMON_COMMON_CFG_H #define DLT_DAEMON_COMMON_CFG_H /*************/ /* Changable */ /*************/ /* Default Path for runtime configuration */ #define DLT_RUNTIME_DEFAULT_DIRECTORY "/tmp" /* Path and filename for runtime configuration (applications) */ #define DLT_RUNTIME_APPLICATION_CFG "/dlt-runtime-application.cfg" /* Path and filename for runtime configuration (contexts) */ #define DLT_RUNTIME_CONTEXT_CFG "/dlt-runtime-context.cfg" /* Path and filename for runtime configuration */ #define DLT_RUNTIME_CONFIGURATION "/dlt-runtime.cfg" /* Default Path for control socket */ #define DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH DLT_RUNTIME_DEFAULT_DIRECTORY \ "/dlt-ctrl.sock" #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC #define DLT_DAEMON_DEFAULT_APP_SOCK_PATH DLT_RUNTIME_DEFAULT_DIRECTORY \ "/dlt-app.sock" #endif /* Size of text buffer */ #define DLT_DAEMON_COMMON_TEXTBUFSIZE 255 /* Application ID used when the dlt daemon creates a control message */ #define DLT_DAEMON_CTRL_APID "DA1" /* Context ID used when the dlt daemon creates a control message */ #define DLT_DAEMON_CTRL_CTID "DC1" /* Number of entries to be allocated at one in application table, * when no more entries are available */ #define DLT_DAEMON_APPL_ALLOC_SIZE 500 /* Number of entries to be allocated at one in context table, * when no more entries are available */ #define DLT_DAEMON_CONTEXT_ALLOC_SIZE 1000 /* Debug get log info function, * set to 1 to enable, 0 to disable debugging */ #define DLT_DEBUG_GETLOGINFO 0 /************************/ /* Don't change please! */ /************************/ /* Minimum ID for an injection message */ #define DLT_DAEMON_INJECTION_MIN 0xFFF /* Maximum ID for an injection message */ #define DLT_DAEMON_INJECTION_MAX 0xFFFFFFFF /* Remote interface identifier */ #define DLT_DAEMON_REMO_STRING "remo" #endif /* DLT_DAEMON_COMMON_CFG_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_connection.c000066400000000000000000000326051446635226000224500ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Frederic Berat * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_connection.c */ #include #include #include #include #include #include #include #include #include #include "dlt_daemon_connection_types.h" #include "dlt_daemon_connection.h" #include "dlt_daemon_event_handler_types.h" #include "dlt_daemon_event_handler.h" #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common.h" #include "dlt_common.h" #include "dlt_gateway.h" #include "dlt_daemon_socket.h" static DltConnectionId connectionId; extern char *app_recv_buffer; /** @brief Generic sending function. * * We manage different type of connection which have similar send/write * functions. We can then abstract the data transfer using this function, * moreover as we often transfer data to different kind of connection * within the same loop. * * @param conn The connection structure. * @param msg The message buffer to be sent * @param msg_size The length of the message to be sent * * @return DLT_DAEMON_ERROR_OK on success, DLT_DAEMON_ERROR_SEND_FAILED * on send failure, DLT_DAEMON_ERROR_UNKNOWN otherwise. * errno is appropriately set. */ DLT_STATIC int dlt_connection_send(DltConnection *conn, void *msg, size_t msg_size) { DltConnectionType type = DLT_CONNECTION_TYPE_MAX; int ret = 0; if ((conn != NULL) && (conn->receiver != NULL)) type = conn->type; switch (type) { case DLT_CONNECTION_CLIENT_MSG_SERIAL: if (write(conn->receiver->fd, msg, msg_size) > 0) return DLT_DAEMON_ERROR_OK; return DLT_DAEMON_ERROR_UNKNOWN; case DLT_CONNECTION_CLIENT_MSG_TCP: ret = dlt_daemon_socket_sendreliable(conn->receiver->fd, msg, msg_size); return ret; default: return DLT_DAEMON_ERROR_UNKNOWN; } } /** @brief Send up to two messages through a connection. * * We often need to send 2 messages through a specific connection, plus * the serial header. This function groups these different calls. * * @param con The connection to send the messages through. * @param data1 The first message to be sent. * @param size1 The size of the first message. * @param data2 The second message to be send. * @param size2 The second message size. * @param sendserialheader Whether we need or not to send the serial header. * * @return DLT_DAEMON_ERROR_OK on success, -1 otherwise. errno is properly set. */ int dlt_connection_send_multiple(DltConnection *con, void *data1, int size1, void *data2, int size2, int sendserialheader) { int ret = 0; if (con == NULL) return DLT_DAEMON_ERROR_UNKNOWN; if (sendserialheader) ret = dlt_connection_send(con, (void *)dltSerialHeader, sizeof(dltSerialHeader)); if ((data1 != NULL) && (ret == DLT_RETURN_OK)) ret = dlt_connection_send(con, data1, size1); if ((data2 != NULL) && (ret == DLT_RETURN_OK)) ret = dlt_connection_send(con, data2, size2); return ret; } /** @brief Get the next connection filtered with a type mask. * * In some cases we need the next connection available of a specific type or * specific different types. This function returns the next available connection * that is of one of the types included in the mask. The current connection can * be returned. * * @param current The current connection pointer. * @param type_mask A bit mask representing the connection types to be filtered. * * @return The next available connection of the considered types or NULL. */ DltConnection *dlt_connection_get_next(DltConnection *current, int type_mask) { while (current && !((1 << current->type) & type_mask)) current = current->next; return current; } DLT_STATIC void dlt_connection_destroy_receiver(DltConnection *con) { if (!con) return; switch (con->type) { case DLT_CONNECTION_GATEWAY: /* We rely on the gateway for clean-up */ break; case DLT_CONNECTION_APP_MSG: dlt_receiver_free_global_buffer(con->receiver); free(con->receiver); con->receiver = NULL; break; default: (void)dlt_receiver_free(con->receiver); free(con->receiver); con->receiver = NULL; break; } } /** @brief Get the receiver structure associated to a connection. * * The receiver structure is sometimes needed while handling the event. * This behavior is mainly due to the fact that it's not intended to modify * the whole design of the daemon while implementing the new event handling. * Based on the connection type provided, this function returns the pointer * to the DltReceiver structure corresponding. * * @param daemon_local Structure where to take the DltReceiver pointer from. * @param type Type of the connection. * @param fd File descriptor * * @return DltReceiver structure or NULL if none corresponds to the type. */ DLT_STATIC DltReceiver *dlt_connection_get_receiver(DltDaemonLocal *daemon_local, DltConnectionType type, int fd) { DltReceiver *ret = NULL; DltReceiverType receiver_type = DLT_RECEIVE_FD; struct stat statbuf; switch (type) { case DLT_CONNECTION_CONTROL_CONNECT: /* FALL THROUGH */ case DLT_CONNECTION_CONTROL_MSG: /* FALL THROUGH */ case DLT_CONNECTION_CLIENT_CONNECT: /* FALL THROUGH */ case DLT_CONNECTION_CLIENT_MSG_TCP: ret = calloc(1, sizeof(DltReceiver)); if (ret) dlt_receiver_init(ret, fd, DLT_RECEIVE_SOCKET, DLT_DAEMON_RCVBUFSIZESOCK); break; case DLT_CONNECTION_CLIENT_MSG_SERIAL: ret = calloc(1, sizeof(DltReceiver)); if (ret) dlt_receiver_init(ret, fd, DLT_RECEIVE_FD, DLT_DAEMON_RCVBUFSIZESERIAL); break; case DLT_CONNECTION_APP_MSG: ret = calloc(1, sizeof(DltReceiver)); receiver_type = DLT_RECEIVE_FD; if (fstat(fd, &statbuf) == 0) { if (S_ISSOCK(statbuf.st_mode)) receiver_type = DLT_RECEIVE_SOCKET; } else { dlt_vlog(LOG_WARNING, "Failed to determine receive type for DLT_CONNECTION_APP_MSG, using \"FD\"\n"); } if (ret) dlt_receiver_init_global_buffer(ret, fd, receiver_type, &app_recv_buffer); break; #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE case DLT_CONNECTION_APP_CONNECT: /* FALL THROUGH */ #endif case DLT_CONNECTION_ONE_S_TIMER: /* FALL THROUGH */ case DLT_CONNECTION_SIXTY_S_TIMER: #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE /* FALL THROUGH */ case DLT_CONNECTION_SYSTEMD_TIMER: #endif /* FALL THROUGH */ case DLT_CONNECTION_GATEWAY_TIMER: ret = calloc(1, sizeof(DltReceiver)); if (ret) dlt_receiver_init(ret, fd, DLT_RECEIVE_FD, DLT_DAEMON_RCVBUFSIZE); break; case DLT_CONNECTION_GATEWAY: /* We rely on the gateway for init */ ret = dlt_gateway_get_connection_receiver(&daemon_local->pGateway, fd); break; default: ret = NULL; } return ret; } /** @brief Get the callback from a specific connection. * * The callback retrieved that way is used to handle event for this connection. * It as been chosen to proceed that way instead of having the callback directly * in the structure in order to have some way to check that the structure is * still valid, or at least gracefully handle errors instead of crashing. * * @param con The connection to retrieve the callback from. * * @return Function pointer or NULL. */ void *dlt_connection_get_callback(DltConnection *con) { void *ret = NULL; DltConnectionType type = DLT_CONNECTION_TYPE_MAX; if (con) type = con->type; switch (type) { case DLT_CONNECTION_CLIENT_CONNECT: ret = dlt_daemon_process_client_connect; break; case DLT_CONNECTION_CLIENT_MSG_TCP: ret = dlt_daemon_process_client_messages; break; case DLT_CONNECTION_CLIENT_MSG_SERIAL: ret = dlt_daemon_process_client_messages_serial; break; #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE case DLT_CONNECTION_APP_CONNECT: ret = dlt_daemon_process_app_connect; break; #endif case DLT_CONNECTION_APP_MSG: ret = dlt_daemon_process_user_messages; break; case DLT_CONNECTION_ONE_S_TIMER: ret = dlt_daemon_process_one_s_timer; break; case DLT_CONNECTION_SIXTY_S_TIMER: ret = dlt_daemon_process_sixty_s_timer; break; #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE case DLT_CONNECTION_SYSTEMD_TIMER: ret = dlt_daemon_process_systemd_timer; break; #endif case DLT_CONNECTION_CONTROL_CONNECT: ret = dlt_daemon_process_control_connect; break; case DLT_CONNECTION_CONTROL_MSG: ret = dlt_daemon_process_control_messages; break; case DLT_CONNECTION_GATEWAY: ret = dlt_gateway_process_passive_node_messages; break; case DLT_CONNECTION_GATEWAY_TIMER: ret = dlt_gateway_process_gateway_timer; break; default: ret = NULL; } return ret; } /** @brief Destroys a connection. * * This function closes and frees the corresponding connection. This is expected * to be called by the connection owner: the DltEventHandler. * Ownership of the connection is given during the registration to * the DltEventHandler. * * @param to_destroy Connection to be destroyed. */ void dlt_connection_destroy(DltConnection *to_destroy) { to_destroy->id = 0; close(to_destroy->receiver->fd); dlt_connection_destroy_receiver(to_destroy); free(to_destroy); } /** @brief Creates a connection and registers it to the DltEventHandler. * * The function will allocate memory for the connection, and give the pointer * to the DltEventHandler in order to register it for incoming events. * The connection is then destroyed later on, once it's not needed anymore or * it the event handler is destroyed. * * @param daemon_local Structure were some needed information is. * @param evh DltEventHandler to register the connection to. * @param fd File descriptor of the connection. * @param mask Event list bit mask. * @param type Connection type. * * @return 0 On success, -1 otherwise. */ int dlt_connection_create(DltDaemonLocal *daemon_local, DltEventHandler *evh, int fd, int mask, DltConnectionType type) { DltConnection *temp = NULL; if (fd < 0) /* Nothing to do */ return 0; if (dlt_event_handler_find_connection(evh, fd) != NULL) /* No need for the same client to be registered twice * for the same event. * TODO: If another mask can be expected, * we need it to update the poll event here. */ return 0; temp = (DltConnection *)malloc(sizeof(DltConnection)); if (temp == NULL) { dlt_log(LOG_CRIT, "Allocation of client handle failed\n"); return -1; } memset(temp, 0, sizeof(DltConnection)); temp->receiver = dlt_connection_get_receiver(daemon_local, type, fd); if (!temp->receiver) { dlt_vlog(LOG_CRIT, "Unable to get receiver from %u connection.\n", type); free(temp); return -1; } struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE char *watchdogUSec = getenv("WATCHDOG_USEC"); if (watchdogUSec) { timeout.tv_sec = atoi(watchdogUSec) / 1000000; timeout.tv_usec = atoi(watchdogUSec) % 1000000; } #endif if (setsockopt (temp->receiver->fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof timeout) < 0) { dlt_vlog(LOG_WARNING, "Unable to set send timeout %s.\n", strerror(errno)); } /* We are single threaded no need for protection. */ temp->id = connectionId++; if (!temp->id) /* Skipping 0 */ temp->id = connectionId++; temp->type = type; temp->status = ACTIVE; /* Now give the ownership of the newly created connection * to the event handler, by registering for events. */ return dlt_event_handler_register_connection(evh, daemon_local, temp, mask); } dlt-daemon-2.18.10/src/daemon/dlt_daemon_connection.h000066400000000000000000000036551446635226000224600ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Frederic Berat * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_connection.h */ #ifndef DLT_DAEMON_CONNECTION_H #define DLT_DAEMON_CONNECTION_H #include "dlt_daemon_connection_types.h" #include "dlt_daemon_event_handler_types.h" #include "dlt-daemon.h" int dlt_connection_send_multiple(DltConnection *, void *, int, void *, int, int); DltConnection *dlt_connection_get_next(DltConnection *, int); int dlt_connection_create_remaining(DltDaemonLocal *); int dlt_connection_create(DltDaemonLocal *, DltEventHandler *, int, int, DltConnectionType); void dlt_connection_destroy(DltConnection *); void *dlt_connection_get_callback(DltConnection *); #ifdef DLT_UNIT_TESTS int dlt_connection_send(DltConnection *conn, void *msg, size_t msg_size); void dlt_connection_destroy_receiver(DltConnection *con); DltReceiver *dlt_connection_get_receiver(DltDaemonLocal *daemon_local, DltConnectionType type, int fd); #endif #endif /* DLT_DAEMON_CONNECTION_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_connection_types.h000066400000000000000000000065221446635226000237000ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Frederic Berat * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_connection_types.h */ #ifndef DLT_DAEMON_CONNECTION_TYPES_H #define DLT_DAEMON_CONNECTION_TYPES_H #include "dlt_common.h" typedef enum { UNDEFINED, /* Undefined status */ INACTIVE, /* Connection is inactive, excluded from poll handling */ ACTIVE, /* Connection is actively handled by poll */ DEACTIVATE,/* Request for deactivation of the connection */ ACTIVATE /* Request for activation of the connection */ } DltConnectionStatus; typedef enum { DLT_CONNECTION_NONE = 0, DLT_CONNECTION_CLIENT_CONNECT, DLT_CONNECTION_CLIENT_MSG_TCP, DLT_CONNECTION_CLIENT_MSG_SERIAL, DLT_CONNECTION_APP_CONNECT, DLT_CONNECTION_APP_MSG, DLT_CONNECTION_ONE_S_TIMER, DLT_CONNECTION_SIXTY_S_TIMER, DLT_CONNECTION_SYSTEMD_TIMER, DLT_CONNECTION_CONTROL_CONNECT, DLT_CONNECTION_CONTROL_MSG, DLT_CONNECTION_GATEWAY, DLT_CONNECTION_GATEWAY_TIMER, DLT_CONNECTION_TYPE_MAX } DltConnectionType; #define DLT_CON_MASK_CLIENT_CONNECT (1 << DLT_CONNECTION_CLIENT_CONNECT) #define DLT_CON_MASK_CLIENT_MSG_TCP (1 << DLT_CONNECTION_CLIENT_MSG_TCP) #define DLT_CON_MASK_CLIENT_MSG_SERIAL (1 << DLT_CONNECTION_CLIENT_MSG_SERIAL) #define DLT_CON_MASK_APP_MSG (1 << DLT_CONNECTION_APP_MSG) #define DLT_CON_MASK_APP_CONNECT (1 << DLT_CONNECTION_APP_CONNECT) #define DLT_CON_MASK_ONE_S_TIMER (1 << DLT_CONNECTION_ONE_S_TIMER) #define DLT_CON_MASK_SIXTY_S_TIMER (1 << DLT_CONNECTION_SIXTY_S_TIMER) #define DLT_CON_MASK_SYSTEMD_TIMER (1 << DLT_CONNECTION_SYSTEMD_TIMER) #define DLT_CON_MASK_CONTROL_CONNECT (1 << DLT_CONNECTION_CONTROL_CONNECT) #define DLT_CON_MASK_CONTROL_MSG (1 << DLT_CONNECTION_CONTROL_MSG) #define DLT_CON_MASK_GATEWAY (1 << DLT_CONNECTION_GATEWAY) #define DLT_CON_MASK_GATEWAY_TIMER (1 << DLT_CONNECTION_GATEWAY_TIMER) #define DLT_CON_MASK_ALL (0xffff) typedef uintptr_t DltConnectionId; /* TODO: squash the DltReceiver structure in there * and remove any other duplicates of FDs */ typedef struct DltConnection { DltConnectionId id; DltReceiver *receiver; /**< Receiver structure for this connection */ DltConnectionType type; /**< Represents what type of handle is this (like FIFO, serial, client, server) */ DltConnectionStatus status; /**< Status of connection */ struct DltConnection *next; /**< For multiple client connection using linked list */ int ev_mask; /**< Mask to set when registering the connection for events */ } DltConnection; #endif /* DLT_DAEMON_CONNECTION_TYPES_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_event_handler.c000066400000000000000000000372021446635226000231250ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Frederic Berat * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_event_handler.c */ #include #include #include #include #include #include #include "dlt_common.h" #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common.h" #include "dlt_daemon_connection.h" #include "dlt_daemon_connection_types.h" #include "dlt_daemon_event_handler.h" #include "dlt_daemon_event_handler_types.h" /** * \def DLT_EV_TIMEOUT_MSEC * The maximum amount of time to wait for a poll event. * Set to 1 second to avoid unnecessary wake ups. */ #define DLT_EV_TIMEOUT_MSEC 1000 #define DLT_EV_BASE_FD 16 #define DLT_EV_MASK_REJECTED (POLLERR | POLLNVAL) /** @brief Initialize a pollfd structure * * That ensures that no event will be mis-watched. * * @param pfd The element to initialize */ static void init_poll_fd(struct pollfd *pfd) { pfd->fd = -1; pfd->events = 0; pfd->revents = 0; } /** @brief Prepare the event handler * * This will create the base poll file descriptor list. * * @param ev The event handler to prepare. * * @return 0 on success, -1 otherwise. */ int dlt_daemon_prepare_event_handling(DltEventHandler *ev) { int i = 0; if (ev == NULL) return DLT_RETURN_ERROR; ev->pfd = calloc(DLT_EV_BASE_FD, sizeof(struct pollfd)); if (ev->pfd == NULL) { dlt_log(LOG_CRIT, "Creation of poll instance failed!\n"); return -1; } for (i = 0; i < DLT_EV_BASE_FD; i++) init_poll_fd(&ev->pfd[i]); ev->nfds = 0; ev->max_nfds = DLT_EV_BASE_FD; return 0; } /** @brief Enable a file descriptor to be watched * * Adds a file descriptor to the descriptor list. If the list is to small, * increase its size. * * @param ev The event handler structure, containing the list * @param fd The file descriptor to add * @param mask The mask of event to be watched */ static void dlt_event_handler_enable_fd(DltEventHandler *ev, int fd, int mask) { if (ev->max_nfds <= ev->nfds) { int i = ev->nfds; int max = 2 * ev->max_nfds; struct pollfd *tmp = realloc(ev->pfd, max * sizeof(*ev->pfd)); if (!tmp) { dlt_log(LOG_CRIT, "Unable to register new fd for the event handler.\n"); return; } ev->pfd = tmp; ev->max_nfds = max; for (; i < max; i++) init_poll_fd(&ev->pfd[i]); } ev->pfd[ev->nfds].fd = fd; ev->pfd[ev->nfds].events = mask; ev->nfds++; } /** @brief Disable a file descriptor for watching * * The file descriptor is removed from the descriptor list, the list is * compressed during the process. * * @param ev The event handler structure containing the list * @param fd The file descriptor to be removed */ static void dlt_event_handler_disable_fd(DltEventHandler *ev, int fd) { unsigned int i = 0; unsigned int j = 0; unsigned int nfds = ev->nfds; for (; i < nfds; i++, j++) { if (ev->pfd[i].fd == fd) { init_poll_fd(&ev->pfd[i]); j++; ev->nfds--; } if (i == j) continue; /* Compressing the table */ if (i < ev->nfds) { ev->pfd[i].fd = ev->pfd[j].fd; ev->pfd[i].events = ev->pfd[j].events; ev->pfd[i].revents = ev->pfd[j].revents; } else { init_poll_fd(&ev->pfd[i]); } } } /** @brief Catch and process incoming events. * * This function waits for events on all connections. Once an event raise, * the callback for the specific connection is called, or the connection is * destroyed if a hangup occurs. * * @param daemon Structure to be passed to the callback. * @param daemon_local Structure containing needed information. * @param pEvent Event handler structure. * * @return 0 on success, -1 otherwise. May be interrupted. */ int dlt_daemon_handle_event(DltEventHandler *pEvent, DltDaemon *daemon, DltDaemonLocal *daemon_local) { int ret = 0; unsigned int i = 0; int (*callback)(DltDaemon *, DltDaemonLocal *, DltReceiver *, int) = NULL; if ((pEvent == NULL) || (daemon == NULL) || (daemon_local == NULL)) return DLT_RETURN_ERROR; ret = poll(pEvent->pfd, pEvent->nfds, DLT_EV_TIMEOUT_MSEC); if (ret <= 0) { /* We are not interested in EINTR has it comes * either from timeout or signal. */ if (errno == EINTR) ret = 0; if (ret < 0) dlt_vlog(LOG_CRIT, "poll() failed: %s\n", strerror(errno)); return ret; } for (i = 0; i < pEvent->nfds; i++) { int fd = 0; DltConnection *con = NULL; DltConnectionType type = DLT_CONNECTION_TYPE_MAX; if (pEvent->pfd[i].revents == 0) continue; con = dlt_event_handler_find_connection(pEvent, pEvent->pfd[i].fd); if (con && con->receiver) { type = con->type; fd = con->receiver->fd; } else { /* connection might have been destroyed in the meanwhile */ dlt_event_handler_disable_fd(pEvent, pEvent->pfd[i].fd); continue; } /* First of all handle error events */ if (pEvent->pfd[i].revents & DLT_EV_MASK_REJECTED) { /* An error occurred, we need to clean-up the concerned event */ if (type == DLT_CONNECTION_CLIENT_MSG_TCP) /* To transition to BUFFER state if this is final TCP client connection, * call dedicated function. this function also calls * dlt_event_handler_unregister_connection() inside the function. */ dlt_daemon_close_socket(fd, daemon, daemon_local, 0); else dlt_event_handler_unregister_connection(pEvent, daemon_local, fd); continue; } /* Get the function to be used to handle the event */ callback = dlt_connection_get_callback(con); if (!callback) { dlt_vlog(LOG_CRIT, "Unable to find function for %u handle type.\n", type); return -1; } /* From now on, callback is correct */ if (callback(daemon, daemon_local, con->receiver, daemon_local->flags.vflag) == -1) { dlt_vlog(LOG_CRIT, "Processing from %u handle type failed!\n", type); return -1; } } return 0; } /** @brief Find connection with a specific \a fd in the connection list. * * There can be only one event per \a fd. We can then find a specific connection * based on this \a fd. That allows to check if a specific \a fd has already been * registered. * * @param ev The event handler structure where the list of connection is. * @param fd The file descriptor of the connection to be found. * * @return The found connection pointer, NULL otherwise. */ DltConnection *dlt_event_handler_find_connection(DltEventHandler *ev, int fd) { DltConnection *temp = ev->connections; while (temp != NULL) { if ((temp->receiver != NULL) && (temp->receiver->fd == fd)) return temp; temp = temp->next; } return temp; } /** @brief Remove a connection from the list and destroy it. * * This function will first look for the connection in the event handler list, * remove it from the list and then destroy it. * * @param ev The event handler structure where the list of connection is. * @param to_remove The connection to remove from the list. * * @return 0 on success, -1 if the connection is not found. */ DLT_STATIC int dlt_daemon_remove_connection(DltEventHandler *ev, DltConnection *to_remove) { if ((ev == NULL) || (to_remove == NULL)) return DLT_RETURN_ERROR; DltConnection *curr = ev->connections; DltConnection *prev = curr; /* Find the address where to_remove value is registered */ while (curr && (curr != to_remove)) { prev = curr; curr = curr->next; } if (!curr) { /* Must not be possible as we check for existence before */ dlt_log(LOG_CRIT, "Connection not found for removal.\n"); return -1; } else if (curr == ev->connections) { ev->connections = curr->next; } else { prev->next = curr->next; } /* Now we can destroy our pointer */ dlt_connection_destroy(to_remove); return 0; } /** @brief Destroy the connection list. * * This function runs through the connection list and destroy them one by one. * * @param ev Pointer to the event handler structure. */ void dlt_event_handler_cleanup_connections(DltEventHandler *ev) { unsigned int i = 0; if (ev == NULL) /* Nothing to do. */ return; while (ev->connections != NULL) /* We don really care on failure */ (void)dlt_daemon_remove_connection(ev, ev->connections); for (i = 0; i < ev->nfds; i++) init_poll_fd(&ev->pfd[i]); free(ev->pfd); } /** @brief Add a new connection to the list. * * The connection is added at the tail of the list. * * @param ev The event handler structure where the connection list is. * @param connection The connection to be added. */ DLT_STATIC void dlt_daemon_add_connection(DltEventHandler *ev, DltConnection *connection) { DltConnection **temp = &ev->connections; while (*temp != NULL) temp = &(*temp)->next; *temp = connection; } /** @brief Check for connection activation * * If the connection is active and it's not allowed anymore or it the user * ask for deactivation, the connection will be deactivated. * If the connection is inactive, the user asks for activation and it's * allowed for it to be activated, the connection will be activated. * * @param evhdl The event handler structure. * @param con The connection to act on * @param activation_type The type of activation requested ((DE)ACTIVATE) * * @return 0 on success, -1 otherwise */ int dlt_connection_check_activate(DltEventHandler *evhdl, DltConnection *con, int activation_type) { if (!evhdl || !con || !con->receiver) { dlt_vlog(LOG_ERR, "%s: wrong parameters.\n", __func__); return -1; } switch (con->status) { case ACTIVE: if (activation_type == DEACTIVATE) { dlt_vlog(LOG_INFO, "Deactivate connection type: %u\n", con->type); dlt_event_handler_disable_fd(evhdl, con->receiver->fd); if (con->type == DLT_CONNECTION_CLIENT_CONNECT) con->receiver->fd = -1; con->status = INACTIVE; } break; case INACTIVE: if (activation_type == ACTIVATE) { dlt_vlog(LOG_INFO, "Activate connection type: %u\n", con->type); dlt_event_handler_enable_fd(evhdl, con->receiver->fd, con->ev_mask); con->status = ACTIVE; } break; default: dlt_vlog(LOG_ERR, "Unknown connection status: %u\n", con->status); return -1; } return 0; } /** @brief Registers a connection for event handling and takes its ownership. * * As we add the connection to the list of connection, we take its ownership. * That's the only place where the connection pointer is stored. * The connection is then used to create a new event trigger. * If the connection is of type DLT_CONNECTION_CLIENT_MSG_TCP, we increase * the daemon_local->client_connections counter. TODO: Move this counter inside * the event handler structure. * * @param evhdl The event handler structure where the connection list is. * @param daemon_local Structure containing needed information. * @param connection The connection to be registered. * @param mask The bit mask of event to be registered. * * @return 0 on success, -1 otherwise. */ int dlt_event_handler_register_connection(DltEventHandler *evhdl, DltDaemonLocal *daemon_local, DltConnection *connection, int mask) { if (!evhdl || !connection || !connection->receiver) { dlt_log(LOG_ERR, "Wrong parameters when registering connection.\n"); return -1; } dlt_daemon_add_connection(evhdl, connection); if ((connection->type == DLT_CONNECTION_CLIENT_MSG_TCP) || (connection->type == DLT_CONNECTION_CLIENT_MSG_SERIAL)) daemon_local->client_connections++; /* On creation the connection is not active by default */ connection->status = INACTIVE; connection->next = NULL; connection->ev_mask = mask; return dlt_connection_check_activate(evhdl, connection, ACTIVATE); } /** @brief Unregisters a connection from the event handler and destroys it. * * We first look for the connection to be unregistered, delete the event * corresponding and then destroy the connection. * If the connection is of type DLT_CONNECTION_CLIENT_MSG_TCP, we decrease * the daemon_local->client_connections counter. TODO: Move this counter inside * the event handler structure. * * @param evhdl The event handler structure where the connection list is. * @param daemon_local Structure containing needed information. * @param fd The file descriptor of the connection to be unregistered. * * @return 0 on success, -1 otherwise. */ int dlt_event_handler_unregister_connection(DltEventHandler *evhdl, DltDaemonLocal *daemon_local, int fd) { if ((evhdl == NULL) || (daemon_local == NULL)) return DLT_RETURN_ERROR; /* Look for the pointer in the client list. * There shall be only one event handler with the same fd. */ DltConnection *temp = dlt_event_handler_find_connection(evhdl, fd); if (!temp) { dlt_log(LOG_ERR, "Connection not found for unregistration.\n"); return -1; } if ((temp->type == DLT_CONNECTION_CLIENT_MSG_TCP) || (temp->type == DLT_CONNECTION_CLIENT_MSG_SERIAL)) { daemon_local->client_connections--; if (daemon_local->client_connections < 0) { daemon_local->client_connections = 0; dlt_log(LOG_CRIT, "Unregistering more client than registered!\n"); } } if (dlt_connection_check_activate(evhdl, temp, DEACTIVATE) < 0) dlt_log(LOG_ERR, "Unable to unregister event.\n"); /* Cannot fail as far as dlt_daemon_find_connection succeed */ return dlt_daemon_remove_connection(evhdl, temp); } dlt-daemon-2.18.10/src/daemon/dlt_daemon_event_handler.h000066400000000000000000000045111446635226000231270ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Frederic Berat * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_event_handler.h */ #include #include "dlt_daemon_connection_types.h" #include "dlt_daemon_event_handler_types.h" #include "dlt-daemon.h" #ifndef DLT_DAEMON_EVENT_HANDLER_H #define DLT_DAEMON_EVENT_HANDLER_H int dlt_daemon_prepare_event_handling(DltEventHandler *); int dlt_daemon_handle_event(DltEventHandler *, DltDaemon *, DltDaemonLocal *); DltConnection *dlt_event_handler_find_connection_by_id(DltEventHandler *, DltConnectionId); DltConnection *dlt_event_handler_find_connection(DltEventHandler *, int); void dlt_event_handler_cleanup_connections(DltEventHandler *); int dlt_event_handler_register_connection(DltEventHandler *, DltDaemonLocal *, DltConnection *, int); int dlt_event_handler_unregister_connection(DltEventHandler *, DltDaemonLocal *, int); int dlt_connection_check_activate(DltEventHandler *, DltConnection *, int); #ifdef DLT_UNIT_TESTS int dlt_daemon_remove_connection(DltEventHandler *ev, DltConnection *to_remove); void dlt_daemon_add_connection(DltEventHandler *ev, DltConnection *connection); #endif #endif /* DLT_DAEMON_EVENT_HANDLER_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_event_handler_types.h000066400000000000000000000031171446635226000243540ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Frederic Berat * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_event_handler_types.h */ #include #include "dlt_daemon_connection_types.h" #ifndef DLT_DAEMON_EVENT_HANDLER_TYPES_H #define DLT_DAEMON_EVENT_HANDLER_TYPES_H /* FIXME: Remove the need for DltDaemonLocal everywhere in the code * These typedefs are needed by DltDaemonLocal which is * itself needed for functions used by the event handler * (as this structure is used everywhere in the code ...) */ typedef enum { DLT_TIMER_PACKET = 0, DLT_TIMER_ECU, #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE DLT_TIMER_SYSTEMD, #endif DLT_TIMER_GATEWAY, DLT_TIMER_UNKNOWN } DltTimers; typedef struct { struct pollfd *pfd; nfds_t nfds; nfds_t max_nfds; DltConnection *connections; } DltEventHandler; #endif /* DLT_DAEMON_EVENT_HANDLER_TYPES_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_offline_logstorage.c000066400000000000000000001330301446635226000241530ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2018 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality source file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * * \file: dlt_daemon_offline_logstorage.c * For further information see http://www.covesa.org/. */ #include #include #include #include #include "dlt_daemon_offline_logstorage.h" #include "dlt_daemon_offline_logstorage_internal.h" #include "dlt_gateway_types.h" #include "dlt_gateway.h" /** * dlt_logstorage_split_ecuid * * Split keys with ECU ID alone * * @param key Key * @param len Key length * @param ecuid ECU ID from key stored here * @param apid Application ID as .* stored here * @param ctid Context id as .* stored here * @return 0 on success -1 on error */ DLT_STATIC DltReturnValue dlt_logstorage_split_ecuid(char *key, int len, char *ecuid, char *apid, char *ctid) { if ((len > (DLT_ID_SIZE + 2)) || (len < 2)) return DLT_RETURN_ERROR; memcpy(ecuid, key, (len - 2)); memcpy(apid, ".*", 2); memcpy(ctid, ".*", 2); return DLT_RETURN_OK; } unsigned int g_logstorage_cache_max; /** * dlt_logstorage_split_ctid * * Split keys with Context ID alone * * @param key Key * @param len Key length * @param apid Application ID as .* stored here * @param ctid Context id from key stored here * @return 0 on success -1 on error */ DLT_STATIC DltReturnValue dlt_logstorage_split_ctid(char *key, int len, char *apid, char *ctid) { if ((len > (DLT_ID_SIZE + 2)) || (len < 1)) return DLT_RETURN_ERROR; strncpy(ctid, (key + 2), (len - 1)); memcpy(apid, ".*", 2); return DLT_RETURN_OK; } /** * dlt_logstorage_split_apid * * Split keys with Application ID alone * * @param key Key * @param len Key length * @param apid Application ID from key is stored here * @param ctid Context id as .* stored here * @return 0 on success -1 on error */ DLT_STATIC DltReturnValue dlt_logstorage_split_apid(char *key, int len, char *apid, char *ctid) { if ((len > (DLT_ID_SIZE + 2)) || (len < 2)) return DLT_RETURN_ERROR; strncpy(apid, key + 1, (len - 2)); memcpy(ctid, ".*", 2); return DLT_RETURN_OK; } /** * dlt_logstorage_split_apid_ctid * * Split keys with Application ID and Context ID * * @param key Key * @param len Key length * @param apid Application ID from key is stored here * @param ctid CContext id from key is stored here * @return 0 on success -1 on error */ DLT_STATIC DltReturnValue dlt_logstorage_split_apid_ctid(char *key, int len, char *apid, char *ctid) { char *tok = NULL; if (len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) return DLT_RETURN_ERROR; /* copy apid and ctid */ tok = strtok(key, ":"); if (tok != NULL) strncpy(apid, tok, DLT_ID_SIZE); else return DLT_RETURN_ERROR; tok = strtok(NULL, ":"); if (tok != NULL) strncpy(ctid, tok, DLT_ID_SIZE); else return DLT_RETURN_ERROR; return DLT_RETURN_OK; } /** * dlt_logstorage_split_ecuid_apid * * Split keys with ECU ID and Application ID * * @param key Key * @param len Key length * @param ecuid ECU ID from key stored here * @param apid Application ID from key is stored here * @param ctid Context id as .* stored here * @return 0 on success -1 on error */ DLT_STATIC DltReturnValue dlt_logstorage_split_ecuid_apid(char *key, int len, char *ecuid, char *apid, char *ctid) { char *tok = NULL; if (len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) return DLT_RETURN_ERROR; /* copy apid and ctid */ tok = strtok(key, ":"); if (tok != NULL) strncpy(ecuid, tok, DLT_ID_SIZE); else return DLT_RETURN_ERROR; tok = strtok(NULL, ":"); if (tok != NULL) strncpy(apid, tok, DLT_ID_SIZE); else return DLT_RETURN_ERROR; memcpy(ctid, ".*", 2); return DLT_RETURN_OK; } /** * dlt_logstorage_split_multi * * Prepares keys with application ID alone, will use ecuid if provided * (ecuid\:apid\:\:) or (\:apid\:\:) * * @param key Prepared key stored here * @param len Key length * @param ecuid ECU ID * @param apid Application ID * @param ctid Context ID * @return None */ DLT_STATIC DltReturnValue dlt_logstorage_split_multi(char *key, int len, char *ecuid, char *apid, char *ctid) { char *tok = NULL; if (len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) return DLT_RETURN_ERROR; tok = strtok(key, ":"); if (tok == NULL) return DLT_RETURN_ERROR; len = strlen(tok); if (key[len + 1] == ':') { strncpy(ecuid, tok, DLT_ID_SIZE); tok = strtok(NULL, ":"); if (tok != NULL) strncpy(ctid, tok, DLT_ID_SIZE); memcpy(apid, ".*", 2); } else { strncpy(ecuid, tok, DLT_ID_SIZE); tok = strtok(NULL, ":"); if (tok != NULL) strncpy(apid, tok, DLT_ID_SIZE); tok = strtok(NULL, ":"); if (tok != NULL) strncpy(ctid, tok, DLT_ID_SIZE); } return DLT_RETURN_OK; } /** * dlt_logstorage_split_key * * Split a given key into apid and ctid. * If APID\: - apid = APID and ctid = .* * If \:CTID - ctid = CTID and apid = .* * Else apid = APID and ctid = CTID * * @param key Given key of filter hash map * @param apid Application id * @param ctid Context id * @param ecuid ECU id * @return 0 on success, -1 on error */ DLT_STATIC DltReturnValue dlt_logstorage_split_key(char *key, char *apid, char *ctid, char *ecuid) { int len = 0; char *sep = NULL; if ((key == NULL) || (apid == NULL) || (ctid == NULL) || (ecuid == NULL)) return DLT_RETURN_WRONG_PARAMETER; len = strlen(key); sep = strchr (key, ':'); if (sep == NULL) return DLT_RETURN_WRONG_PARAMETER; /* key is ecuid only ecuid::*/ if ((key[len - 1] == ':') && (key[len - 2] == ':')) return dlt_logstorage_split_ecuid(key, len, ecuid, apid, ctid); /* key is context id only ::apid*/ else if ((key[0] == ':') && (key[1] == ':')) return dlt_logstorage_split_ctid(key, len, apid, ctid); /* key is application id only :apid: */ else if ((key[0] == ':') && (key[len - 1] == ':')) return dlt_logstorage_split_apid(key, len, apid, ctid); /* key is :apid:ctid */ else if ((key[0] == ':') && (key[len - 1] != ':')) return dlt_logstorage_split_apid_ctid(key, len, apid, ctid); /* key is ecuid:apid: */ else if ((key[0] != ':') && (key[len - 1] == ':')) return dlt_logstorage_split_ecuid_apid(key, len, ecuid, apid, ctid); /* key is either ecuid::ctid or ecuid:apid:ctid */ else return dlt_logstorage_split_multi(key, len, ecuid, apid, ctid); } /** * Forward SET_LOG_LEVEL request to passive node * * @param daemon_local pointer to DltDaemonLocal structure * @param apid Application ID * @param ctid Context ID * @param ecuid ECU ID * @param loglevel requested log level * @param verbose verbosity flag */ DLT_STATIC DltReturnValue dlt_daemon_logstorage_update_passive_node_context( DltDaemonLocal *daemon_local, char *apid, char *ctid, char *ecuid, int loglevel, int verbose) { DltServiceSetLogLevel req = { 0 }; DltPassiveControlMessage ctrl = { 0 }; DltGatewayConnection *con = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon_local == NULL) || (apid == NULL) || (ctid == NULL) || (ecuid == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } con = dlt_gateway_get_connection(&daemon_local->pGateway, ecuid, verbose); if (con == NULL) { dlt_vlog(LOG_ERR, "Failed to fond connection to passive node %s\n", ecuid); return DLT_RETURN_ERROR; } ctrl.id = DLT_SERVICE_ID_SET_LOG_LEVEL; ctrl.type = CONTROL_MESSAGE_ON_DEMAND; dlt_set_id(req.apid, apid); dlt_set_id(req.ctid, ctid); req.log_level = loglevel; if (dlt_gateway_send_control_message(con, &ctrl, (void *)&req, verbose) != 0) { dlt_vlog(LOG_ERR, "Failed to forward SET_LOG_LEVEL message to passive node %s\n", ecuid); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } /** * dlt_daemon_logstorage_send_log_level * * Send new log level for the provided context, if ecuid is not daemon ecuid * update log level of passive node * * @param daemon DltDaemon structure * @param daemon_local DltDaemonLocal structure * @param context DltDaemonContext structure * @param ecuid ECU id * @param loglevel log level to be set to context * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ DLT_STATIC DltReturnValue dlt_daemon_logstorage_send_log_level(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltDaemonContext *context, char *ecuid, int loglevel, int verbose) { int old_log_level = -1; int ll = DLT_LOG_DEFAULT; if ((daemon == NULL) || (daemon_local == NULL) || (ecuid == NULL) || (context == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (strncmp(ecuid, daemon->ecuid, DLT_ID_SIZE) == 0) { old_log_level = context->storage_log_level; context->storage_log_level = DLT_OFFLINE_LOGSTORAGE_MAX(loglevel, context->storage_log_level); if (context->storage_log_level > old_log_level) { if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) { dlt_log(LOG_ERR, "Unable to update log level\n"); return DLT_RETURN_ERROR; } } } else { old_log_level = context->log_level; ll = DLT_OFFLINE_LOGSTORAGE_MAX(loglevel, context->log_level); if (ll > old_log_level) return dlt_daemon_logstorage_update_passive_node_context(daemon_local, context->apid, context->ctid, ecuid, ll, verbose); } return DLT_RETURN_OK; } /** * dlt_daemon_logstorage_reset_log_level * * The log levels are reset if log level provided is -1 (not sent to * application in this case). Reset and sent to application if current log level * provided is 0. * * @param daemon DltDaemon structure * @param daemon_local DltDaemonLocal structure * @param context DltDaemonContext structure * @param ecuid ECU ID * @param loglevel log level to be set to context * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ DLT_STATIC DltReturnValue dlt_daemon_logstorage_reset_log_level(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltDaemonContext *context, char *ecuid, int loglevel, int verbose) { if ((daemon == NULL) || (daemon_local == NULL) || (ecuid == NULL) || (context == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* Set storage level to -1, to clear log levels */ context->storage_log_level = DLT_LOG_DEFAULT; if (loglevel == DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL) { if (strncmp(ecuid, daemon->ecuid, DLT_ID_SIZE) == 0) { if (dlt_daemon_user_send_log_level(daemon, context, verbose) == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Unable to update log level\n"); return DLT_RETURN_ERROR; } } else { /* forward set log level to passive node */ return dlt_daemon_logstorage_update_passive_node_context(daemon_local, context->apid, context->ctid, ecuid, DLT_LOG_DEFAULT, verbose); } } return DLT_RETURN_OK; } /** * dlt_daemon_logstorage_force_reset_level * * Force resetting of log level since have no data provided by passive node. * * @param daemon DltDaemon structure * @param daemon_local DltDaemonLocal structure * @param apid Application ID * @param ctid Context ID * @param ecuid ECU ID * @param loglevel log level to be set to context * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ DLT_STATIC DltReturnValue dlt_daemon_logstorage_force_reset_level(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *apid, char *ctid, char *ecuid, int loglevel, int verbose) { int ll = DLT_LOG_DEFAULT; int num = 0; int i = 0; DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; if ((daemon == NULL) || (daemon_local == NULL) || (ecuid == NULL) || (apid == NULL) || (ctid == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) { num = dlt_logstorage_get_config(&(daemon->storage_handle[i]), config, apid, ctid, ecuid); if (num > 0) break; /* found config */ } if ((num == 0) || (config[0] == NULL)) { dlt_vlog(LOG_ERR, "%s: No information about APID: %s, CTID: %s, ECU: %s in Logstorage configuration\n", __func__, apid, ctid, ecuid); return DLT_RETURN_ERROR; } if (loglevel == DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL) ll = config[0]->reset_log_level; else ll = config[0]->log_level; return dlt_daemon_logstorage_update_passive_node_context(daemon_local, apid, ctid, ecuid, ll, verbose); } /** * dlt_logstorage_update_all_contexts * * Update log level of all contexts of the application by updating the daemon * internal table. The compare flags (cmp_flag) indicates if Id has to be * compared with application id or Context id of the daemon internal table. * The log levels are reset if current log level provided is -1 (not sent to * application in this case). Reset and sent to application if current log level * provided is 0. * * @param daemon DltDaemon structure * @param daemon_local DltDaemonLocal structure * @param id application id or context id * @param curr_log_level log level to be set to context * @param cmp_flag compare flag * @param ecuid ecu id where application runs * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ DltReturnValue dlt_logstorage_update_all_contexts(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *id, int curr_log_level, int cmp_flag, char *ecuid, int verbose) { DltDaemonRegisteredUsers *user_list = NULL; int i = 0; char tmp_id[DLT_ID_SIZE + 1] = { '\0' }; if ((daemon == NULL) || (daemon_local == NULL) || (id == NULL) || (ecuid == NULL) || (cmp_flag <= DLT_DAEMON_LOGSTORAGE_CMP_MIN) || (cmp_flag >= DLT_DAEMON_LOGSTORAGE_CMP_MAX)) { dlt_vlog(LOG_ERR, "Wrong parameter in function %s\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } user_list = dlt_daemon_find_users_list(daemon, ecuid, verbose); if (user_list == NULL) return DLT_RETURN_ERROR; for (i = 0; i < user_list->num_contexts; i++) { if (cmp_flag == DLT_DAEMON_LOGSTORAGE_CMP_APID) dlt_set_id(tmp_id, user_list->contexts[i].apid); else if (cmp_flag == DLT_DAEMON_LOGSTORAGE_CMP_CTID) dlt_set_id(tmp_id, user_list->contexts[i].ctid); else /* this is for the case when both apid and ctid are wildcard */ dlt_set_id(tmp_id, ".*"); if (strncmp(id, tmp_id, DLT_ID_SIZE) == 0) { if (curr_log_level > 0) dlt_daemon_logstorage_send_log_level(daemon, daemon_local, &user_list->contexts[i], ecuid, curr_log_level, verbose); else /* The request is to reset log levels */ dlt_daemon_logstorage_reset_log_level(daemon, daemon_local, &user_list->contexts[i], ecuid, curr_log_level, verbose); } } return DLT_RETURN_OK; } /** * dlt_logstorage_update_context * * Update log level of a context by updating the daemon internal table * The log levels are reset if current log level provided is -1 (not sent to * application in this case) * Reset and sent to application if current log level provided is 0 * * @param daemon DltDaemon structure * @param daemon_local DltDaemonLocal structure * @param apid application id * @param ctid context id * @param ecuid ecu id * @param curr_log_level log level to be set to context * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ DltReturnValue dlt_logstorage_update_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *apid, char *ctid, char *ecuid, int curr_log_level, int verbose) { DltDaemonContext *context = NULL; if ((daemon == NULL) || (daemon_local == NULL) || (apid == NULL) || (ctid == NULL) || (ecuid == NULL)) { dlt_vlog(LOG_ERR, "Wrong parameter in function %s\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } context = dlt_daemon_context_find(daemon, apid, ctid, ecuid, verbose); if (context != NULL) { if (curr_log_level > 0) return dlt_daemon_logstorage_send_log_level(daemon, daemon_local, context, ecuid, curr_log_level, verbose); else /* The request is to reset log levels */ return dlt_daemon_logstorage_reset_log_level(daemon, daemon_local, context, ecuid, curr_log_level, verbose); } else { if (strncmp(ecuid, daemon->ecuid, DLT_ID_SIZE) != 0) { /* we intentionally have no data provided by passive node. */ /* We blindly send the log level or reset log level */ return dlt_daemon_logstorage_force_reset_level(daemon, daemon_local, apid, ctid, ecuid, curr_log_level, verbose); } else { dlt_vlog(LOG_WARNING, "%s: No information about APID: %s, CTID: %s, ECU: %s\n", __func__, apid, ctid, ecuid); return DLT_RETURN_ERROR; } } return DLT_RETURN_OK; } /** * dlt_logstorage_update_context_loglevel * * Update all contexts or particular context depending provided key * * @param daemon Pointer to DLT Daemon structure * @param daemon_local Pointer to DLT Daemon Local structure * @param key Filter key stored in Hash Map * @param curr_log_level log level to be set to context * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ DltReturnValue dlt_logstorage_update_context_loglevel(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *key, int curr_log_level, int verbose) { int cmp_flag = 0; char apid[DLT_ID_SIZE + 1] = { '\0' }; char ctid[DLT_ID_SIZE + 1] = { '\0' }; char ecuid[DLT_ID_SIZE + 1] = { '\0' }; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (key == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (dlt_logstorage_split_key(key, apid, ctid, ecuid) != 0) { dlt_log(LOG_ERR, "Error while updating application log levels (split key)\n"); return DLT_RETURN_ERROR; } if (ecuid[0] == '\0') /* ECU id was not specified in filter configuration */ dlt_set_id(ecuid, daemon->ecuid); /* check wildcard for both apid and ctid first of all */ if (strcmp(ctid, ".*") == 0 && strcmp(apid, ".*") == 0) { cmp_flag = DLT_DAEMON_LOGSTORAGE_CMP_ECID; if (dlt_logstorage_update_all_contexts(daemon, daemon_local, apid, curr_log_level, cmp_flag, ecuid, verbose) != 0) return DLT_RETURN_ERROR; } else if (strcmp(ctid, ".*") == 0) { cmp_flag = DLT_DAEMON_LOGSTORAGE_CMP_APID; if (dlt_logstorage_update_all_contexts(daemon, daemon_local, apid, curr_log_level, cmp_flag, ecuid, verbose) != 0) return DLT_RETURN_ERROR; } /* wildcard for application id, find all contexts with context id */ else if (strcmp(apid, ".*") == 0) { cmp_flag = DLT_DAEMON_LOGSTORAGE_CMP_CTID; if (dlt_logstorage_update_all_contexts(daemon, daemon_local, ctid, curr_log_level, cmp_flag, ecuid, verbose) != 0) return DLT_RETURN_ERROR; } /* In case of given application id, context id pair, call available context * find function */ else if (dlt_logstorage_update_context(daemon, daemon_local, apid, ctid, ecuid, curr_log_level, verbose) != 0) { return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } /** * dlt_daemon_logstorage_reset_application_loglevel * * Reset storage log level of all running applications * 2 steps for resetting * 1. Setup storage_loglevel of all contexts configured for the requested device * to -1 * 2. Re-run update log level for all other configured devices * * @param daemon Pointer to DLT Daemon structure * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param max_device Maximum storage devices setup by the daemon * @param verbose If set to true verbose information is printed out */ void dlt_daemon_logstorage_reset_application_loglevel(DltDaemon *daemon, DltDaemonLocal *daemon_local, int dev_num, int max_device, int verbose) { DltLogStorage *handle = NULL; DltLogStorageFilterList **tmp = NULL; int i = 0; char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { '\0' }; unsigned int status; int log_level = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (daemon->storage_handle == NULL) || (dev_num < 0)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return; } handle = &(daemon->storage_handle[dev_num]); if ((handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) return; /* for all filters (keys) check if application context are already running * and log level need to be reset*/ tmp = &(handle->config_list); while (*(tmp) != NULL) { for (i = 0; i < (*tmp)->num_keys; i++) { memset(key, 0, sizeof(key)); strncpy(key, ((*tmp)->key_list + (i * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); /* dlt-daemon wants to reset loglevel if * a logstorage device is disconnected. */ log_level = DLT_DAEMON_LOGSTORAGE_RESET_LOGLEVEL; dlt_logstorage_update_context_loglevel( daemon, daemon_local, key, log_level, verbose); } tmp = &(*tmp)->next; } /* Re-run update log level for all other configured devices */ for (i = 0; i < max_device; i++) { status = daemon->storage_handle[i].config_status; if (i == dev_num) continue; if (status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) dlt_daemon_logstorage_update_application_loglevel(daemon, daemon_local, i, verbose); } return; } /** * dlt_daemon_logstorage_update_application_loglevel * * Update log level of all running applications with new filter configuration * available due to newly attached DltLogstorage device. The log level is only * updated when the current application log level is less than the log level * obtained from the storage configuration file * * @param daemon Pointer to DLT Daemon structure * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param verbose If set to true verbose information is printed out */ void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, DltDaemonLocal *daemon_local, int dev_num, int verbose) { DltLogStorage *handle = NULL; DltLogStorageFilterList **tmp = NULL; char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { '\0' }; int i = 0; int log_level = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (dev_num < 0)) { dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__); return; } handle = &(daemon->storage_handle[dev_num]); if ((handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) return; /* for all filters (keys) check if application or context already running * and log level need to be updated*/ tmp = &(handle->config_list); while (*(tmp) != NULL) { for (i = 0; i < (*tmp)->num_keys; i++) { memset(key, 0, sizeof(key)); strncpy(key, ((*tmp)->key_list + (i * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); /* Obtain storage configuration data */ log_level = dlt_logstorage_get_loglevel_by_key(handle, key); if (log_level < 0) { dlt_log(LOG_ERR, "Failed to get log level by key \n"); return; } /* Update context log level with storage configuration log level */ dlt_logstorage_update_context_loglevel(daemon, daemon_local, key, log_level, verbose); } tmp = &(*tmp)->next; } return; } /** * dlt_daemon_logstorage_get_loglevel * * Obtain log level as a union of all configured storage devices and filters for * the provided application id and context id * * @param daemon Pointer to DLT Daemon structure * @param max_device Maximum storage devices setup by the daemon * @param apid Application ID * @param ctid Context ID * @return Log level on success, -1 on error */ int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, int max_device, char *apid, char *ctid) { DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; int i = 0; int j = 0; int8_t storage_loglevel = -1; int8_t configured_loglevel = -1; int num_config = 0; if ((daemon == NULL) || (max_device == 0) || (apid == NULL) || (ctid == NULL)) return DLT_RETURN_WRONG_PARAMETER; for (i = 0; i < max_device; i++) if (daemon->storage_handle[i].config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { num_config = dlt_logstorage_get_config(&(daemon->storage_handle[i]), config, apid, ctid, daemon->ecuid); if (num_config == 0) { dlt_log(LOG_DEBUG, "No valid filter configuration found\n"); continue; } for (j = 0; j < num_config; j++) { if (config[j] == NULL) continue; /* If logstorage configuration do not contain file name, * then it is non verbose control filter, so return level as in this filter */ if (config[j]->file_name == NULL) { storage_loglevel = config[j]->log_level; break; } configured_loglevel = config[j]->log_level; storage_loglevel = DLT_OFFLINE_LOGSTORAGE_MAX( configured_loglevel, storage_loglevel); } } return storage_loglevel; } /** * dlt_daemon_logstorage_write * * Write log message to all attached storage device. If the called * dlt_logstorage_write function is not able to write to the device, DltDaemon * will disconnect this device. * * @param daemon Pointer to Dlt Daemon structure * @param user_config DltDaemon configuration * @param data1 message header buffer * @param size1 message header buffer size * @param data2 message extended header buffer * @param size2 message extended header size * @param data3 message data buffer * @param size3 message data size */ void dlt_daemon_logstorage_write(DltDaemon *daemon, DltDaemonFlags *user_config, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3) { int i = 0; DltLogStorageUserConfig file_config; if ((daemon == NULL) || (user_config == NULL) || (user_config->offlineLogstorageMaxDevices <= 0) || (data1 == NULL) || (data2 == NULL) || (data3 == NULL)) { dlt_vlog(LOG_DEBUG, "%s: message type is not LOG. Skip storing.\n", __func__); return; /* Log Level changed callback */ } /* Copy user configuration */ file_config.logfile_timestamp = user_config->offlineLogstorageTimestamp; file_config.logfile_delimiter = user_config->offlineLogstorageDelimiter; file_config.logfile_maxcounter = user_config->offlineLogstorageMaxCounter; file_config.logfile_counteridxlen = user_config->offlineLogstorageMaxCounterIdx; for (i = 0; i < user_config->offlineLogstorageMaxDevices; i++) if (daemon->storage_handle[i].config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { if (dlt_logstorage_write(&(daemon->storage_handle[i]), &file_config, data1, size1, data2, size2, data3, size3) != 0) { dlt_log(LOG_ERR, "dlt_daemon_logstorage_write: failed. " "Disable storage device\n"); /* DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS happened, * therefore remove logstorage device */ dlt_logstorage_device_disconnected( &(daemon->storage_handle[i]), DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); } } } /** * dlt_daemon_logstorage_setup_internal_storage * * Setup user defined path as offline log storage device * * @param daemon Pointer to Dlt Daemon structure * @param daemon_local Pointer to Dlt Daemon local structure * @param path User configured internal storage path * @param verbose If set to true verbose information is printed out * @return 0 on sucess, -1 otherwise */ int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *path, int verbose) { int ret = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((path == NULL) || (daemon == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* connect internal storage device */ /* Device index always used as 0 as it is setup on DLT daemon startup */ ret = dlt_logstorage_device_connected(&(daemon->storage_handle[0]), path); if (ret != 0) { dlt_vlog(LOG_ERR, "%s: Device connect failed\n", __func__); return DLT_RETURN_ERROR; } /* check if log level of running application need an update */ dlt_daemon_logstorage_update_application_loglevel(daemon, daemon_local, 0, verbose); if (daemon->storage_handle[0].maintain_logstorage_loglevel != DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_UNDEF) { daemon->maintain_logstorage_loglevel = daemon->storage_handle[0].maintain_logstorage_loglevel; dlt_vlog(LOG_DEBUG, "[%s] Startup with maintain loglevel: [%d]\n", __func__, daemon->storage_handle[0].maintain_logstorage_loglevel); } return ret; } void dlt_daemon_logstorage_set_logstorage_cache_size(unsigned int size) { /* store given [KB] size in [Bytes] */ g_logstorage_cache_max = size * 1024; } int dlt_daemon_logstorage_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { int i = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (daemon->storage_handle == NULL)) return DLT_RETURN_WRONG_PARAMETER; for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) /* call disconnect on all currently connected devices */ if (daemon->storage_handle[i].connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { (&daemon->storage_handle[i])->uconfig.logfile_counteridxlen = daemon_local->flags.offlineLogstorageMaxCounterIdx; (&daemon->storage_handle[i])->uconfig.logfile_delimiter = daemon_local->flags.offlineLogstorageDelimiter; (&daemon->storage_handle[i])->uconfig.logfile_maxcounter = daemon_local->flags.offlineLogstorageMaxCounter; (&daemon->storage_handle[i])->uconfig.logfile_timestamp = daemon_local->flags.offlineLogstorageTimestamp; dlt_logstorage_device_disconnected( &daemon->storage_handle[i], DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT); } return 0; } int dlt_daemon_logstorage_sync_cache(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *mnt_point, int verbose) { int i = 0; DltLogStorage *handle = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (mnt_point == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (strlen(mnt_point) > 0) { /* mount point is given */ handle = dlt_daemon_logstorage_get_device(daemon, daemon_local, mnt_point, verbose); if (handle == NULL) { return DLT_RETURN_ERROR; } else { handle->uconfig.logfile_counteridxlen = daemon_local->flags.offlineLogstorageMaxCounterIdx; handle->uconfig.logfile_delimiter = daemon_local->flags.offlineLogstorageDelimiter; handle->uconfig.logfile_maxcounter = daemon_local->flags.offlineLogstorageMaxCounter; handle->uconfig.logfile_timestamp = daemon_local->flags.offlineLogstorageTimestamp; if (dlt_logstorage_sync_caches(handle) != 0) return DLT_RETURN_ERROR; } } else { /* sync caches for all connected logstorage devices */ for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) if (daemon->storage_handle[i].connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { daemon->storage_handle[i].uconfig.logfile_counteridxlen = daemon_local->flags.offlineLogstorageMaxCounterIdx; daemon->storage_handle[i].uconfig.logfile_delimiter = daemon_local->flags.offlineLogstorageDelimiter; daemon->storage_handle[i].uconfig.logfile_maxcounter = daemon_local->flags.offlineLogstorageMaxCounter; daemon->storage_handle[i].uconfig.logfile_timestamp = daemon_local->flags.offlineLogstorageTimestamp; if (dlt_logstorage_sync_caches(&daemon->storage_handle[i]) != 0) return DLT_RETURN_ERROR; } } return 0; } DltLogStorage *dlt_daemon_logstorage_get_device(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *mnt_point, int verbose) { int i = 0; int len = 0; int len1 = 0; int len2 = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL) || (mnt_point == NULL)) return NULL; len1 = strlen(mnt_point); for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) { len2 = strlen(daemon->storage_handle[i].device_mount_point); /* Check if the requested device path is already used as log storage * device. Check for strlen first, to avoid comparison errors when * final '/' is given or not */ len = len1 > len2 ? len2 : len1; if (strncmp(daemon->storage_handle[i].device_mount_point, mnt_point, len) == 0) return &daemon->storage_handle[i]; } return NULL; } dlt-daemon-2.18.10/src/daemon/dlt_daemon_offline_logstorage.h000066400000000000000000000222221446635226000241600ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * * \file: dlt_daemon_offline_logstorage.h * For further information see http://www.covesa.org/. */ /******************************************************************************* * ** * SRC-MODULE: dlt_daemon_offline_logstorage.h ** * ** * TARGET : linux ** * ** * PROJECT : DLT ** * ** * AUTHOR : Syed Hameed shameed@jp.adit-jv.com ** * Christoph Lipka clipka@jp.adit-jv.com ** * PURPOSE : ** * ** * REMARKS : ** * ** * PLATFORM DEPENDANT [yes/no]: yes ** * ** * TO BE CHANGED BY USER [yes/no]: no ** * ** ******************************************************************************/ /******************************************************************************* * Author Identity ** ******************************************************************************* * ** * Initials Name Company ** * -------- ------------------------- ---------------------------------- ** * sh Syed Hameed ADIT ** * cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef DLT_DAEMON_OFFLINE_LOGSTORAGE_H #define DLT_DAEMON_OFFLINE_LOGSTORAGE_H #include "dlt-daemon.h" #include "dlt_daemon_common.h" #include "dlt_offline_logstorage.h" #define DLT_DAEMON_LOGSTORAGE_RESET_LOGLEVEL -1 #define DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL 0 typedef enum { DLT_DAEMON_LOGSTORAGE_CMP_MIN = 0, DLT_DAEMON_LOGSTORAGE_CMP_APID = 1, DLT_DAEMON_LOGSTORAGE_CMP_CTID = 2, DLT_DAEMON_LOGSTORAGE_CMP_ECID = 3, DLT_DAEMON_LOGSTORAGE_CMP_MAX, } DltCompareFlags; /** * dlt_daemon_logstorage_get_loglevel * * Obtain log level as a union of all configured storage devices and filters for * the provided application id and context id * * @param daemon Pointer to DLT Daemon structure * @param max_device Maximum storage devices setup by the daemon * @param apid Application ID * @param ctid Context ID * @return Log level on success, -1 on error */ int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, int max_device, char *apid, char *ctid); /** * dlt_daemon_logstorage_reset_application_loglevel * * Reset storage log level of all running applications with -1 * * @param daemon Pointer to DLT Daemon structure * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param verbose If set to true verbose information is printed out */ void dlt_daemon_logstorage_reset_application_loglevel(DltDaemon *daemon, DltDaemonLocal *daemon_local, int dev_num, int max_device, int verbose); /** * dlt_daemon_logstorage_update_application_loglevel * * Update log level of all running applications with new filter configuration * available due to newly attached DltLogstorage device. The log level is only * updated when the current application log level is less than the log level * obtained from the storage configuration file. * * @param daemon Pointer to DLT Daemon structure * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param verbose if set to true verbose information is printed out */ void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, DltDaemonLocal *daemon_local, int dev_num, int verbose); /** * dlt_daemon_logstorage_write * * Write log message to all attached storage device. If the called * dlt_logstorage_write function is not able to write to the device, * DltDaemon will disconnect this device. * * @param daemon Pointer to Dlt Daemon structure * @param user_config DltDaemon configuration * @param data1 message header buffer * @param size1 message header buffer size * @param data2 message extended data buffer * @param size2 message extended data size * @param data3 message data buffer * @param size3 message data size */ void dlt_daemon_logstorage_write(DltDaemon *daemon, DltDaemonFlags *user_config, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3); /** * dlt_daemon_logstorage_setup_internal_storage * * Setup user defined path as offline log storage device * * @param daemon Pointer to Dlt Daemon structure * @param daemon_local Pointer to Dlt Daemon Local structure * @param path User configured internal storage path * @param verbose If set to true verbose information is printed out */ int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *path, int verbose); /** * Set max size of logstorage cache. Stored internally in bytes * * @param size Size of logstorage cache [in KB] */ void dlt_daemon_logstorage_set_logstorage_cache_size(unsigned int size); /** * Cleanup dlt logstorage * * @param daemon Pointer to Dlt Daemon structure * @param daemon_local Pointer to Dlt Daemon Local structure * @param verbose If set to true verbose information is printed out */ int dlt_daemon_logstorage_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); /** * Sync logstorage caches * * @param daemon Pointer to Dlt Daemon structure * @param daemon_local Pointer to Dlt Daemon Local structure * @param mnt_point Logstorage device mount point * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 otherwise */ int dlt_daemon_logstorage_sync_cache(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *mnt_point, int verbose); /** * dlt_logstorage_get_device * * Get a Logstorage device handle for given the mount point. * * @param daemon Pointer to Dlt Daemon structure * @param daemon_local Pointer to Dlt Daemon Local structure * @param mnt_point Logstorage device mount point * @param verbose If set to true verbose information is printed out * @return handle to Logstorage device on success, NULL otherwise */ DltLogStorage *dlt_daemon_logstorage_get_device(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *mnt_point, int verbose); #endif /* DLT_DAEMON_OFFLINE_LOGSTORAGE_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_offline_logstorage_internal.h000066400000000000000000000105021446635226000260520ustar00rootroot00000000000000/** * Copyright (C) 2018 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality internal header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Aditya Paluri ADIT 2018 * * \file: dlt_daemon_offline_logstorage_internal.h * For further information see http://www.covesa.org/. */ /******************************************************************************* * ** * SRC-MODULE: dlt_daemon_offline_logstorage_internal.h ** * ** * TARGET : linux ** * ** * PROJECT : DLT ** * ** * AUTHOR : Aditya Paluri venkataaditya.paluri@in.bosch.com ** * PURPOSE : ** * ** * REMARKS : ** * ** * PLATFORM DEPENDANT [yes/no]: yes ** * ** * TO BE CHANGED BY USER [yes/no]: no ** * ** ******************************************************************************/ /******************************************************************************* * Author Identity ** ******************************************************************************* * ** * Initials Name Company ** * -------- ------------------------- ---------------------------------- ** * ap Aditya Paluri ADIT ** *******************************************************************************/ #ifndef DLT_DAEMON_OFFLINE_LOGSTORAGE_INTERNAL_H #define DLT_DAEMON_OFFLINE_LOGSTORAGE_INTERNAL_H DLT_STATIC DltReturnValue dlt_logstorage_split_key(char *key, char *apid, char *ctid, char *ecuid); DltReturnValue dlt_logstorage_update_all_contexts(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *id, int curr_log_level, int cmp_flag, char *ecuid, int verbose); DltReturnValue dlt_logstorage_update_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *apid, char *ctid, char *ecuid, int curr_log_level, int verbose); DltReturnValue dlt_logstorage_update_context_loglevel(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *key, int curr_log_level, int verbose); #endif dlt-daemon-2.18.10/src/daemon/dlt_daemon_serial.c000066400000000000000000000074561446635226000215760ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_serial.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_serial.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include #include #include #include #include /* send() */ #include "dlt-daemon.h" #include "dlt_types.h" #include "dlt_daemon_serial.h" int dlt_daemon_serial_send(int sock, void *data1, int size1, void *data2, int size2, char serialheader) { /* Optional: Send serial header, if requested */ if (serialheader) { if (0 > write(sock, dltSerialHeader, sizeof(dltSerialHeader))) { return DLT_DAEMON_ERROR_SEND_FAILED; } } /* Send data */ if (data1 && (size1 > 0)) { if (0 > write(sock, data1, size1)) { return DLT_DAEMON_ERROR_SEND_FAILED; } } if (data2 && (size2 > 0)) { if (0 > write(sock, data2, size2)) { return DLT_DAEMON_ERROR_SEND_FAILED; } } return DLT_DAEMON_ERROR_OK; } dlt-daemon-2.18.10/src/daemon/dlt_daemon_serial.h000066400000000000000000000063101446635226000215670ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_serial.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_serial.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #ifndef DLT_DAEMON_SERIAL_H #define DLT_DAEMON_SERIAL_H #include #include #include "dlt_common.h" #include "dlt_user.h" int dlt_daemon_serial_send(int sock, void *data1, int size1, void *data2, int size2, char serialheader); #endif /* DLT_DAEMON_SERIAL_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_socket.c000066400000000000000000000142361446635226000216010ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_socket.c */ #include #include #include /* for printf() and fprintf() */ #include /* for socket(), connect(), (), and recv() */ #include /* for sockaddr_in and inet_addr() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include #include #include #include #include #ifdef linux #include #endif #include #if defined(linux) && defined(__NR_statx) #include #endif #include "dlt_types.h" #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common_cfg.h" #include "dlt_daemon_socket.h" int dlt_daemon_socket_open(int *sock, unsigned int servPort, char *ip) { int yes = 1; int ret_inet_pton = 1; int lastErrno = 0; #ifdef DLT_USE_IPv6 /* create socket */ if ((*sock = socket(AF_INET6, SOCK_STREAM, 0)) == -1) { lastErrno = errno; dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno, strerror(lastErrno)); return -1; } #else if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { lastErrno = errno; dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno, strerror(lastErrno)); return -1; } #endif dlt_vlog(LOG_INFO, "%s: Socket created\n", __FUNCTION__); /* setsockpt SO_REUSEADDR */ if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { lastErrno = errno; dlt_vlog( LOG_ERR, "dlt_daemon_socket_open: Setsockopt error %d in dlt_daemon_local_connection_init: %s\n", lastErrno, strerror(lastErrno)); return -1; } /* bind */ #ifdef DLT_USE_IPv6 struct sockaddr_in6 forced_addr; memset(&forced_addr, 0, sizeof(forced_addr)); forced_addr.sin6_family = AF_INET6; forced_addr.sin6_port = htons(servPort); if (0 == strcmp(ip, "0.0.0.0")) { forced_addr.sin6_addr = in6addr_any; } else { ret_inet_pton = inet_pton(AF_INET6, ip, &forced_addr.sin6_addr); } #else struct sockaddr_in forced_addr; memset(&forced_addr, 0, sizeof(forced_addr)); forced_addr.sin_family = AF_INET; forced_addr.sin_port = htons(servPort); ret_inet_pton = inet_pton(AF_INET, ip, &forced_addr.sin_addr); #endif /* inet_pton returns 1 on success */ if (ret_inet_pton != 1) { lastErrno = errno; dlt_vlog( LOG_WARNING, "dlt_daemon_socket_open: inet_pton() error %d: %s. Cannot convert IP address: %s\n", lastErrno, strerror(lastErrno), ip); return -1; } if (bind(*sock, (struct sockaddr *)&forced_addr, sizeof(forced_addr)) == -1) { lastErrno = errno; /*close() may set errno too */ close(*sock); dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: bind() error %d: %s\n", lastErrno, strerror(lastErrno)); return -1; } /*listen */ dlt_vlog(LOG_INFO, "%s: Listening on ip %s and port: %u\n", __FUNCTION__, ip, servPort); /* get socket buffer size */ dlt_vlog(LOG_INFO, "dlt_daemon_socket_open: Socket send queue size: %d\n", dlt_daemon_socket_get_send_qeue_max_size(*sock)); if (listen(*sock, 3) < 0) { lastErrno = errno; dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: listen() failed with error %d: %s\n", lastErrno, strerror(lastErrno)); return -1; } return 0; /* OK */ } int dlt_daemon_socket_close(int sock) { close(sock); return 0; } int dlt_daemon_socket_send(int sock, void *data1, int size1, void *data2, int size2, char serialheader) { int ret = DLT_RETURN_OK; /* Optional: Send serial header, if requested */ if (serialheader) { ret = dlt_daemon_socket_sendreliable(sock, (void *)dltSerialHeader, sizeof(dltSerialHeader)); if (ret != DLT_RETURN_OK) { return ret; } } /* Send data */ if ((data1 != NULL) && (size1 > 0)) { ret = dlt_daemon_socket_sendreliable(sock, data1, size1); if (ret != DLT_RETURN_OK) { return ret; } } if ((data2 != NULL) && (size2 > 0)) { ret = dlt_daemon_socket_sendreliable(sock, data2, size2); } return ret; } int dlt_daemon_socket_get_send_qeue_max_size(int sock) { int n = 0; socklen_t m = sizeof(n); getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&n, &m); return n; } int dlt_daemon_socket_sendreliable(int sock, void *data_buffer, int message_size) { int data_sent = 0; while (data_sent < message_size) { ssize_t ret = send(sock, (uint8_t *)data_buffer + data_sent, message_size - data_sent, 0); if (ret < 0) { dlt_vlog(LOG_WARNING, "%s: socket send failed [errno: %d]!\n", __func__, errno); return DLT_DAEMON_ERROR_SEND_FAILED; } else { data_sent += ret; } } return DLT_DAEMON_ERROR_OK; } dlt-daemon-2.18.10/src/daemon/dlt_daemon_socket.h000066400000000000000000000073461446635226000216120ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_socket.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_socket.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #ifndef DLT_DAEMON_SOCKET_H #define DLT_DAEMON_SOCKET_H #include #include #include "dlt_common.h" #include "dlt_user.h" int dlt_daemon_socket_open(int *sock, unsigned int servPort, char *ip); int dlt_daemon_socket_close(int sock); int dlt_daemon_socket_get_send_qeue_max_size(int sock); int dlt_daemon_socket_send(int sock, void *data1, int size1, void *data2, int size2, char serialheader); /** * @brief dlt_daemon_socket_sendreliable - sends data to socket with additional checks and resending functionality - trying to be reliable * @param sock * @param data_buffer * @param message_size * @return on sucess: DLT_DAEMON_ERROR_OK, on error: DLT_DAEMON_ERROR_SEND_FAILED */ int dlt_daemon_socket_sendreliable(int sock, void *data_buffer, int message_size); #endif /* DLT_DAEMON_SOCKET_H */ dlt-daemon-2.18.10/src/daemon/dlt_daemon_unix_socket.c000066400000000000000000000123051446635226000226370ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015, Advanced Driver Information Technology * Copyright of Advanced Driver Information Technology, Bosch and Denso * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Christoph Lipka * * \copyright Copyright © 2015 ADIT. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_unix_socket.c */ #include #include #include #include #if defined(ANDROID) # include /* for android_get_control_socket() */ # include /* for basename() */ #else # include /* for socket(), connect(), (), and recv() */ #endif #include #include #include #include #if DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE #include #endif #include "dlt-daemon.h" #include "dlt_common.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_socket.h" #include "dlt_daemon_unix_socket.h" #ifdef ANDROID DltReturnValue dlt_daemon_unix_android_get_socket(int *sock, const char *sock_path) { DltReturnValue ret = DLT_RETURN_OK; if ((sock == NULL) || (sock_path == NULL)) { dlt_log(LOG_ERR, "dlt_daemon_unix_android_get_socket: arguments invalid"); ret = DLT_RETURN_WRONG_PARAMETER; } else { const char* sock_name = basename(sock_path); if (sock_name == NULL) { dlt_log(LOG_WARNING, "dlt_daemon_unix_android_get_socket: can't get socket name from its path"); ret = DLT_RETURN_ERROR; } else { *sock = android_get_control_socket(sock_name); if (*sock < 0) { dlt_log(LOG_WARNING, "dlt_daemon_unix_android_get_socket: can get socket from init"); ret = DLT_RETURN_ERROR; } else { if (listen(*sock, 1) == -1) { dlt_vlog(LOG_WARNING, "unix socket: listen error: %s", strerror(errno)); ret = DLT_RETURN_ERROR; } } } } return ret; } #endif int dlt_daemon_unix_socket_open(int *sock, char *sock_path, int type, int mask) { struct sockaddr_un addr; int old_mask; if ((sock == NULL) || (sock_path == NULL)) { dlt_log(LOG_ERR, "dlt_daemon_unix_socket_open: arguments invalid"); return -1; } #ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE char **names = NULL; const int num_fds = sd_listen_fds_with_names(0, &names); bool sd_socket_open = false; int i; if (num_fds <= 0) { dlt_vlog(LOG_WARNING, "unix socket: no sockets configured via systemd, error: %s\n", strerror(errno)); } else { for (i = 0; i < num_fds; ++i) { if (strcmp(sock_path, names[i]) != 0) { continue; } if (sd_is_socket_unix(i + SD_LISTEN_FDS_START, type, 1, names[i], strlen(names[i])) < 0) { dlt_vlog(LOG_WARNING, "unix socket: socket with matching name is not of correct type or not in listen mode, error: %s\n", strerror(errno)); continue; } *sock = i + SD_LISTEN_FDS_START; sd_socket_open = true; dlt_vlog(LOG_INFO, "unix socket: sock_path %s found systemd socket %s\n", sock_path, names[i]); break; } /* * The caller [of sd_listen_fds_with_names] needs to free the array * itself and each of its elements with libc's free() call after use. * */ for (i = 0; i < num_fds; ++i) { free(names[i]); } free(names); } if (!sd_socket_open) { dlt_vlog(LOG_INFO, "unix socket: sock_path %s no systemd socket found\n", sock_path); #endif if ((*sock = socket(AF_UNIX, type, 0)) == -1) { dlt_log(LOG_WARNING, "unix socket: socket() error"); return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; memcpy(addr.sun_path, sock_path, sizeof(addr.sun_path)); unlink(sock_path); /* set appropriate access permissions */ old_mask = umask(mask); if (bind(*sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { dlt_vlog(LOG_WARNING, "%s: bind() error (%s)\n", __func__, strerror(errno)); return -1; } if (listen(*sock, 1) == -1) { dlt_vlog(LOG_WARNING, "%s: listen error (%s)\n", __func__, strerror(errno)); return -1; } /* restore permissions */ umask(old_mask); #ifdef DLT_SYSTEM_SOCKET_ACTIVATION_ENABLE } // end of: if (!sd_socket_open) { #endif return 0; } int dlt_daemon_unix_socket_close(int sock) { int ret = close(sock); if (ret != 0) { dlt_vlog(LOG_WARNING, "unix socket close failed: %s", strerror(errno)); } return ret; } dlt-daemon-2.18.10/src/daemon/dlt_daemon_unix_socket.h000066400000000000000000000063231446635226000226470ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015, Advanced Driver Information Technology * Copyright of Advanced Driver Information Technology, Bosch and Denso. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Christoph Lipka * * \copyright Copyright © 2015 ADIT. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_unix_socket.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_daemon_unix_socket.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef DLT_DAEMON_UNIX_SOCKET_H #define DLT_DAEMON_UNIX_SOCKET_H #ifdef ANDROID DltReturnValue dlt_daemon_unix_android_get_socket(int *sock, const char *sock_path); #endif int dlt_daemon_unix_socket_open(int *sock, char *socket_path, int type, int mask); int dlt_daemon_unix_socket_close(int sock); #endif /* DLT_DAEMON_UNIX_SOCKET_H */ dlt-daemon-2.18.10/src/daemon/udp_connection/000077500000000000000000000000001446635226000207605ustar00rootroot00000000000000dlt-daemon-2.18.10/src/daemon/udp_connection/dlt_daemon_udp_common_socket.h000066400000000000000000000037351446635226000270370ustar00rootroot00000000000000/* * Copyright (c) 2019 LG Electronics Inc. * SPDX-License-Identifier: MPL-2.0 * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Guruprasad KN * Sachin Sudhakar Shetty * Sunil Kovila Sampath * * \copyright Copyright (c) 2019 LG Electronics Inc. * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_udp_common_socket.h */ #ifndef DLT_DAEMON_UDP_COMMON_SOCKET_H #define DLT_DAEMON_UDP_COMMON_SOCKET_H #include /* for sockaddr_in and inet_addr() */ #include #include #include #include #include /* for atoi() and exit() */ #include /* for memset() */ #include #include /* for socket(), connect(), (), and recv() */ #include /* for close() */ #include "dlt_common.h" #include "dlt-daemon.h" #include "dlt_daemon_udp_socket.h" #include "dlt_types.h" /* #define variables */ #define ADDRESS_VALID 1 #define ADDRESS_INVALID 0 #define SOCKPORT_MAX_LEN 6 /* port range 0-65535 */ #define SYSTEM_CALL_ERROR -1 #define ZERO_BYTE_RECIEVED 0 #define ONE_BYTE_RECIEVED 0 typedef struct sockaddr_storage CLIENT_ADDR_STRUCT; typedef socklen_t CLIENT_ADDR_STRUCT_SIZE; /* udp strutures */ typedef struct { CLIENT_ADDR_STRUCT clientaddr; CLIENT_ADDR_STRUCT_SIZE clientaddr_size; int isvalidflag; } DltDaemonClientSockInfo; /* Function prototype declaration */ void dlt_daemon_udp_init_clientstruct(DltDaemonClientSockInfo *clientinfo_struct); DltReturnValue dlt_daemon_udp_socket_open(int *sock, unsigned int servPort); void dlt_daemon_udp_setmulticast_addr(DltDaemonLocal *daemon_local); #endif /* DLT_DAEMON_UDP_COMMON_SOCKET_H */ dlt-daemon-2.18.10/src/daemon/udp_connection/dlt_daemon_udp_socket.c000066400000000000000000000240411446635226000254530ustar00rootroot00000000000000/* * Copyright (c) 2019 LG Electronics Inc. * SPDX-License-Identifier: MPL-2.0 * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Guruprasad KN * Sachin Sudhakar Shetty * Sunil Kovila Sampath * * \copyright Copyright (c) 2019 LG Electronics Inc. * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_udp_socket.c */ #include "dlt_daemon_udp_common_socket.h" static void dlt_daemon_udp_clientmsg_send(DltDaemonClientSockInfo *clientinfo, void *data1, int size1, void *data2, int size2, int verbose); static int g_udp_sock_fd = -1; static DltDaemonClientSockInfo g_udpmulticast_addr; /* ************************************************************************** */ /* Function : dlt_daemon_udp_init_clientstruct */ /* In Param : UDP client_info struct to be initilzed */ /* Out Param : NIL */ /* Description: client struct to be initilized to copy control/connect/disconnect */ /* client addr */ /* ************************************************************************** */ void dlt_daemon_udp_init_clientstruct(DltDaemonClientSockInfo *clientinfo_struct) { if (clientinfo_struct == NULL) { dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); return; } memset(&clientinfo_struct->clientaddr, 0x00, sizeof(clientinfo_struct->clientaddr)); clientinfo_struct->clientaddr_size = sizeof(clientinfo_struct->clientaddr); clientinfo_struct->isvalidflag = ADDRESS_INVALID; /* info is invalid */ dlt_vlog(LOG_DEBUG, "%s: client addr struct init success \n", __func__); } /* ************************************************************************** */ /* Function : dlt_daemon_udp_setmulticast_addr */ /* In Param : NIL */ /* Out Param : NIL */ /* Description: set the multicast addr to global variables */ /* ************************************************************************** */ void dlt_daemon_udp_setmulticast_addr(DltDaemonLocal *daemon_local) { if (daemon_local == NULL) { dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); return; } dlt_daemon_udp_init_clientstruct(&g_udpmulticast_addr); struct sockaddr_in clientaddr; clientaddr.sin_family = AF_INET; inet_pton(AF_INET, daemon_local->UDPMulticastIPAddress, &clientaddr.sin_addr); clientaddr.sin_port = htons(daemon_local->UDPMulticastIPPort); memcpy(&g_udpmulticast_addr.clientaddr, &clientaddr, sizeof(struct sockaddr_in)); g_udpmulticast_addr.clientaddr_size = sizeof(g_udpmulticast_addr.clientaddr); g_udpmulticast_addr.isvalidflag = ADDRESS_VALID; } /* ************************************************************************** */ /* Function : dlt_daemon_udp_connection_setup */ /* In Param : contains daemon param values used globally */ /* Out Param : status of udp connection setup and fd registration */ /* Description: DataGram socket fd connection is setup */ /* ************************************************************************** */ DltReturnValue dlt_daemon_udp_connection_setup(DltDaemonLocal *daemon_local) { int fd = DLT_FD_INIT; DltReturnValue ret_val = DLT_RETURN_WRONG_PARAMETER; if (daemon_local == NULL) return ret_val; if ((ret_val = dlt_daemon_udp_socket_open(&fd, daemon_local->flags.port)) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Could not initialize udp socket.\n"); } else { /* assign to global udp fd */ g_udp_sock_fd = fd; /* set global multicast addr */ dlt_daemon_udp_setmulticast_addr(daemon_local); dlt_log(LOG_DEBUG, "initialize udp socket success\n"); } return ret_val; } /* ************************************************************************** */ /* Function : dlt_daemon_udp_socket_open */ /* In Param : contains udp port number */ /* Out Param : status of udp connection setup */ /* Description: This funtion is used to setup DGRAM connection */ /* does socket()->bind() on udp port */ /* ************************************************************************** */ DltReturnValue dlt_daemon_udp_socket_open(int *sock, unsigned int servPort) { int enable_reuse_addr = 1; int sockbuffer = DLT_DAEMON_RCVBUFSIZESOCK; char portnumbuffer[SOCKPORT_MAX_LEN] = { 0 }; struct addrinfo hints; struct addrinfo *servinfo = NULL; struct addrinfo *addrinfo_iterator = NULL; int getaddrinfo_errorcode = -1; if (sock == NULL) return DLT_RETURN_WRONG_PARAMETER; memset(&hints, 0, sizeof hints); #ifdef DLT_USE_IPv6 hints.ai_family = AF_INET6; /* force IPv6 - will still work with IPv4 */ #else hints.ai_family = AF_INET; #endif hints.ai_socktype = SOCK_DGRAM;/* UDP Connection */ hints.ai_flags = AI_PASSIVE; /* use my IP address */ snprintf(portnumbuffer, SOCKPORT_MAX_LEN, "%d", servPort); if ((getaddrinfo_errorcode = getaddrinfo(NULL, portnumbuffer, &hints, &servinfo)) != 0) { dlt_vlog(LOG_WARNING, "[%s:%d] getaddrinfo: %s\n", __func__, __LINE__, gai_strerror(getaddrinfo_errorcode)); return DLT_RETURN_ERROR; } for (addrinfo_iterator = servinfo; addrinfo_iterator != NULL; addrinfo_iterator = addrinfo_iterator->ai_next) { if ((*sock = socket(addrinfo_iterator->ai_family, addrinfo_iterator->ai_socktype, addrinfo_iterator->ai_protocol)) == SYSTEM_CALL_ERROR) { dlt_log(LOG_WARNING, "socket() error\n"); continue; } dlt_vlog(LOG_INFO, "[%s:%d] Socket created - socket_family:%i socket_type:%i, protocol:%i\n", __func__, __LINE__, addrinfo_iterator->ai_family, addrinfo_iterator->ai_socktype, addrinfo_iterator->ai_protocol); if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &enable_reuse_addr, sizeof(enable_reuse_addr)) == SYSTEM_CALL_ERROR) { dlt_vlog(LOG_WARNING, "[%s:%d] Setsockopt error %s\n", __func__, __LINE__, strerror(errno)); close(*sock); continue; } if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUF, &sockbuffer, sizeof(sockbuffer)) == SYSTEM_CALL_ERROR) { dlt_vlog(LOG_WARNING, "[%s:%d] Setsockopt error %s\n", __func__, __LINE__, strerror(errno)); close(*sock); continue; } if (bind(*sock, addrinfo_iterator->ai_addr, addrinfo_iterator->ai_addrlen) == SYSTEM_CALL_ERROR) { close(*sock); dlt_log(LOG_WARNING, "bind() error\n"); continue; } break; } if (addrinfo_iterator == NULL) { dlt_log(LOG_WARNING, "failed to bind socket\n"); return DLT_RETURN_ERROR; } freeaddrinfo(servinfo); return DLT_RETURN_OK; /* OK */ } /* ************************************************************************** */ /* Function : dlt_daemon_udp_dltmsg_multicast */ /* In Param : data bytes in dlt format */ /* Out Param : NIL */ /* Description: multicast UDP dlt-message packets to dlt-client */ /* ************************************************************************** */ void dlt_daemon_udp_dltmsg_multicast(void *data1, int size1, void *data2, int size2, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); /* * When UDP Buffer is implemented then data2 would be expected to be NULL * as the data comes from buffer directly. In that case data2 should * not be checked for NULL */ if ((data1 == NULL) || (data2 == NULL)) { dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); return; } dlt_daemon_udp_clientmsg_send(&g_udpmulticast_addr, data1, size1, data2, size2, verbose); } /* ************************************************************************** */ /* Function : dlt_daemon_udp_clientmsg_send */ /* In Param : data bytes & respective size in dlt format */ /* Out Param : NIL */ /* Description: common interface to send data via UDP protocol */ /* ************************************************************************** */ void dlt_daemon_udp_clientmsg_send(DltDaemonClientSockInfo *clientinfo, void *data1, int size1, void *data2, int size2, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((clientinfo->isvalidflag == ADDRESS_VALID) && (size1 > 0) && (size2 > 0)) { void *data = (void *)calloc(size1 + size2, sizeof(char)); if (data == NULL) { dlt_vlog(LOG_ERR, "%s: calloc failure\n", __func__); return; } memcpy(data, data1, size1); memcpy(data + size1, data2, size2); if (sendto(g_udp_sock_fd, data, size1 + size2, 0, (struct sockaddr *)&clientinfo->clientaddr, clientinfo->clientaddr_size) < 0) dlt_vlog(LOG_ERR, "%s: Send UDP Packet Data failed\n", __func__); free(data); data = NULL; } else { if (clientinfo->isvalidflag != ADDRESS_VALID) dlt_vlog(LOG_ERR, "%s: clientinfo->isvalidflag != ADDRESS_VALID %d\n", __func__, clientinfo->isvalidflag); if (size1 <= 0) dlt_vlog(LOG_ERR, "%s: size1 <= 0\n", __func__); if (size2 <= 0) dlt_vlog(LOG_ERR, "%s: size2 <= 0\n", __func__); } } /* ************************************************************************** */ /* Function : dlt_daemon_udp_close_connection */ /* In Param : NIL */ /* Out Param : NIL */ /* Description: Closes UDP Connection */ /* ************************************************************************** */ void dlt_daemon_udp_close_connection(void) { if (close(g_udp_sock_fd) == SYSTEM_CALL_ERROR) dlt_vlog(LOG_WARNING, "[%s:%d] close error %s\n", __func__, __LINE__, strerror(errno)); } dlt-daemon-2.18.10/src/daemon/udp_connection/dlt_daemon_udp_socket.h000066400000000000000000000020271446635226000254600ustar00rootroot00000000000000/* * Copyright (c) 2019 LG Electronics Inc. * SPDX-License-Identifier: MPL-2.0 * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Guruprasad KN * Sachin Sudhakar Shetty * Sunil Kovila Sampath * * \copyright Copyright (c) 2019 LG Electronics Inc. * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_udp_socket.h */ #ifndef DLT_DAEMON_UDP_SOCKET_H #define DLT_DAEMON_UDP_SOCKET_H #include "dlt-daemon.h" DltReturnValue dlt_daemon_udp_connection_setup(DltDaemonLocal *daemon_local); void dlt_daemon_udp_dltmsg_multicast(void *data1, int size1, void *data2, int size2, int verbose); void dlt_daemon_udp_close_connection(void); #endif /* DLT_DAEMON_UDP_SOCKET_H */ dlt-daemon-2.18.10/src/dbus/000077500000000000000000000000001446635226000154435ustar00rootroot00000000000000dlt-daemon-2.18.10/src/dbus/CMakeLists.txt000066400000000000000000000016041446635226000202040ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### include_directories( ${PROJECT_SOURCE_DIR}/ ${PROJECT_SOURCE_DIR}/include/dlt ${DBUS_INCLUDE_DIRS} ) set(dlt_dbus_SRCS dlt-dbus.c dlt-dbus-options.c) add_executable(dlt-dbus ${dlt_dbus_SRCS}) target_link_libraries(dlt-dbus dlt ${DBUS_LIBRARIES}) set_target_properties(dlt-dbus PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-dbus RUNTIME DESTINATION bin COMPONENT base) INSTALL(FILES dlt-dbus.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) dlt-daemon-2.18.10/src/dbus/dlt-dbus-options.c000066400000000000000000000156101446635226000210210ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-dbus-options.c */ #include "dlt-dbus.h" #include #include /** * Print information how to use this program. */ void usage(char *prog_name) { char version[255]; dlt_get_version(version, 255); printf("Usage: %s [options]\n", prog_name); printf("Application to forward dbus messages to DLT.\n"); printf("%s\n", version); printf("Options:\n"); printf(" -d Daemonize. Detach from terminal and run in background.\n"); printf(" -c filename Use configuration file. \n"); printf(" -a apid Used application id. \n"); printf(" Default: %s\n", DEFAULT_CONF_FILE); printf(" -b type Used bus type. \n"); printf(" Session = 0, System = 1.\n"); printf(" -h This help message.\n"); } /** * Initialize command line options with default values. */ void init_cli_options(DltDBusCliOptions *options) { options->ConfigurationFileName = DEFAULT_CONF_FILE; options->ApplicationId = 0; options->BusType = 0; options->Daemonize = 0; } /** * Read command line options and set the values in provided structure */ int read_command_line(DltDBusCliOptions *options, int argc, char *argv[]) { init_cli_options(options); int opt; while ((opt = getopt(argc, argv, "c:b:a:hd")) != -1) switch (opt) { case 'd': { options->Daemonize = 1; break; } case 'b': { options->BusType = malloc(strlen(optarg) + 1); MALLOC_ASSERT(options->BusType); strcpy(options->BusType, optarg); /* strcpy uncritical here, because size matches exactly the size to be copied */ break; } case 'a': { options->ApplicationId = malloc(strlen(optarg) + 1); MALLOC_ASSERT(options->ApplicationId); strcpy(options->ApplicationId, optarg); /* strcpy uncritical here, because size matches exactly the size to be copied */ break; } case 'c': { options->ConfigurationFileName = malloc(strlen(optarg) + 1); MALLOC_ASSERT(options->ConfigurationFileName); strcpy(options->ConfigurationFileName, optarg); /* strcpy uncritical here, because size matches exactly the size to be copied */ break; } case 'h': { usage(argv[0]); exit(0); return -1; /*for parasoft */ } default: { fprintf(stderr, "Unknown option '%c'\n", optopt); usage(argv[0]); return -1; } } return 0; } /** * Initialize configuration to default values. */ void init_configuration(DltDBusConfiguration *config) { /* Common */ config->ApplicationId = "IPC0"; /* DBus */ config->DBus.ContextId = "ALL"; config->DBus.BusType = 0; config->DBus.FilterCount = 0; } /** * Read options from the configuration file */ int read_configuration_file(DltDBusConfiguration *config, char *file_name) { FILE *file; char *line, *token, *value, *filter, *pch; int ret = 0; char *filterBegin, *filterEnd; init_configuration(config); file = fopen(file_name, "r"); if (file == NULL) { fprintf(stderr, "dlt-dbus-options, could not open configuration file.\n"); return -1; } line = malloc(MAX_LINE); token = malloc(MAX_LINE); value = malloc(MAX_LINE); filter = malloc(MAX_LINE); MALLOC_ASSERT(line); MALLOC_ASSERT(token); MALLOC_ASSERT(value); MALLOC_ASSERT(filter); while (fgets(line, MAX_LINE, file) != NULL) { token[0] = 0; value[0] = 0; filter[0] = 0; filterBegin = strchr(line, '='); filterEnd = strpbrk (line, "\r\n"); if (filterBegin) { if (filterEnd && (filterEnd > filterBegin)) { strncpy(filter, filterBegin + 1, filterEnd - filterBegin - 1); filter[filterEnd - filterBegin - 1] = 0; } else { strcpy(filter, filterBegin + 1); } } pch = strtok (line, " =\r\n"); while (pch != NULL) { if (pch[0] == '#') break; if (token[0] == 0) { strncpy(token, pch, MAX_LINE - 1); token[MAX_LINE - 1] = 0; } else { strncpy(value, pch, MAX_LINE); value[MAX_LINE - 1] = 0; break; } pch = strtok (NULL, " =\r\n"); } if (token[0] && value[0]) { /* Common */ if (strcmp(token, "ApplicationId") == 0) { config->ApplicationId = malloc(strlen(value) + 1); MALLOC_ASSERT(config->ApplicationId); strcpy(config->ApplicationId, value); /* strcpy unritical here, because size matches exactly the size to be copied */ } /* ContextId */ else if (strcmp(token, "ContextId") == 0) { config->DBus.ContextId = malloc(strlen(value) + 1); MALLOC_ASSERT(config->DBus.ContextId); strcpy(config->DBus.ContextId, value); /* strcpy unritical here, because size matches exactly the size to be copied */ } /* BusType */ else if (strcmp(token, "BusType") == 0) { config->DBus.BusType = malloc(strlen(value) + 1); MALLOC_ASSERT(config->DBus.BusType); strcpy(config->DBus.BusType, value); /* strcpy unritical here, because size matches exactly the size to be copied */ } /* BusType */ else if (strcmp(token, "FilterMatch") == 0) { if (config->DBus.FilterCount < DLT_DBUS_FILTER_MAX) { config->DBus.FilterMatch[config->DBus.FilterCount] = malloc(strlen(filter) + 1); MALLOC_ASSERT(config->DBus.FilterMatch[config->DBus.FilterCount]); strcpy(config->DBus.FilterMatch[config->DBus.FilterCount], filter); config->DBus.FilterCount++; } } } } fclose(file); free(value); free(token); free(filter); free(line); return ret; } dlt-daemon-2.18.10/src/dbus/dlt-dbus.c000066400000000000000000000114541446635226000173320ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-dbus.c */ #include "dlt-dbus.h" #include #include #include #include #include #include #include DLT_DECLARE_CONTEXT(dbusLog) DLT_DECLARE_CONTEXT(dbusContext) static char dbus_message_buffer[DBUS_MAXIMUM_MESSAGE_LENGTH]; static DBusHandlerResult filter_func (DBusConnection *con, DBusMessage *message, void *data) { char **buf; int len_p; UNUSED(con); UNUSED(data); buf = (char **)&dbus_message_buffer; if (!dbus_message_marshal(message, buf, &len_p)) { fprintf (stderr, "Failed to serialize DBus message!\n"); return DBUS_HANDLER_RESULT_HANDLED; } DLT_TRACE_NETWORK_SEGMENTED(dbusContext, DLT_NW_TRACE_IPC, 0, 0, len_p, (void *)*buf); free(*buf); *buf = NULL; if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { DLT_UNREGISTER_CONTEXT (dbusContext); DLT_UNREGISTER_APP (); exit (0); } /* Conceptually we want this to be * DBUS_HANDLER_RESULT_NOT_YET_HANDLED, but this raises * some problems. See bug 1719. */ return DBUS_HANDLER_RESULT_HANDLED; } int main (int argc, char *argv[]) { DltDBusCliOptions options; DltDBusConfiguration config; DBusConnection *connection; DBusError error; DBusBusType type; int num; if (read_command_line(&options, argc, argv) < 0) { fprintf(stderr, "Failed to read command line!\n"); return -1; } if (read_configuration_file(&config, options.ConfigurationFileName) < 0) { fprintf(stderr, "Failed to read configuration file!\n"); return -1; } /* register application */ if (options.ApplicationId) DLT_REGISTER_APP (options.ApplicationId, "DBus Logging"); else DLT_REGISTER_APP (config.ApplicationId, "DBus Logging"); /* register context */ DLT_REGISTER_CONTEXT_LL_TS(dbusContext, config.DBus.ContextId, "DBus Context for Logging", DLT_LOG_INFO, DLT_TRACE_STATUS_ON); DLT_REGISTER_CONTEXT(dbusLog, "Log", "DBus Context for Logging Generic information"); /* initialise error handler */ dbus_error_init (&error); /* set DBus bus type */ if (options.BusType) type = (DBusBusType)atoi(options.BusType); else type = (DBusBusType)atoi(config.DBus.BusType); /* get connection */ connection = dbus_bus_get (type, &error); if (type == 0) DLT_LOG(dbusLog, DLT_LOG_INFO, DLT_STRING("BusType"), DLT_STRING("Session Bus")); else if (type == 1) DLT_LOG(dbusLog, DLT_LOG_INFO, DLT_STRING("BusType"), DLT_STRING("System Bus")); else DLT_LOG(dbusLog, DLT_LOG_INFO, DLT_STRING("BusType"), DLT_INT(type)); if (NULL == connection) { fprintf (stderr, "Failed to open connection to %d: %s\n", DBUS_BUS_SYSTEM, error.message); dbus_error_free (&error); exit (1); } for (num = 0; num < config.DBus.FilterCount; num++) { dbus_bus_add_match (connection, config.DBus.FilterMatch[num], &error); printf("Added FilterMatch: %s\n", config.DBus.FilterMatch[num]); DLT_LOG(dbusLog, DLT_LOG_INFO, DLT_STRING("FilterMatch"), DLT_UINT(num + 1), DLT_STRING(config.DBus.FilterMatch[num])); if (dbus_error_is_set (&error)) goto fail; } if (!dbus_connection_add_filter (connection, filter_func, NULL, NULL)) { fprintf (stderr, "Couldn't add filter!\n"); exit (1); } while (dbus_connection_read_write_dispatch(connection, -1)) ; DLT_UNREGISTER_CONTEXT (dbusContext); DLT_UNREGISTER_CONTEXT (dbusLog); DLT_UNREGISTER_APP (); exit(1); fail: /* fail */ fprintf (stderr, "Error: %s\n", error.message); DLT_UNREGISTER_CONTEXT (dbusContext); DLT_UNREGISTER_CONTEXT (dbusLog); DLT_UNREGISTER_APP (); exit(1); } dlt-daemon-2.18.10/src/dbus/dlt-dbus.conf000066400000000000000000000013031446635226000200250ustar00rootroot00000000000000# Configuration file of DLT dbus forwarder # ######################################################################## # General configuration ######################################################################## # The application Id used for DBus Trace (Default: DBUS) # If command line parameter used, the command line application id is used instead ApplicationId = DBUS # The context Id used for the DBus Trace(Default: ALL) ContextId = ALL # The DBus bus to be logged (Default: 1) # DBUS_BUS_SESSION = 0 # DBUS_BUS_SYSTEM = 1 # DBUS_BUS_STARTER = 2 BusType = 1 # Add one or several filters # Filter String is beginning directly after first occurence of character '=' FilterMatch=eavesdrop=true dlt-daemon-2.18.10/src/dbus/dlt-dbus.h000066400000000000000000000032551446635226000173370ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-dbus.h */ #ifndef DLT_DBUS_H_ #define DLT_DBUS_H_ /* DLT related includes. */ #include "dlt.h" #include "dlt_common.h" #define DEFAULT_CONF_FILE CONFIGURATION_FILES_DIR "/dlt-dbus.conf" #define DLT_DBUS_FILTER_MAX 32 /* Macros */ #define UNUSED(x) (void)(x) #define MALLOC_ASSERT(x) if (x == NULL) { \ fprintf(stderr, "Out of memory\n"); \ abort(); } #define MAX_LINE 1024 /* Command line options */ typedef struct { char *ConfigurationFileName; char *ApplicationId; char *BusType; int Daemonize; } DltDBusCliOptions; /* Configuration dbus options */ typedef struct { char *ContextId; char *BusType; int FilterCount; char *FilterMatch[DLT_DBUS_FILTER_MAX]; } DBusOptions; typedef struct { char *ApplicationId; DBusOptions DBus; } DltDBusConfiguration; extern void init_cli_options(DltDBusCliOptions *options); extern int read_command_line(DltDBusCliOptions *options, int argc, char *argv[]); extern int read_configuration_file(DltDBusConfiguration *config, char *file_name); #endif /* DLT_DBUS_H_ */ dlt-daemon-2.18.10/src/dlt-qnx-system/000077500000000000000000000000001446635226000174175ustar00rootroot00000000000000dlt-daemon-2.18.10/src/dlt-qnx-system/CMakeLists.txt000066400000000000000000000020121446635226000221520ustar00rootroot00000000000000####### # @licence make begin@ # SPDX license identifier: MPL-2.0 # # Copyright (C) 2018 Advanced Driver Information Technology. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. # @licence end@ ####### if(NOT WITH_DLT_CXX11_EXT) message(FATAL_ERROR "DLT_QNX_SYSTEM needs the C++ features of dlt, please enable the WITH_DLT_CXX11_EXT option.") endif() set(dlt-qnx-system_SRCS dlt-qnx-system.c dlt-qnx-slogger2-adapter.cpp) add_executable(dlt-qnx-system ${dlt-qnx-system_SRCS}) target_link_libraries(dlt-qnx-system dlt slog2parse json) install(TARGETS dlt-qnx-system RUNTIME DESTINATION bin COMPONENT base) install(FILES dlt-qnx-system.conf dlt-slog2ctxt.json DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) dlt-daemon-2.18.10/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp000066400000000000000000000233251446635226000246570ustar00rootroot00000000000000/** * Copyright (C) 2018-2020 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT QNX system functionality source file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Nguyen Dinh Thi ADIT 2018 * \author Felix Herrmann ADIT 2020 * * \file: dlt-qnx-slogger2-adapter.cpp * For further information see http://www.covesa.org/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dlt-qnx-system.h" #include "dlt_cpp_extension.hpp" using std::chrono_literals::operator""ms; using std::chrono_literals::operator""s; /* Teach dlt about json_decoder_error_t */ template<> inline int32_t logToDlt(DltContextData &log, const json_decoder_error_t &value) { return logToDlt(log, static_cast(value)); } extern DltContext dltQnxSystem; static DltContext dltQnxSlogger2Context; static std::set dltWarnedMissingMappings; extern DltQnxSystemThreads g_threads; extern volatile bool g_inj_disable_slog2_cb; static std::unordered_map g_slog2file; static void dlt_context_map_read(const char *json_filename) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_VERBOSE, "Loading Slog2Ctxt Map from json file: ", json_filename); auto dec = json_decoder_create(); if (json_decoder_parse_file(dec, json_filename) != JSON_DECODER_OK) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_ERROR, "Could not load Slog2Ctxt Map from json file: ", json_filename); return; } const char *ctxtID, *name, *description; /* go to first element in dlt-slog2ctxt.json e.g. "ADIO" */ auto ret = json_decoder_push_object(dec, nullptr, false); while (ret == JSON_DECODER_OK) { ctxtID = json_decoder_name(dec); /* go into the element e.g. { name: "", description: "" } */ ret = json_decoder_push_object(dec, nullptr, false); if (ret != JSON_DECODER_OK) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__, ": json parser error while descending into context dict. ret=", ret); break; } ret = json_decoder_get_string(dec, "name", &name, false); if (ret != JSON_DECODER_OK) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__, ": json parser error while retrieving 'name' element of ", ctxtID, ". ret=", ret); break; } ret = json_decoder_get_string(dec, "description", &description, false); if (ret != JSON_DECODER_OK) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__, ": json parser error while retrieving 'description' element of ", ctxtID, ". ret=", ret); break; } auto ctxt = new DltContext; g_slog2file.emplace(name, ctxt); auto search = g_slog2file.find(name); if (search == g_slog2file.end()) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_INFO, "Could not emplace slog2ctxt map key: ", name); } else { dlt_register_context(ctxt, ctxtID, description); } ret = json_decoder_pop(dec); } DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_DEBUG, "Added ", g_slog2file.size(), " elements into the mapping table."); } /** * Map the slog2 logfile name to a dlt context * e.g. i2c_service.2948409 -> Context with id "I2CS" */ static DltContext *dlt_context_from_slog2file(const char *file_name) { auto d = strchr(file_name, '.'); if (d == nullptr) return &dltQnxSlogger2Context; auto name = std::string(file_name).substr(0, d - file_name); auto search = g_slog2file.find(name); if (search == g_slog2file.end()) { // Only warn once about missing mapping. auto it = dltWarnedMissingMappings.find(name); if (it == dltWarnedMissingMappings.end()) { dltWarnedMissingMappings.insert(name); DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_INFO, "slog2 filename not found in mapping: ", name.c_str()); } return &dltQnxSlogger2Context; } else { return search->second; } } template static void wait_for_buffer_space(const double max_usage_threshold, const std::chrono::duration max_wait_time) { int total_size = 0; int used_size = 0; double used_percent = 100.0; bool timeout = false; const auto end_time = std::chrono::steady_clock::now() + max_wait_time; do { dlt_user_check_buffer(&total_size, &used_size); used_percent = static_cast(used_size) / total_size; if (used_percent < max_usage_threshold) { break; } dlt_user_log_resend_buffer(); std::this_thread::sleep_for(10ms); timeout = std::chrono::steady_clock::now() < end_time; } while (!timeout); if (timeout) { DLT_LOG(dltQnxSystem, DLT_LOG_ERROR, DLT_STRING("failed to get enough buffer space")); } } /** * Function which is invoked by slog2_parse_all() * See slog2_parse_all api docs on qnx.com for details */ static int sloggerinfo_callback(slog2_packet_info_t *info, void *payload, void *param) { DltQnxSystemConfiguration* conf = (DltQnxSystemConfiguration*) param; if (param == NULL) return -1; if (g_inj_disable_slog2_cb == true) { DLT_LOG(dltQnxSystem, DLT_LOG_INFO, DLT_STRING("Disabling slog2 callback by injection request.")); return -1; } DltLogLevelType loglevel; switch (info->severity) { case SLOG2_SHUTDOWN: case SLOG2_CRITICAL: loglevel = DLT_LOG_FATAL; break; case SLOG2_ERROR: loglevel = DLT_LOG_ERROR; break; case SLOG2_WARNING: loglevel = DLT_LOG_WARN; break; case SLOG2_NOTICE: case SLOG2_INFO: loglevel = DLT_LOG_INFO; break; case SLOG2_DEBUG1: loglevel = DLT_LOG_DEBUG; break; case SLOG2_DEBUG2: loglevel = DLT_LOG_VERBOSE; break; default: loglevel = DLT_LOG_INFO; break; } DltContextData log_local; /* Used in DLT_* macros, do not rename */ DltContext *ctxt = dlt_context_from_slog2file(info->file_name); wait_for_buffer_space(0.8, std::chrono::milliseconds(DLT_QNX_SLOG_ADAPTER_WAIT_BUFFER_TIMEOUT_MS)); int ret; ret = dlt_user_log_write_start(ctxt, &log_local, loglevel); /* OK means loglevel under threshold */ if (ret == DLT_RETURN_OK) { return 0; } if (ret != DLT_RETURN_TRUE) { fprintf(stderr, "%s: could not log to DLT status=%d\n", __func__, ret); return -1; } if (conf->qnxslogger2.useOriginalTimestamp == 1) { /* convert from ns to .1 ms */ log_local.user_timestamp = (uint32_t) (info->timestamp / 100000); log_local.use_timestamp = DLT_USER_TIMESTAMP; } else { DLT_UINT64(info->timestamp); } DLT_UINT16(info->sequence_number); DLT_STRING((char *)info->file_name); DLT_STRING((char *)info->buffer_name); DLT_UINT16(info->thread_id); DLT_UINT8(info->severity); DLT_STRING((char *)payload); dlt_user_log_write_finish(&log_local); return 0; } static void *slogger2_thread(void *v_conf) { int ret = -1; DltQnxSystemConfiguration *conf = (DltQnxSystemConfiguration *)v_conf; if (v_conf == NULL) return reinterpret_cast(EINVAL); slog2_packet_info_t packet_info = SLOG2_PACKET_INFO_INIT; DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("dlt-qnx-slogger2-adapter, in thread.")); /** * Thread will block inside this function to get new log because * flag = SLOG2_PARSE_FLAGS_DYNAMIC */ ret = slog2_parse_all( SLOG2_PARSE_FLAGS_DYNAMIC, /* live streaming of all buffers merged */ NULL, NULL, &packet_info, sloggerinfo_callback, (void*) conf); if (ret == -1) { DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_ERROR, "slog2_parse_all() returned error=", ret); ret = EBADMSG; } DLT_LOG_CXX(dltQnxSystem, DLT_LOG_DEBUG, __func__, ": Exited main loop."); DLT_UNREGISTER_CONTEXT(dltQnxSlogger2Context); /* process should be shutdown if the callback was not manually disabled */ if (g_inj_disable_slog2_cb == false) { for (auto& x: g_slog2file) { if(x.second != NULL) { delete(x.second); x.second = NULL; } } /* Send a signal to main thread to wake up sigwait */ pthread_kill(g_threads.mainThread, SIGTERM); } return reinterpret_cast(ret); } void start_qnx_slogger2(DltQnxSystemConfiguration *conf) { static pthread_attr_t t_attr; static pthread_t pt; DLT_REGISTER_CONTEXT(dltQnxSlogger2Context, conf->qnxslogger2.contextId, "SLOGGER2 Adapter"); dlt_context_map_read(CONFIGURATION_FILES_DIR "/dlt-slog2ctxt.json"); DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_DEBUG, "dlt-qnx-slogger2-adapter, start syslog"); pthread_create(&pt, &t_attr, slogger2_thread, conf); g_threads.threads[g_threads.count++] = pt; } dlt-daemon-2.18.10/src/dlt-qnx-system/dlt-qnx-system.c000066400000000000000000000306631446635226000225040ustar00rootroot00000000000000/** * Copyright (C) 2020 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT QNX system functionality source file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Nguyen Dinh Thi * * \file: dlt-qnx-system.c * For further information see http://www.covesa.org/. * @licence end@ */ #include #include #include #include #include #include #include #include #include #include "dlt.h" #include "dlt-qnx-system.h" DLT_DECLARE_CONTEXT(dltQnxSystem) /* Global variables */ volatile DltQnxSystemThreads g_threads; #define INJECTION_SLOG2_ADAPTER 4096 #define DATA_DISABLED "00" #define DATA_ENABLED "01" volatile bool g_inj_disable_slog2_cb = false; /* Function prototype */ static void daemonize(); static void start_threads(); static void join_threads(); static int read_configuration_file(const char *file_name); static int read_command_line(DltQnxSystemCliOptions *options, int argc, char *argv[]); static int dlt_injection_cb(uint32_t service_id, void *data, uint32_t length); static DltQnxSystemConfiguration *g_dlt_qnx_conf = NULL; static void init_configuration(); static void clean_up(); int main(int argc, char* argv[]) { DltQnxSystemCliOptions options; int sigNo = 0; int ret = 0; sigset_t mask; int i; if (read_command_line(&options, argc, argv) < 0) { fprintf(stderr, "Failed to read command line!\n"); return -1; } if (read_configuration_file(options.configurationFileName) < 0) { fprintf(stderr, "Failed to read configuration file!\n"); return -1; } if (options.daemonize > 0) { daemonize(); } sigemptyset(&mask); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGALRM); if (pthread_sigmask(SIG_BLOCK, &mask, NULL) != 0) { fprintf(stderr, "Couldn't set mask for potential future threads.\n"); return -1; } DLT_REGISTER_APP(g_dlt_qnx_conf->applicationId, "DLT QNX System"); DLT_REGISTER_CONTEXT(dltQnxSystem, g_dlt_qnx_conf->applicationContextId, "Context of main dlt qnx system manager"); dlt_register_injection_callback(&dltQnxSystem, INJECTION_SLOG2_ADAPTER, dlt_injection_cb); DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("Setting signals wait for abnormal exit")); g_threads.mainThread = pthread_self(); DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("Launching threads.")); start_threads(); ret = sigwait(&mask, &sigNo); for (i = 0; i < MAX_THREADS; i++) { pthread_cancel(g_threads.threads[i]); } join_threads(); if (ret != 0) { DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("sigwait failed with error: "), DLT_INT(ret)); DLT_UNREGISTER_APP(); return -1; } DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("Received signal: "), DLT_STRING(strsignal(sigNo))); DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); clean_up(); return 0; } /** * Print information how to use this program. */ static void usage(char *prog_name) { char version[255]; dlt_get_version(version, 255); printf("Usage: %s [options]\n", prog_name); printf("Application to manage QNX system, such as:\n"); printf(" - forward slogger2 messages from QNX to DLT) .\n"); printf("%s\n", version); printf("Options:\n"); printf(" -d Daemonize. Detach from terminal and run in background.\n"); printf(" -c filename Use configuration file. \n"); printf(" Default: %s\n", DEFAULT_CONF_FILE); printf(" -h This help message.\n"); } /** * Initialize command line options with default values. */ static void init_cli_options(DltQnxSystemCliOptions *options) { options->configurationFileName = DEFAULT_CONF_FILE; options->daemonize = 0; } /** * Read command line options and set the values in provided structure */ static int read_command_line(DltQnxSystemCliOptions *options, int argc, char *argv[]) { init_cli_options(options); int opt; while ((opt = getopt(argc, argv, "c:hd")) != -1) { switch (opt) { case 'd': { options->daemonize = 1; break; } case 'c': { options->configurationFileName = (char *)malloc(strlen(optarg)+1); MALLOC_ASSERT(options->configurationFileName); /** * strcpy unritical here, because size matches exactly the size * to be copied */ strcpy(options->configurationFileName, optarg); break; } case 'h': { usage(argv[0]); exit(0); return -1; } default: { fprintf(stderr, "Unknown option '%c'\n", optopt); usage(argv[0]); return -1; } } } return 0; } /** * Initialize configuration to default values. */ static void init_configuration() { g_dlt_qnx_conf = calloc(1, sizeof(DltQnxSystemConfiguration)); /* Common */ g_dlt_qnx_conf->applicationId = strdup("QSYM"); g_dlt_qnx_conf->applicationContextId = strdup("QSYC"); /* Slogger2 */ g_dlt_qnx_conf->qnxslogger2.enable = 0; g_dlt_qnx_conf->qnxslogger2.contextId = strdup("QSLA"); g_dlt_qnx_conf->qnxslogger2.useOriginalTimestamp = 1; } /** * Read options from the configuration file */ static int read_configuration_file(const char *file_name) { FILE *file; char *line; char *token; char *value; char *pch; int ret = 0; init_configuration(); if (g_dlt_qnx_conf == NULL) { fprintf(stderr, "dlt-qnx-system, could not allocate memory.\n"); return -1; } file = fopen(file_name, "r"); if (file == NULL) { fprintf(stderr, "dlt-qnx-system, could not open configuration file.\n"); return -1; } line = malloc(MAX_LINE); token = malloc(MAX_LINE); value = malloc(MAX_LINE); MALLOC_ASSERT(line); MALLOC_ASSERT(token); MALLOC_ASSERT(value); while (fgets(line, MAX_LINE, file) != NULL) { token[0] = 0; value[0] = 0; pch = strtok(line, " =\r\n"); while (pch != NULL) { if (pch[0] == '#') { break; } if (token[0] == 0) { strncpy(token, pch, MAX_LINE-1); token[MAX_LINE-1] = 0; } else { strncpy(value, pch, MAX_LINE); value[MAX_LINE-1] = 0; break; } pch = strtok(NULL, " =\r\n"); } if (token[0] && value[0]) { /* Common */ if (strcmp(token, "ApplicationId") == 0) { if (g_dlt_qnx_conf->applicationId) free(g_dlt_qnx_conf->applicationId); g_dlt_qnx_conf->applicationId = strndup(value, DLT_ID_SIZE); MALLOC_ASSERT(g_dlt_qnx_conf->applicationId); } else if (strcmp(token, "ApplicationContextID") == 0) { if (g_dlt_qnx_conf->applicationContextId) free(g_dlt_qnx_conf->applicationContextId); g_dlt_qnx_conf->applicationContextId = strndup(value, DLT_ID_SIZE); MALLOC_ASSERT(g_dlt_qnx_conf->applicationContextId); strncpy(g_dlt_qnx_conf->applicationContextId, value, DLT_ID_SIZE); } /* Slogger2 */ else if (strcmp(token, "QnxSlogger2Enable") == 0) { g_dlt_qnx_conf->qnxslogger2.enable = atoi(value); } else if (strcmp(token, "QnxSlogger2ContextId") == 0) { if (g_dlt_qnx_conf->qnxslogger2.contextId) free(g_dlt_qnx_conf->qnxslogger2.contextId); g_dlt_qnx_conf->qnxslogger2.contextId = strndup(value, DLT_ID_SIZE); MALLOC_ASSERT(g_dlt_qnx_conf->qnxslogger2.contextId); } else if (strcmp(token, "QnxSlogger2UseOriginalTimestamp") == 0) { g_dlt_qnx_conf->qnxslogger2.useOriginalTimestamp = atoi(value); } else { /* Do nothing */ } } } fclose(file); file = NULL; free(value); value = NULL; free(token); token = NULL; free(line); line = NULL; return ret; } static void daemonize() { pid_t pid = fork(); if (pid == -1) { err(-1, "%s failed on fork()", __func__); } if (pid > 0) { /* parent process*/ exit(0); } /* Create a new process group */ if (setsid() == -1) { err(-1, "%s failed on setsid()", __func__); } /* Point std(in,out,err) to /dev/null */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); int fd = open("/dev/null", O_RDWR); if (fd == -1) { err(-1, "%s failed on open() /dev/null", __func__); } if ((dup2(fd, STDIN_FILENO) == -1) || (dup2(fd, STDOUT_FILENO) == -1 ) || (dup2(fd, STDERR_FILENO) == -1 )) { err(-1, "%s failed on dup2()", __func__); } /** * Ignore signals related to child processes and * terminal handling. */ signal(SIGCHLD, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); } static void start_threads() { int i = 0; DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("dlt-qnx-system, start threads")); g_threads.count = 0; g_threads.shutdown = 0; for (i = 0; i < MAX_THREADS; i++) { g_threads.threads[i] = 0; } if (g_dlt_qnx_conf->qnxslogger2.enable) { start_qnx_slogger2(g_dlt_qnx_conf); } } /** * Wait for threads to exit. */ static void join_threads() { int i = 0; DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("dlt-qnx-system, waiting for threads to exit")); if (g_threads.count < 1) { DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("dlt-qnx-system, no threads, waiting for signal.")); } else { DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("dlt-qnx-system, thread count: "), DLT_INT(g_threads.count)); for (i = 0; i < g_threads.count; i++) { pthread_join(g_threads.threads[i], NULL); DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("dlt-qnx-system, thread exit: "), DLT_INT(g_threads.threads[i])); } } DLT_UNREGISTER_CONTEXT(dltQnxSystem); } static int dlt_injection_cb(uint32_t service_id, void *data, uint32_t length) { (void) length; DLT_LOG(dltQnxSystem, DLT_LOG_INFO, DLT_STRING("Injection received:"), DLT_INT32(service_id)); if (service_id != INJECTION_SLOG2_ADAPTER) return -1; if (0 == strncmp((char*) data, DATA_DISABLED, sizeof(DATA_DISABLED)-1)) g_inj_disable_slog2_cb = true; else if (0 == strncmp((char*) data, DATA_ENABLED, sizeof(DATA_ENABLED)-1)) { if (g_inj_disable_slog2_cb == true) { g_inj_disable_slog2_cb = false; start_threads(); } } return 0; } static void clean_up() { if (g_dlt_qnx_conf->applicationId) { free(g_dlt_qnx_conf->applicationId); g_dlt_qnx_conf->applicationId = NULL; } if (g_dlt_qnx_conf->applicationContextId) { free(g_dlt_qnx_conf->applicationContextId); g_dlt_qnx_conf->applicationContextId = NULL; } if (g_dlt_qnx_conf->qnxslogger2.contextId) { free(g_dlt_qnx_conf->qnxslogger2.contextId); g_dlt_qnx_conf->qnxslogger2.contextId = NULL; } if (g_dlt_qnx_conf) { free(g_dlt_qnx_conf); g_dlt_qnx_conf = NULL; } } dlt-daemon-2.18.10/src/dlt-qnx-system/dlt-qnx-system.conf000066400000000000000000000014531446635226000232020ustar00rootroot00000000000000# Configuration file of DLT QNX Slogger2 Manager # ######################################################################## # General configuration ######################################################################## # The application Id used for the QNX system Manager (Default: QSYM) ApplicationId = QSYM # Context of main dlt QNX system ApplicationContextID = QSYC ######################################################################## # Syslog Adapter configuration ######################################################################## # Enable the Qnx slogger2 Adapter (Default: 1) QnxSlogger2Enable = 1 # The Context Id of the Qnx syslog adapter (Default: QSLA) QnxSlogger2ContextId = QSLA # Use slogger2 event timestamps as DLT timestamps (Default: 1) QnxSlogger2UseOriginalTimestamp = 1 dlt-daemon-2.18.10/src/dlt-qnx-system/dlt-qnx-system.h000066400000000000000000000100631446635226000225010ustar00rootroot00000000000000/** * Copyright (C) 2020 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT QNX system functionality header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Nguyen Dinh Thi ADIT 2020 * * \file: dlt-qnx-system.h * For further information see http://www.covesa.org/. * @licence end@ */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_qnx-system.h ** ** ** ** TARGET : QNX ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Thi.NguyenDinh@vn.bosch.com ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** ndt Nguyen Dinh Thi ADIT ** ** ** *******************************************************************************/ #ifndef DLT_QNX_SYSTEM_H_ #define DLT_QNX_SYSTEM_H_ #include "dlt.h" #include "dlt_user_macros.h" /* Constants */ #define DEFAULT_CONF_FILE ( CONFIGURATION_FILES_DIR "/dlt-qnx-system.conf") #define MAX_LINE 1024 #define MAX_THREADS 8 /* Macros */ #define MALLOC_ASSERT(x)\ do\ {\ if(x == NULL) {\ fprintf(stderr, "%s - %d: Out of memory\n", __func__, __LINE__);\ abort();\ }\ }\ while (0) #ifdef __cplusplus extern "C" { #endif /* Command line options */ typedef struct { char *configurationFileName; int daemonize; } DltQnxSystemCliOptions; /* Configuration slogger2 options */ typedef struct { int enable; char *contextId; int useOriginalTimestamp; } Qnxslogger2Options; typedef struct { char *applicationId; char *applicationContextId; Qnxslogger2Options qnxslogger2; } DltQnxSystemConfiguration; typedef struct { pthread_t threads[MAX_THREADS]; pthread_t mainThread; int count; int shutdown; } DltQnxSystemThreads; void start_qnx_slogger2(DltQnxSystemConfiguration *conf); #ifdef __cplusplus } // extern "C" #endif #endif /* DLT_QNX_SYSTEM_H_ */ dlt-daemon-2.18.10/src/dlt-qnx-system/dlt-slog2ctxt.json000066400000000000000000000002701446635226000230230ustar00rootroot00000000000000{ "SRCN": { "name": "screen", "description": "" }, "SLM ": { "name": "slm", "description": "" }, "SYSL": { "name": "syslogd", "description": "" } } dlt-daemon-2.18.10/src/examples/000077500000000000000000000000001446635226000163245ustar00rootroot00000000000000dlt-daemon-2.18.10/src/examples/CMakeLists.txt000066400000000000000000000021271446635226000210660ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### set(TARGET_LIST dlt-example-user-func) set(TARGET_LIST ${TARGET_LIST} dlt-example-filetransfer) if(NOT WITH_DLT_DISABLE_MACRO) set(TARGET_LIST ${TARGET_LIST} dlt-example-user) set(TARGET_LIST ${TARGET_LIST} dlt-example-user-common-api) endif() if(WITH_UDP_CONNECTION) set(TARGET_LIST ${TARGET_LIST} dlt-example-multicast-clientmsg-view) endif() foreach(TARGET IN LISTS TARGET_LIST) set(TARGET_SRCS ${TARGET}) add_executable(${TARGET} ${TARGET_SRCS}) target_link_libraries(${TARGET} dlt) set_target_properties(${TARGET} PROPERTIES LINKER_LANGUAGE C) install(TARGETS ${TARGET} RUNTIME DESTINATION bin COMPONENT base) endforeach() dlt-daemon-2.18.10/src/examples/dlt-example-filetransfer.c000066400000000000000000000153001446635226000233650ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-example-filetransfer.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-client.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include #include /*Needed for transferring files with the dlt protocol*/ #include /*Needed for dlt logging*/ #define MAXSTRLEN 1024 #define FLTR_APP_DESC "Filetransfer application" #define FLTR_CONTEXT_DESC "Filetransfer context" #define FLTR_APP "FLTR" #define FLTR_CONTEXT "FLTR" #define TIMEOUT 1 /*!Declare some context for the file transfer. It's not a must have to do this, but later you can set a filter on this context in the dlt viewer. */ DLT_DECLARE_CONTEXT(fileContext) /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-example-filetransfer [options] absolute-path-to-file\n"); printf("Simple filetransfer example"); printf("%s \n", version); printf("Options:\n"); printf("-a apid - Set application id to apid (default: FLTR)\n"); printf("-c ctid - Set context id to ctid (default: FLTR)\n"); printf("-t ms - Timeout between file packages in ms (minimum 1 ms)\n"); printf("-d - Flag to delete the file after the transfer (default: false)\n"); printf("-i - Flag to log file infos to DLT before transfer file (default: false)\n"); printf("-h - This help\n"); } /*!Main program dlt-test-filestransfer starts here */ int main(int argc, char *argv[]) { /*char str[MAXSTRLEN]; */ int opt, timeout; char apid[DLT_ID_SIZE]; char ctid[DLT_ID_SIZE]; /*char version[255]; */ int index; int dflag = 0; int iflag = 0; char *file = 0; char *tvalue = 0; dlt_set_id(apid, FLTR_APP); dlt_set_id(ctid, FLTR_CONTEXT); while ((opt = getopt(argc, argv, "idf:t:a:c:h")) != -1) switch (opt) { case 'd': { dflag = 1; break; } case 'i': { iflag = 1; break; } case 't': { tvalue = optarg; break; } case 'a': { dlt_set_id(apid, optarg); break; } case 'c': { dlt_set_id(ctid, optarg); break; } case 'h': { usage(); break; } case '?': { if ((optopt == 'a') || (optopt == 'c') || (optopt == 't')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } } for (index = optind; index < argc; index++) file = argv[index]; if (file == 0) { /* no message, show usage and terminate */ fprintf(stderr, "ERROR: No absolute path to file specified\n"); usage(); return -1; } if (tvalue) timeout = atoi(tvalue); else timeout = TIMEOUT; /*Register the application at the dlt-daemon */ DLT_REGISTER_APP(apid, FLTR_APP_DESC); /*Register the context of the main program at the dlt-daemon */ DLT_REGISTER_CONTEXT(fileContext, ctid, FLTR_CONTEXT_DESC); /*More details in corresponding methods */ if (iflag) dlt_user_log_file_infoAbout(&fileContext, file); if (dlt_user_log_file_complete(&fileContext, file, dflag, timeout) < 0) printf("File couldn't be transferred. Please check the dlt log messages.\n"); /*Unregister the context in which the file transfer happened from the dlt-daemon */ DLT_UNREGISTER_CONTEXT(fileContext); /*Unregister the context of the main program from the dlt-daemon */ DLT_UNREGISTER_APP(); return 0; } dlt-daemon-2.18.10/src/examples/dlt-example-multicast-clientmsg-view.c000066400000000000000000000136541446635226000256530ustar00rootroot00000000000000/* * Copyright (c) 2019 LG Electronics Inc. * SPDX-License-Identifier: MPL-2.0 * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Guruprasad KN * Sachin Sudhakar Shetty * Sunil Kovila Sampath * * \copyright Copyright (c) 2019 LG Electronics Inc. * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-example-multicast-clientmsg-view.c */ #include #include #include #include #include #include #include #include /* for isprint() */ #include /* for atoi() */ #include /* for S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH */ #include /* for open() */ #include /* for writev() */ #include #include #include #include #include /* for PATH_MAX */ #include #include "dlt_client.h" #include "dlt_client_cfg.h" #define DLT_RECEIVE_TEXTBUFSIZE 10024 #define HELLO_PORT 3491 #define HELLO_GROUP "225.0.0.37" struct clientinfostruct { int fd; struct sockaddr_in addr; socklen_t addlen; DltReceiver receiver; }; int dlt_receiver_receive_socket_udp(struct clientinfostruct *clientinfo, DltReceiver *receiver) { if ((receiver == NULL) || (clientinfo == NULL)) { printf("NULL receiver or clientinfo in dlt_receiver_receive_socket_udp\n"); return -1; } if (receiver->buffer == NULL) { printf("NULL receiver->buffer in dlt_receiver_receive_socket_udp\n"); return -1; } receiver->buf = (char *)receiver->buffer; receiver->lastBytesRcvd = receiver->bytesRcvd; /* wait for data from socket */ unsigned int addrlen = sizeof(clientinfo->addr); if ((receiver->bytesRcvd = recvfrom(clientinfo->fd, receiver->buf + receiver->lastBytesRcvd, receiver->buffersize - receiver->lastBytesRcvd, 0, (struct sockaddr *)&(clientinfo->addr), &addrlen)) <= 0) { printf("Error\n"); perror("recvfrom"); receiver->bytesRcvd = 0; return receiver->bytesRcvd; } /* if */ receiver->totalBytesRcvd += receiver->bytesRcvd; receiver->bytesRcvd += receiver->lastBytesRcvd; return receiver->bytesRcvd; } int dlt_receive_message_callback_udp(DltMessage *message) { static char text[DLT_RECEIVE_TEXTBUFSIZE]; if ((message == NULL)) { printf("NULL message in dlt_receive_message_callback_udp\n"); return -1; } /* prepare storage header */ if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) dlt_set_storageheader(message->storageheader, message->headerextra.ecu); else dlt_set_storageheader(message->storageheader, "ECU1"); dlt_message_header(message, text, DLT_RECEIVE_TEXTBUFSIZE, 0); printf("%s ", text); dlt_message_payload(message, text, DLT_RECEIVE_TEXTBUFSIZE, DLT_OUTPUT_ASCII, 0); printf("[%s]\n", text); return 0; } int main() { struct clientinfostruct clientinfo; struct ip_mreq mreq; u_int yes = 1; /* create what looks like an ordinary UDP socket */ if ((clientinfo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } /* allow multiple sockets to use the same PORT number */ if (setsockopt(clientinfo.fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { perror("Reusing ADDR failed"); exit(1); } /* set up destination address */ memset(&clientinfo.addr, 0, sizeof(clientinfo.addr)); clientinfo.addr.sin_family = AF_INET; clientinfo.addr.sin_addr.s_addr = htonl(INADDR_ANY); /* N.B.: differs from sender */ clientinfo.addr.sin_port = htons(HELLO_PORT); /* bind to receive address */ if (bind(clientinfo.fd, (struct sockaddr *)&clientinfo.addr, sizeof(clientinfo.addr)) < 0) { perror("bind"); exit(1); } /* use setsockopt() to request that the kernel join a multicast group */ mreq.imr_multiaddr.s_addr = inet_addr(HELLO_GROUP); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(clientinfo.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { perror("setsockopt"); exit(1); } DltMessage msg; if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; if (dlt_receiver_init(&(clientinfo.receiver), clientinfo.fd, DLT_RECEIVE_UDP_SOCKET, DLT_RECEIVE_BUFSIZE) != DLT_RETURN_OK) return DLT_RETURN_ERROR; printf("Waiting for message on ip %s port : %d\n", HELLO_GROUP, HELLO_PORT); while (1) { /* wait for data from socket */ dlt_receiver_receive_socket_udp(&clientinfo, &(clientinfo.receiver)); while (dlt_message_read(&msg, (unsigned char *)(clientinfo.receiver.buf), clientinfo.receiver.bytesRcvd, 0, 0) == DLT_MESSAGE_ERROR_OK) { dlt_receive_message_callback_udp(&msg); if (dlt_receiver_remove(&(clientinfo.receiver), msg.headersize + msg.datasize - sizeof(DltStorageHeader)) == DLT_RETURN_ERROR) { /* Return value ignored */ dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } } if (dlt_receiver_move_to_begin(&(clientinfo.receiver)) == DLT_RETURN_ERROR) { /* Return value ignored */ dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } } } dlt-daemon-2.18.10/src/examples/dlt-example-non-verbose-1.xml000077500000000000000000000600151446635226000236600ustar00rootroot00000000000000 projectTCB TCB 001.004.062 LOG Application 1 TEST Context 1 PDU_10_0 DLT non verbose test message. 0 OTHER PDU_11_0 Buffer near limit. Free size: 0 OTHER PDU_11_1 2 OTHER 0 PDU_12_0 Buffer size exceeded. 0 OTHER PDU_12_1 4 OTHER 0 PDU_12_2 4 OTHER 0 PDU_12_3 Process terminated. 0 OTHER PDU_13_0 Temperature measurement 0 OTHER PDU_13_1 1 OTHER 0 measurement_point PDU_13_2 4 OTHER 0 reading Kelvin PDU_14_0 Build ID: 0 OTHER PDU_14_1 0 OTHER 0 ID_10 0 OTHER 0 DLT_TYPE_LOG DLT_LOG_INFO LOG TEST dlt_test.c 411 ID_1001 2 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_WARN LOG TEST application_file.c 955 ID_1002 2 OTHER 0 1 2 3 DLT_TYPE_LOG DLT_LOG_ERROR LOG TEST application_file.c 1058 ID_1003 5 OTHER 0 1 2 DLT_TYPE_LOG DLT_LOG_INFO LOG TEST temp_meas.c 42 ID_14 0 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_INFO LOG TEST latsTask.c 421 S_BOOL S_SINT8 S_UINT8 S_SINT16 S_UINT16 S_SINT32 S_UINT32 S_SINT64 S_UINT64 S_FLOA16 S_FLOA32 S_FLOA64 S_STRG_ASCII S_STRG_UTF8 BOOL Coding for boolean values. 8 SINT8 Coding for signel 8bit values. 8 UINT8 Coding for unsignel 8bit values. 8 SINT16 Coding for signel 16bit values. 16 UINT16 Coding for unsignel 16bit values. 16 SINT32 Coding for signel 32bit values. 32 UINT32 Coding for unsignel 32bit values. 32 SINT64 Coding for signel 64bit values. 64 UINT64 Coding for unsignel 64bit values. 64 FLOA16 Coding for float 16bit values. 16 FLOA32 Coding for float 32bit values. 32 FLOA64 Coding for float 64bit values. 64 STRG_ASCII Coding for ASCII string. 0 255 STRG_UTF8 Coding for UTF8 string. 0 255 dlt-daemon-2.18.10/src/examples/dlt-example-non-verbose-1.xml.old000066400000000000000000000621201446635226000244310ustar00rootroot00000000000000 projectTCB TCB 001.004.062 APP1 Application 1 CON1 Context 1 TEST Test Application CON1 Context 1 LAT Log And Trace NV NV test PDU_10_0 DLT non verbose test message. 0 OTHER PDU_11_0 Buffer near limit. Free size: 0 OTHER PDU_11_1 2 OTHER 0 PDU_12_0 Buffer size exceeded. 0 OTHER PDU_12_1 4 OTHER 0 PDU_12_2 4 OTHER 0 PDU_12_3 Process terminated. 0 OTHER PDU_13_0 Temperature measurement 0 OTHER PDU_13_1 1 OTHER 0 measurement_point PDU_13_2 4 OTHER 0 reading Kelvin PDU_14_0 Build ID: 0 OTHER PDU_14_1 0 OTHER 0 ID_10 0 OTHER 0 DLT_TYPE_LOG DLT_LOG_INFO TEST CON1 dlt_test.c 411 ID_1001 2 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_WARN APP1 CON1 application_file.c 955 ID_1002 2 OTHER 0 1 2 3 DLT_TYPE_LOG DLT_LOG_ERROR APP1 CON1 application_file.c 1058 ID_1003 5 OTHER 0 1 2 DLT_TYPE_LOG DLT_LOG_INFO APP1 CON1 temp_meas.c 42 ID_14 0 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_INFO LAT NV latsTask.c 421 S_BOOL S_SINT8 S_UINT8 S_SINT16 S_UINT16 S_SINT32 S_UINT32 S_SINT64 S_UINT64 S_FLOA16 S_FLOA32 S_FLOA64 S_STRG_ASCII S_STRG_UTF8 BOOL Coding for boolean values. 8 SINT8 Coding for signel 8bit values. 8 UINT8 Coding for unsignel 8bit values. 8 SINT16 Coding for signel 16bit values. 16 UINT16 Coding for unsignel 16bit values. 16 SINT32 Coding for signel 32bit values. 32 UINT32 Coding for unsignel 32bit values. 32 SINT64 Coding for signel 64bit values. 64 UINT64 Coding for unsignel 64bit values. 64 FLOA16 Coding for float 16bit values. 16 FLOA32 Coding for float 32bit values. 32 FLOA64 Coding for float 64bit values. 64 STRG_ASCII Coding for ASCII string. 0 255 STRG_UTF8 Coding for UTF8 string. 0 255 dlt-daemon-2.18.10/src/examples/dlt-example-non-verbose.xml000066400000000000000000000443021446635226000235200ustar00rootroot00000000000000 projectTCB TCB 001.004.062 PDU_10_0 DLT non verbose test message. 0 OTHER PDU_11_0 Buffer near limit. Free size: 0 OTHER PDU_11_1 2 OTHER 0 PDU_12_0 Buffer size exceeded. 0 OTHER PDU_12_1 Requested size: 4 OTHER 0 PDU_12_2 Free size: 4 OTHER 0 PDU_12_3 Process terminated. 0 OTHER PDU_13_0 Temperature measurement 0 OTHER PDU_13_1 1 OTHER 0 measurement_point PDU_13_2 4 OTHER 0 reading Kelvin ID_10 0 OTHER 0 DLT_TYPE_LOG DLT_LOG_INFO TEST CON1 dlt_test.c 411 ID_11 2 OTHER 0 1 DLT_TYPE_LOG DLT_LOG_WARN APP1 CON1 application_file.c 955 ID_12 8 OTHER 0 1 2 3 DLT_TYPE_LOG DLT_LOG_ERROR APP1 CON1 application_file.c 1058 ID_13 5 OTHER 0 1 2 DLT_TYPE_LOG DLT_LOG_INFO APP1 CON1 temp_meas.c 42 S_BOOL S_SINT8 S_UINT8 S_SINT16 S_UINT16 S_SINT32 S_UINT32 S_SINT64 S_UINT64 S_FLOA16 S_FLOA32 S_FLOA64 S_STRG_ASCII S_STRG_UTF8 BOOL Coding for boolean values. 8 SINT8 Coding for signel 8bit values. 8 UINT8 Coding for unsignel 8bit values. 8 SINT16 Coding for signel 16bit values. 16 UINT16 Coding for unsignel 16bit values. 16 SINT32 Coding for signel 32bit values. 32 UINT32 Coding for unsignel 32bit values. 32 SINT64 Coding for signel 64bit values. 64 UINT64 Coding for unsignel 64bit values. 64 FLOA16 Coding for float 16bit values. 16 FLOA32 Coding for float 32bit values. 32 FLOA64 Coding for float 64bit values. 64 STRG_ASCII Coding for ASCII string. 0 255 STRG_UTF8 Coding for UTF8 string. 0 255 dlt-daemon-2.18.10/src/examples/dlt-example-user-common-api.c000066400000000000000000000207001446635226000237140ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-example-user-common-api.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-example-common-api.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include "dlt_common_api.h" DLT_DECLARE_CONTEXT(mycontext) /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-example-common-api [options] message\n"); printf("Generate DLT messages and store them to file or send them to daemon.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -d delay Milliseconds to wait between sending messages (Default: 500)\n"); printf(" -f filename Use local log file instead of sending to daemon\n"); printf(" -n count Number of messages to be generated (Default: 10)\n"); printf(" -g Switch to non-verbose mode (Default: verbose mode)\n"); printf(" -a Enable local printing of DLT messages (Default: disabled)\n"); printf(" -m mode Set log mode 0=off,1=external,2=internal,3=both\n"); #ifdef DLT_TEST_ENABLE printf(" -c Corrupt user header\n"); printf(" -s size Corrupt message size\n"); printf(" -z size Size of message\n"); #endif /* DLT_TEST_ENABLE */ } /** * Main function of tool. */ int main(int argc, char *argv[]) { #ifdef DLT_TEST_ENABLE int cflag = 0; char *svalue = 0; char *zvalue = 0; #endif /* DLT_TEST_ENABLE */ int gflag = 0; char *dvalue = 0; char *nvalue = 0; char *message = 0; int index; int c; char *text; int num, maxnum; int delay; struct timespec ts; int state = -1, newstate; opterr = 0; #ifdef DLT_TEST_ENABLE while ((c = getopt (argc, argv, "vgcd:n:z:s:")) != -1) #else while ((c = getopt (argc, argv, "vgd:n:")) != -1) #endif /* DLT_TEST_ENABLE */ { switch (c) { #ifdef DLT_TEST_ENABLE case 'c': { cflag = 1; break; } case 's': { svalue = optarg; break; } case 'z': { zvalue = optarg; break; } #endif /* DLT_TEST_ENABLE */ case 'g': { gflag = 1; break; } case 'd': { dvalue = optarg; break; } case 'n': { nvalue = optarg; break; } case '?': { if ((optopt == 'd') || (optopt == 'f') || (optopt == 'n')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); break;/*for parasoft */ } } } for (index = optind; index < argc; index++) message = argv[index]; if (message == 0) { /* no message, show usage and terminate */ fprintf(stderr, "ERROR: No message selected\n"); usage(); return -1; } DLT_REGISTER_APP("LOG", "Test Application for Logging"); DLT_REGISTER_CONTEXT_APP(mycontext, "TEST", "LOG", "Test Context for Logging"); text = message; if (nvalue) maxnum = atoi(nvalue); else maxnum = 10; if (dvalue) delay = atoi(dvalue) * 1000000; else delay = 500 * 1000000; if (gflag) { /* DLT messages to test Fibex non-verbose description: dlt-example-non-verbose.xml */ DLT_LOG_ID0(mycontext, DLT_LOG_INFO, 10); DLT_LOG_ID1(mycontext, DLT_LOG_INFO, 11, DLT_UINT16(1011)); DLT_LOG_ID2(mycontext, DLT_LOG_INFO, 12, DLT_UINT32(1012), DLT_UINT32(1013)); DLT_LOG_ID2(mycontext, DLT_LOG_INFO, 13, DLT_UINT8(123), DLT_FLOAT32(1.12)); DLT_LOG_ID1(mycontext, DLT_LOG_INFO, 14, DLT_STRING("DEAD BEEF")); } #ifdef DLT_TEST_ENABLE if (cflag) dlt_user_test_corrupt_user_header(1); if (svalue) dlt_user_test_corrupt_message_size(1, atoi(svalue)); if (zvalue) { char *buffer = malloc(atoi(zvalue)); if (buffer == 0) { /* no message, show usage and terminate */ fprintf(stderr, "Cannot allocate buffer memory!\n"); return -1; } DLT_LOG2(mycontext, DLT_LOG_WARN, DLT_STRING(text), DLT_RAW(buffer, atoi(zvalue))); free(buffer); } #endif /* DLT_TEST_ENABLE */ for (num = 0; num < maxnum; num++) { printf("Send %d %s\n", num, text); newstate = dlt_get_log_state(); if (state != newstate) { state = newstate; if (state == -1) printf("Client unknown state!\n"); else if (state == 0) printf("Client disconnected!\n"); else if (state == 1) printf("Client connected!\n"); } if (gflag) /* Non-verbose mode */ DLT_LOG_ID2(mycontext, DLT_LOG_WARN, num, DLT_INT(num), DLT_STRING(text)); else /* Verbose mode */ DLT_LOG2(mycontext, DLT_LOG_WARN, DLT_INT(num), DLT_STRING(text)); if (delay > 0) { ts.tv_sec = delay / 1000000000; ts.tv_nsec = delay % 1000000000; nanosleep(&ts, NULL); } } sleep(1); DLT_UNREGISTER_CONTEXT(mycontext); DLT_UNREGISTER_APP(); return 0; } dlt-daemon-2.18.10/src/examples/dlt-example-user-func.c000066400000000000000000000226731446635226000226230ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-example-user-func.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-example-user-func.cpp ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include #include #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include "dlt.h" #include "dlt_common.h" /* for dlt_get_version() */ int dlt_user_injection_callback(uint32_t service_id, void *data, uint32_t length); DltContext mycontext; DltContextData mycontextdata; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-example-user-func [options] message\n"); printf("Generate DLT messages and store them to file or send them to daemon.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -d delay Milliseconds to wait between sending messages (Default: 500)\n"); printf(" -f filename Use local log file instead of sending to daemon\n"); printf(" -n count Number of messages to be generated (Default: 10)\n"); printf(" -g Switch to non-verbose mode (Default: verbose mode)\n"); printf(" -a Enable local printing of DLT messages (Default: disabled)\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { int gflag = 0; int aflag = 0; char *dvalue = 0; char *fvalue = 0; char *nvalue = 0; char *message = 0; int index; int c; char *text; int num, maxnum; int delay; struct timespec ts; opterr = 0; while ((c = getopt (argc, argv, "vgad:f:n:")) != -1) switch (c) { case 'g': { gflag = 1; break; } case 'a': { aflag = 1; break; } case 'd': { dvalue = optarg; break; } case 'f': { fvalue = optarg; break; } case 'n': { nvalue = optarg; break; } case '?': { if ((optopt == 'd') || (optopt == 'f') || (optopt == 'n')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1;/*for parasoft */ } } for (index = optind; index < argc; index++) message = argv[index]; if (message == 0) { /* no message, show usage and terminate */ fprintf(stderr, "ERROR: No message selected\n"); usage(); return -1; } if (fvalue) { /* DLT is intialised automatically, except another output target will be used */ if (dlt_init_file(fvalue) < 0) /* log to file */ return -1; } dlt_register_app("LOG", "Test Application for Logging"); dlt_register_context(&mycontext, "TEST", "Test Context for Logging"); dlt_register_injection_callback(&mycontext, 0xFFF, dlt_user_injection_callback); text = message; if (gflag) dlt_nonverbose_mode(); if (aflag) dlt_enable_local_print(); if (nvalue) maxnum = atoi(nvalue); else maxnum = 10; if (dvalue) delay = atoi(dvalue) * 1000000; else delay = 500 * 1000000; if (gflag) { /* DLT messages to test Fibex non-verbose description: dlt-example-non-verbose.xml */ if (dlt_user_log_write_start_id(&mycontext, &mycontextdata, DLT_LOG_INFO, 10) > 0) dlt_user_log_write_finish(&mycontextdata); if (dlt_user_log_write_start_id(&mycontext, &mycontextdata, DLT_LOG_INFO, 11) > 0) { dlt_user_log_write_uint16(&mycontextdata, 1011); dlt_user_log_write_finish(&mycontextdata); } if (dlt_user_log_write_start_id(&mycontext, &mycontextdata, DLT_LOG_INFO, 12) > 0) { dlt_user_log_write_uint32(&mycontextdata, 1012); dlt_user_log_write_uint32(&mycontextdata, 1013); dlt_user_log_write_finish(&mycontextdata); } if (dlt_user_log_write_start_id(&mycontext, &mycontextdata, DLT_LOG_INFO, 13) > 0) { dlt_user_log_write_uint8(&mycontextdata, 123); dlt_user_log_write_float32(&mycontextdata, 1.12); dlt_user_log_write_finish(&mycontextdata); } if (dlt_user_log_write_start_id(&mycontext, &mycontextdata, DLT_LOG_INFO, 14) > 0) { dlt_user_log_write_string(&mycontextdata, "DEAD BEEF"); dlt_user_log_write_finish(&mycontextdata); } } for (num = 0; num < maxnum; num++) { printf("Send %d %s\n", num, text); if (gflag) { /* Non-verbose mode */ if (dlt_user_log_write_start_id(&mycontext, &mycontextdata, DLT_LOG_WARN, num) > 0) { dlt_user_log_write_int(&mycontextdata, num); dlt_user_log_write_string(&mycontextdata, text); dlt_user_log_write_finish(&mycontextdata); } } else /* Verbose mode */ if (dlt_user_log_write_start(&mycontext, &mycontextdata, DLT_LOG_WARN) > 0) { dlt_user_log_write_int(&mycontextdata, num); dlt_user_log_write_string(&mycontextdata, text); dlt_user_log_write_finish(&mycontextdata); } if (delay > 0) { ts.tv_sec = delay / 1000000000; ts.tv_nsec = delay % 1000000000; nanosleep(&ts, NULL); } } dlt_unregister_context(&mycontext); dlt_unregister_app(); return 0; } int dlt_user_injection_callback(uint32_t service_id, void *data, uint32_t length) { char text[1024]; printf("Injection %d, Length=%d \n", service_id, length); if (length > 0) { dlt_print_mixed_string(text, 1024, data, length, 0); printf("%s \n", text); } return 0; } dlt-daemon-2.18.10/src/examples/dlt-example-user.c000066400000000000000000000350551446635226000216700ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-example-user.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-example-user.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include #include #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include "dlt.h" #include "dlt_common.h" /* for dlt_get_version() */ int dlt_user_injection_callback(uint32_t service_id, void *data, uint32_t length); int dlt_user_injection_callback_with_specific_data(uint32_t service_id, void *data, uint32_t length, void *priv_data); void dlt_user_log_level_changed_callback(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status); DLT_DECLARE_CONTEXT(mycontext1) DLT_DECLARE_CONTEXT(mycontext2) DLT_DECLARE_CONTEXT(mycontext3) /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-example-user [options] message\n"); printf("Generate DLT messages and store them to file or send them to daemon.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -d delay Milliseconds to wait between sending messages (Default: 500)\n"); printf(" -f filename Use local log file instead of sending to daemon\n"); printf(" -S filesize Set maximum size of local log file (Default: UINT_MAX)\n"); printf(" -n count Number of messages to be generated (Default: 10)\n"); printf(" -g Switch to non-verbose mode (Default: verbose mode)\n"); printf(" -a Enable local printing of DLT messages (Default: disabled)\n"); printf(" -k Send marker message\n"); printf(" -m mode Set log mode 0=off, 1=external, 2=internal, 3=both\n"); printf(" -l level Set log level to , level=-1..6\n"); printf(" -C ContextID Set context ID for send message (Default: TEST)\n"); printf(" -A AppID Set app ID for send message (Default: LOG)\n"); printf(" -t timeout Set timeout when sending messages at exit, in ms (Default: 10000 = 10sec)\n"); printf(" -r size Send raw data with specified size instead of string\n"); #ifdef DLT_TEST_ENABLE printf(" -c Corrupt user header\n"); printf(" -s size Corrupt message size\n"); printf(" -z size Size of message\n"); #endif /* DLT_TEST_ENABLE */ } /** * Main function of tool. */ int main(int argc, char *argv[]) { int gflag = 0; int aflag = 0; int kflag = 0; #ifdef DLT_TEST_ENABLE int cflag = 0; char *svalue = 0; char *zvalue = 0; #endif /* DLT_TEST_ENABLE */ char *dvalue = 0; char *fvalue = 0; unsigned int filesize = 0; char *nvalue = 0; char *mvalue = 0; char *message = 0; int lvalue = DLT_LOG_WARN; char *tvalue = 0; int rvalue = -1; int index; int c; char *appID = "LOG"; char *contextID = "TEST"; char *text; int num, maxnum; int delay; struct timespec ts; int state = -1, newstate; opterr = 0; #ifdef DLT_TEST_ENABLE while ((c = getopt (argc, argv, "vgakcd:f:S:n:m:z:r:s:l:t:A:C:")) != -1) #else while ((c = getopt (argc, argv, "vgakd:f:S:n:m:l:r:t:A:C:")) != -1) #endif /* DLT_TEST_ENABLE */ { switch (c) { case 'g': { gflag = 1; break; } case 'a': { aflag = 1; break; } case 'k': { kflag = 1; break; } #ifdef DLT_TEST_ENABLE case 'c': { cflag = 1; break; } case 's': { svalue = optarg; break; } case 'z': { zvalue = optarg; break; } #endif /* DLT_TEST_ENABLE */ case 'd': { dvalue = optarg; break; } case 'f': { fvalue = optarg; break; } case 'S': { filesize = atoi(optarg); break; } case 'n': { nvalue = optarg; break; } case 'm': { mvalue = optarg; break; } case 'l': { lvalue = atoi(optarg); break; } case 'A': { appID = optarg; break; } case 'C': { contextID = optarg; break; } case 't': { tvalue = optarg; break; } case 'r': { rvalue = atoi(optarg); break; } case '?': { if ((optopt == 'd') || (optopt == 'f') || (optopt == 'n') || (optopt == 'l') || (optopt == 't') || (optopt == 'S')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); break;/*for parasoft */ } } } if (rvalue == -1) { for (index = optind; index < argc; index++) message = argv[index]; } else { /* allocate raw buffer */ message = calloc(sizeof(char), rvalue); memset(message, 'X', rvalue - 1); } if (message == 0) { /* no message, show usage and terminate */ fprintf(stderr, "ERROR: No message selected\n"); usage(); return -1; } if (fvalue) { /* DLT is initialized automatically, except another output target will be used */ if (dlt_init_file(fvalue) < 0) /* log to file */ return -1; } if (filesize != 0) { if (dlt_set_filesize_max(filesize) < 0) return -1; } dlt_with_session_id(1); dlt_with_timestamp(1); dlt_with_ecu_id(1); dlt_verbose_mode(); DLT_REGISTER_APP(appID, "Test Application for Logging"); DLT_REGISTER_CONTEXT(mycontext1, contextID, "Test Context for Logging"); DLT_REGISTER_CONTEXT_LLCCB(mycontext2, "TS1", "Test Context1 for injection", dlt_user_log_level_changed_callback); DLT_REGISTER_CONTEXT_LLCCB(mycontext3, "TS2", "Test Context2 for injection", dlt_user_log_level_changed_callback); DLT_REGISTER_INJECTION_CALLBACK(mycontext1, 0x1000, dlt_user_injection_callback); DLT_REGISTER_INJECTION_CALLBACK_WITH_ID(mycontext2, 0x1000, dlt_user_injection_callback_with_specific_data, (void *)"TS1 context"); DLT_REGISTER_INJECTION_CALLBACK(mycontext2, 0x1001, dlt_user_injection_callback); DLT_REGISTER_INJECTION_CALLBACK_WITH_ID(mycontext3, 0x1000, dlt_user_injection_callback_with_specific_data, (void *)"TS2 context"); DLT_REGISTER_INJECTION_CALLBACK(mycontext3, 0x1001, dlt_user_injection_callback); DLT_REGISTER_LOG_LEVEL_CHANGED_CALLBACK(mycontext1, dlt_user_log_level_changed_callback); text = message; if (mvalue) { printf("Set log mode to %d\n", atoi(mvalue)); dlt_set_log_mode(atoi(mvalue)); } if (gflag) DLT_NONVERBOSE_MODE(); if (aflag) DLT_ENABLE_LOCAL_PRINT(); if (kflag) DLT_LOG_MARKER(); if (nvalue) maxnum = atoi(nvalue); else maxnum = 10; if (dvalue) delay = atoi(dvalue); else delay = 500; if (tvalue) dlt_set_resend_timeout_atexit(atoi(tvalue)); if (gflag) { /* DLT messages to test Fibex non-verbose description: dlt-example-non-verbose.xml */ DLT_LOG_ID(mycontext1, DLT_LOG_INFO, 10); DLT_LOG_ID(mycontext1, DLT_LOG_INFO, 11, DLT_UINT16(1011)); DLT_LOG_ID(mycontext1, DLT_LOG_INFO, 12, DLT_UINT32(1012), DLT_UINT32(1013)); DLT_LOG_ID(mycontext1, DLT_LOG_INFO, 13, DLT_UINT8(123), DLT_FLOAT32(1.12)); DLT_LOG_ID(mycontext1, DLT_LOG_INFO, 14, DLT_STRING("DEAD BEEF")); } #ifdef DLT_TEST_ENABLE if (cflag) dlt_user_test_corrupt_user_header(1); if (svalue) dlt_user_test_corrupt_message_size(1, atoi(svalue)); if (zvalue) { char *buffer = malloc(atoi(zvalue)); if (buffer == 0) { /* no message, show usage and terminate */ fprintf(stderr, "Cannot allocate buffer memory!\n"); return -1; } DLT_LOG(mycontext1, DLT_LOG_WARN, DLT_STRING(text), DLT_RAW(buffer, atoi(zvalue))); free(buffer); } #endif /* DLT_TEST_ENABLE */ for (num = 0; num < maxnum; num++) { printf("Send %d %s\n", num, text); newstate = dlt_get_log_state(); if (state != newstate) { state = newstate; if (state == -1) printf("Client unknown state!\n"); else if (state == 0) printf("Client disconnected!\n"); else if (state == 1) printf("Client connected!\n"); } if (gflag) { /* Non-verbose mode */ DLT_LOG_ID(mycontext1, lvalue, num, DLT_INT(num), DLT_STRING(text)); } else { if (rvalue == -1) /* Verbose mode */ DLT_LOG(mycontext1, lvalue, DLT_INT(num), DLT_STRING(text)); else DLT_LOG(mycontext1, lvalue, DLT_RAW(text, rvalue)); } if (delay > 0) { ts.tv_sec = delay / 1000; ts.tv_nsec = (delay % 1000) * 1000000; nanosleep(&ts, NULL); } } sleep(1); DLT_UNREGISTER_CONTEXT(mycontext1); DLT_UNREGISTER_APP(); return 0; } int dlt_user_injection_callback(uint32_t service_id, void *data, uint32_t length) { char text[1024]; DLT_LOG(mycontext1, DLT_LOG_INFO, DLT_STRING("Injection: "), DLT_UINT32(service_id)); printf("Injection %d, Length=%d \n", service_id, length); if (length > 0) { dlt_print_mixed_string(text, 1024, data, length, 0); DLT_LOG(mycontext1, DLT_LOG_INFO, DLT_STRING("Data: "), DLT_STRING(text)); printf("%s \n", text); } return 0; } int dlt_user_injection_callback_with_specific_data(uint32_t service_id, void *data, uint32_t length, void *priv_data) { char text[1024]; DLT_LOG(mycontext1, DLT_LOG_INFO, DLT_STRING("Injection: "), DLT_UINT32(service_id)); printf("Injection %d, Length=%d \n", service_id, length); if (length > 0) { dlt_print_mixed_string(text, 1024, data, length, 0); DLT_LOG(mycontext1, DLT_LOG_INFO, DLT_STRING("Data: "), DLT_STRING(text), DLT_STRING(priv_data)); printf("%s \n", text); } return 0; } void dlt_user_log_level_changed_callback(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status) { char text[5]; text[4] = 0; memcpy(text, context_id, DLT_ID_SIZE); printf("Log level changed of context %s, LogLevel=%u, TraceState=%u \n", text, log_level, trace_status); } dlt-daemon-2.18.10/src/gateway/000077500000000000000000000000001446635226000161475ustar00rootroot00000000000000dlt-daemon-2.18.10/src/gateway/CMakeLists.txt000066400000000000000000000012501446635226000207050ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2015, Advanced Driver Information Technology # This code is developed by Advanced Driver Information Technology. # Copyright of Advanced Driver Information Technology, Bosch and DENSO. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### INSTALL(FILES dlt_gateway.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) dlt-daemon-2.18.10/src/gateway/dlt_gateway.c000066400000000000000000001647621446635226000206370ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Christoph Lipka * Saya Sugiura * * \copyright Copyright © 2015-2018 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_gateway.c */ #include #include #include #include #include #include #include #include #include #include #include "dlt_gateway.h" #include "dlt_gateway_internal.h" #include "dlt_config_file_parser.h" #include "dlt_common.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common_cfg.h" #include "dlt_daemon_event_handler.h" #include "dlt_daemon_connection.h" #include "dlt_daemon_client.h" #include "dlt_daemon_offline_logstorage.h" /** * Check if given string is a valid IP address * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_ip(DltGatewayConnection *con, char *value) { struct sockaddr_in sa; int ret = DLT_RETURN_ERROR; if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } ret = inet_pton(AF_INET, value, &(sa.sin_addr)); /* valid IP address */ if (ret != 0) { con->ip_address = strdup(value); if (con->ip_address == NULL) { dlt_log(LOG_ERR, "Cannot copy passive node IP address string\n"); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } else { dlt_log(LOG_ERR, "IP address is not valid\n"); } return DLT_RETURN_ERROR; } /** * Check port number * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_port(DltGatewayConnection *con, char *value) { long int tmp = -1; if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } errno = 0; tmp = strtol(value, NULL, 10); if ((errno == ERANGE && (tmp == LONG_MAX || tmp == LONG_MIN)) || (errno != 0 && tmp == 0)) { dlt_vlog(LOG_ERR, "%s: cannot convert port number\n", __func__); return DLT_RETURN_ERROR; } /* port ranges for unprivileged applications */ if ((tmp > IPPORT_RESERVED) && ((unsigned)tmp <= USHRT_MAX)) { con->port = (int)tmp; return DLT_RETURN_OK; } else { dlt_log(LOG_ERR, "Port number is invalid\n"); } return DLT_RETURN_ERROR; } /** * Check ECU name * * @param con DltGatewayConnection to be updated * @param value string to be used as ECU identifier * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_ecu(DltGatewayConnection *con, char *value) { if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } con->ecuid = strdup(value); if (con->ecuid == NULL) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } /** * Check connection trigger * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_connect_trigger(DltGatewayConnection *con, char *value) { if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (strncasecmp(value, "OnStartup", strlen("OnStartup")) == 0) { con->trigger = DLT_GATEWAY_ON_STARTUP; } else if (strncasecmp(value, "OnDemand", strlen("OnDemand")) == 0) { con->trigger = DLT_GATEWAY_ON_DEMAND; } else { dlt_log(LOG_ERR, "Wrong connection trigger state given.\n"); con->trigger = DLT_GATEWAY_UNDEFINED; return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } /** * Check connection timeout value * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_timeout(DltGatewayConnection *con, char *value) { if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } con->timeout = (int)strtol(value, NULL, 10); if (con->timeout >= 0) return DLT_RETURN_OK; return DLT_RETURN_ERROR; } /** * Check connection interval value in General section * * @param con DltGateway to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_interval(DltGateway *gateway, char *value) { if ((gateway == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } gateway->interval = (int)strtol(value, NULL, 10); if (gateway->interval > 0) return DLT_RETURN_OK; return DLT_RETURN_ERROR; } /** * Check the value for SendSerialHeader * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_send_serial(DltGatewayConnection *con, char *value) { if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } con->send_serial = !!((int)strtol(value, NULL, 10)); return DLT_RETURN_OK; } /** * Allocate passive control messages * * @param con DltGatewayConnection to be updated * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_allocate_control_messages(DltGatewayConnection *con) { if (con == NULL) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (con->p_control_msgs == NULL) { con->p_control_msgs = calloc(1, sizeof(DltPassiveControlMessage)); if (!con->p_control_msgs) { dlt_log(LOG_ERR, "Passive Control Message could not be allocated\n"); return DLT_RETURN_ERROR; } } else { con->p_control_msgs->next = calloc(1, sizeof(DltPassiveControlMessage)); if (!con->p_control_msgs->next) { dlt_log(LOG_ERR, "Passive Control Message could not be allocated\n"); return DLT_RETURN_ERROR; } con->p_control_msgs = con->p_control_msgs->next; } return DLT_RETURN_OK; } /** * Check the specified control messages identifier * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_control_messages(DltGatewayConnection *con, char *value) { /* list of allowed clients given */ char *token = NULL; char *rest = NULL; DltPassiveControlMessage *head = NULL; if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (strlen(value) == 0) return DLT_RETURN_OK; /* set on startup control msg id and interval*/ token = strtok_r(value, ",", &rest); while (token != NULL) { if (dlt_gateway_allocate_control_messages(con) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Passive Control Message could not be allocated\n"); return DLT_RETURN_ERROR; } con->p_control_msgs->id = strtol(token, NULL, 16); con->p_control_msgs->user_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECT; con->p_control_msgs->type = CONTROL_MESSAGE_ON_STARTUP; con->p_control_msgs->req = CONTROL_MESSAGE_NOT_REQUESTED; con->p_control_msgs->interval = -1; if (head == NULL) head = con->p_control_msgs; if ((errno == EINVAL) || (errno == ERANGE)) { dlt_vlog(LOG_ERR, "Control message ID is not an integer: %s\n", token); return DLT_RETURN_ERROR; } else if ((con->p_control_msgs->id < DLT_SERVICE_ID_SET_LOG_LEVEL) || (con->p_control_msgs->id >= DLT_SERVICE_ID_LAST_ENTRY)) { dlt_vlog(LOG_ERR, "Control message ID is not valid: %s\n", token); return DLT_RETURN_ERROR; } token = strtok_r(NULL, ",", &rest); } /* get back to head */ con->p_control_msgs = head; con->head = head; return DLT_RETURN_OK; } /** * Check the specified periodic control messages identifier * * @param con DltGatewayConnection to be updated * @param value string to be tested * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_periodic_control_messages( DltGatewayConnection *con, char *value) { char *token = NULL; char *rest = NULL; DltPassiveControlMessage *head = NULL; if ((con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (strlen(value) == 0) return DLT_RETURN_OK; /* store head address */ head = con->p_control_msgs; /* set periodic control msg id and interval*/ token = strtok_r(value, ",", &rest); while (token != NULL) { char *p_token = NULL; char *p_rest = NULL; uint32_t id = 0; p_token = strtok_r(token, ":", &p_rest); if ((p_token != NULL) && (strlen(p_token) != 0)) { id = strtol(p_token, NULL, 16); /* get back to head */ con->p_control_msgs = head; /* check if there is already id set in p_control_msgs */ while (con->p_control_msgs != NULL) { if (con->p_control_msgs->id == id) { con->p_control_msgs->type = CONTROL_MESSAGE_BOTH; con->p_control_msgs->interval = strtol(p_rest, NULL, 10); if (con->p_control_msgs->interval <= 0) dlt_vlog(LOG_WARNING, "%s interval is %d. It won't be send periodically.\n", dlt_get_service_name(con->p_control_msgs->id), con->p_control_msgs->interval); break; } con->p_control_msgs = con->p_control_msgs->next; } /* if the id is not added yet, p_control_msgs supposed to be NULL */ if (con->p_control_msgs == NULL) { /* get back to head */ con->p_control_msgs = head; /* go to last pointer */ while (con->p_control_msgs != NULL) { if (con->p_control_msgs->next == NULL) break; con->p_control_msgs = con->p_control_msgs->next; } if (dlt_gateway_allocate_control_messages(con) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Passive Control Message could not be allocated\n"); return DLT_RETURN_ERROR; } con->p_control_msgs->id = id; con->p_control_msgs->user_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECT; con->p_control_msgs->type = CONTROL_MESSAGE_PERIODIC; con->p_control_msgs->req = CONTROL_MESSAGE_NOT_REQUESTED; con->p_control_msgs->interval = strtol(p_rest, NULL, 10); if (con->p_control_msgs->interval <= 0) dlt_vlog(LOG_WARNING, "%s interval is %d. It won't be send periodically.\n", dlt_get_service_name(con->p_control_msgs->id), con->p_control_msgs->interval); if (head == NULL) head = con->p_control_msgs; } } if ((errno == EINVAL) || (errno == ERANGE)) { dlt_vlog(LOG_ERR, "Control message ID is not an integer: %s\n", p_token); return DLT_RETURN_ERROR; } else if ((con->p_control_msgs->id < DLT_SERVICE_ID_SET_LOG_LEVEL) || (con->p_control_msgs->id >= DLT_SERVICE_ID_LAST_ENTRY)) { dlt_vlog(LOG_ERR, "Control message ID is not valid: %s\n", p_token); return DLT_RETURN_ERROR; } token = strtok_r(NULL, ",", &rest); } /* get back to head */ con->p_control_msgs = head; con->head = head; return DLT_RETURN_OK; } /** * Expected entries for a passive node configuration * Caution: after changing entries here, * dlt_gateway_check_param needs to be updated as well * */ DLT_STATIC DltGatewayConf configuration_entries[GW_CONF_COUNT] = { [GW_CONF_IP_ADDRESS] = { .key = "IPaddress", .func = dlt_gateway_check_ip, .is_opt = 0 }, [GW_CONF_PORT] = { .key = "Port", .func = dlt_gateway_check_port, .is_opt = 1 }, [GW_CONF_ECUID] = { .key = "EcuID", .func = dlt_gateway_check_ecu, .is_opt = 0 }, [GW_CONF_CONNECT] = { .key = "Connect", .func = dlt_gateway_check_connect_trigger, .is_opt = 1 }, [GW_CONF_TIMEOUT] = { .key = "Timeout", .func = dlt_gateway_check_timeout, .is_opt = 0 }, [GW_CONF_SEND_CONTROL] = { .key = "SendControl", .func = dlt_gateway_check_control_messages, .is_opt = 1 }, [GW_CONF_SEND_PERIODIC_CONTROL] = { .key = "SendPeriodicControl", .func = dlt_gateway_check_periodic_control_messages, .is_opt = 1 }, [GW_CONF_SEND_SERIAL_HEADER] = { .key = "SendSerialHeader", .func = dlt_gateway_check_send_serial, .is_opt = 1 } }; DLT_STATIC DltGatewayGeneralConf general_entries[GW_CONF_COUNT] = { [GW_CONF_GENERAL_INTERVAL] = { .key = "Interval", .func = dlt_gateway_check_interval, .is_opt = 1 } }; #define DLT_GATEWAY_NUM_PROPERTIES_MAX GW_CONF_COUNT /** * Check if gateway connection general configuration parameter is valid. * * @param gateway DltGateway * @param ctype DltGatwayGeneralConnection property * @param value specified property value from configuration file * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_general_param(DltGateway *gateway, DltGatewayGeneralConfType ctype, char *value) { if ((gateway == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (ctype < GW_CONF_GENEREL_COUNT) return general_entries[ctype].func(gateway, value); return DLT_RETURN_ERROR; } /** * Check if gateway connection configuration parameter is valid. * * @param gateway DltGateway * @param con DltGatewayConnection * @param ctype DltGatwayConnection property * @param value specified property value from configuration file * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_check_param(DltGateway *gateway, DltGatewayConnection *con, DltGatewayConfType ctype, char *value) { if ((gateway == NULL) || (con == NULL) || (value == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (ctype < GW_CONF_COUNT) return configuration_entries[ctype].func(con, value); return DLT_RETURN_ERROR; } /** * Store gateway connection in internal data structure * * @param gateway DltGatway * @param tmp DltGatewayConnection * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_store_connection(DltGateway *gateway, DltGatewayConnection *tmp, int verbose) { int i = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((gateway == NULL) || (tmp == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* find next free entry in connection array */ while (i < gateway->num_connections) { if (gateway->connections[i].status == DLT_GATEWAY_UNINITIALIZED) break; i++; } if (&(gateway->connections[i]) == NULL) return DLT_RETURN_ERROR; /* store values */ gateway->connections[i].ip_address = strdup(tmp->ip_address); gateway->connections[i].ecuid = strdup(tmp->ecuid); gateway->connections[i].sock_domain = tmp->sock_domain; gateway->connections[i].sock_type = tmp->sock_type; gateway->connections[i].sock_protocol = tmp->sock_protocol; gateway->connections[i].port = tmp->port; gateway->connections[i].trigger = tmp->trigger; gateway->connections[i].timeout = tmp->timeout; gateway->connections[i].handle = 0; gateway->connections[i].status = DLT_GATEWAY_INITIALIZED; gateway->connections[i].p_control_msgs = tmp->p_control_msgs; gateway->connections[i].head = tmp->head; gateway->connections[i].send_serial = tmp->send_serial; if (dlt_client_init_port(&gateway->connections[i].client, gateway->connections[i].port, verbose) != 0) { free(gateway->connections[i].ip_address); gateway->connections[i].ip_address = NULL; free(gateway->connections[i].ecuid); gateway->connections[i].ecuid = NULL; free(gateway->connections[i].p_control_msgs); gateway->connections[i].p_control_msgs = NULL; dlt_log(LOG_CRIT, "dlt_client_init_port() failed for gateway connection\n"); return DLT_RETURN_ERROR; } /* setup DltClient Structure */ if (dlt_client_set_server_ip(&gateway->connections[i].client, gateway->connections[i].ip_address) == -1) { dlt_log(LOG_ERR, "dlt_client_set_server_ip() failed for gateway connection \n"); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } /** * Read configuration file and initialize connection data structures * * @param gateway DltGateway * @param config_file Gateway configuration * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_configure(DltGateway *gateway, char *config_file, int verbose) { int ret = 0; int i = 0; DltConfigFile *file = NULL; int num_sections = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((gateway == NULL) || (config_file == 0) || (config_file[0] == '\0')) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* read configuration file */ file = dlt_config_file_init(config_file); if(file == NULL) { return DLT_RETURN_ERROR; } /* get number of entries and allocate memory to store information */ ret = dlt_config_file_get_num_sections(file, &num_sections); if (ret != 0) { dlt_config_file_release(file); dlt_log(LOG_ERR, "Invalid number of sections in configuration file\n"); return DLT_RETURN_ERROR; } ret = dlt_config_file_check_section_name_exists(file, DLT_GATEWAY_GENERAL_SECTION_NAME); if (ret == -1) { /* * No General section in configuration file. * Try to use default for interval. */ gateway->num_connections = num_sections; dlt_vlog(LOG_WARNING, "Missing General section in gateway. Using default interval %d (secs)\n", gateway->interval); } else { /* * Since the General section is also counted in num_sections, * so number of connections must be number of sections - 1. */ gateway->num_connections = num_sections - 1; } gateway->connections = calloc(gateway->num_connections, sizeof(DltGatewayConnection)); if (gateway->connections == NULL) { dlt_config_file_release(file); dlt_log(LOG_CRIT, "Memory allocation for gateway connections failed\n"); return DLT_RETURN_ERROR; } for (i = 0; i < num_sections; i++) { DltGatewayConnection tmp; int invalid = 0; DltGatewayConfType j = 0; DltGatewayGeneralConfType g = 0; char section[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' }; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' }; memset(&tmp, 0, sizeof(tmp)); /* Set default */ tmp.send_serial = gateway->send_serial; tmp.port = DLT_DAEMON_TCP_PORT; ret = dlt_config_file_get_section_name(file, i, section); if (ret != 0) { dlt_log(LOG_WARNING, "Get section name failed\n"); continue; } if (strncmp(section, DLT_GATEWAY_GENERAL_SECTION_NAME, sizeof(DLT_GATEWAY_GENERAL_SECTION_NAME)) == 0) { for (g = 0; g < GW_CONF_GENEREL_COUNT; g++) { ret = dlt_config_file_get_value(file, section, general_entries[g].key, value); if ((ret != 0) && general_entries[g].is_opt) { /* Use default values for this key */ dlt_vlog(LOG_WARNING, "Using default for %s.\n", general_entries[g].key); continue; } else if (ret != 0) { dlt_vlog(LOG_WARNING, "Missing configuration for %s.\n", general_entries[g].key); break; } /* check value and store general configuration */ ret = dlt_gateway_check_general_param(gateway, g, value); if (ret != 0) dlt_vlog(LOG_ERR, "Configuration %s = %s is invalid. Using default.\n", general_entries[g].key, value); } } else { for (j = 0; j < GW_CONF_COUNT; j++) { ret = dlt_config_file_get_value(file, section, configuration_entries[j].key, value); if ((ret != 0) && configuration_entries[j].is_opt) { /* Use default values for this key */ dlt_vlog(LOG_WARNING, "Using default for %s.\n", configuration_entries[j].key); continue; } else if (ret != 0) { dlt_vlog(LOG_WARNING, "Missing configuration for %s.\n", configuration_entries[j].key); invalid = 1; break; } /* check value and store temporary */ ret = dlt_gateway_check_param(gateway, &tmp, j, value); if (ret != 0) dlt_vlog(LOG_ERR, "Configuration %s = %s is invalid.\n" "Using default.\n", configuration_entries[j].key, value); } if (!tmp.ip_address) { invalid = 1; } if (invalid) { dlt_vlog(LOG_ERR, "%s configuration is invalid.\n" "Ignoring.\n", section); } else { ret = dlt_gateway_store_connection(gateway, &tmp, verbose); if (ret != 0) dlt_log(LOG_ERR, "Storing gateway connection data failed\n"); } } /* strdup used inside some get_value function */ if (tmp.ecuid != NULL) { free(tmp.ecuid); tmp.ecuid = NULL; } if (tmp.ip_address != NULL) { free(tmp.ip_address); tmp.ip_address = NULL; } } dlt_config_file_release(file); return ret; } int dlt_gateway_init(DltDaemonLocal *daemon_local, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (daemon_local == NULL) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } DltGateway *gateway = &daemon_local->pGateway; if (gateway != NULL) { /* Get default value from daemon_local */ gateway->send_serial = daemon_local->flags.lflag; gateway->interval = DLT_GATEWAY_TIMER_DEFAULT_INTERVAL; if (dlt_gateway_configure(gateway, daemon_local->flags.gatewayConfigFile, verbose) != 0) { dlt_log(LOG_ERR, "Gateway initialization failed\n"); return DLT_RETURN_ERROR; } } else { dlt_log(LOG_CRIT, "Pointer to Gateway structure is NULL\n"); return DLT_RETURN_ERROR; } /* ignore return value */ dlt_gateway_establish_connections(gateway, daemon_local, verbose); return DLT_RETURN_OK; } void dlt_gateway_deinit(DltGateway *gateway, int verbose) { DltPassiveControlMessage *msg; int i = 0; if (gateway == NULL) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return; } PRINT_FUNCTION_VERBOSE(verbose); for (i = 0; i < gateway->num_connections; i++) { DltGatewayConnection *c = &gateway->connections[i]; dlt_client_cleanup(&c->client, verbose); free(c->ip_address); c->ip_address = NULL; free(c->ecuid); c->ecuid = NULL; while (c->p_control_msgs != NULL) { msg = c->p_control_msgs->next; free(c->p_control_msgs); c->p_control_msgs = msg; } } free(gateway->connections); gateway->connections = NULL; } /** * If connection to passive node established, add to event loop * * @param daemon_local DltDaemonLocal * @param con DltGatewayConnection * @param verbose verbose flag * @return 0 on success, -1 otherwise */ DLT_STATIC int dlt_gateway_add_to_event_loop(DltDaemonLocal *daemon_local, DltGatewayConnection *con, int verbose) { DltPassiveControlMessage *control_msg = NULL; int sendtime = 1; if ((daemon_local == NULL) || (con == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* connection to passive node established, add to event loop */ con->status = DLT_GATEWAY_CONNECTED; con->reconnect_cnt = 0; con->timeout_cnt = 0; con->sendtime_cnt = 0; /* setup dlt connection and add to poll event loop here */ if (dlt_connection_create(daemon_local, &daemon_local->pEvent, con->client.sock, POLLIN, DLT_CONNECTION_GATEWAY) != 0) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); return DLT_RETURN_ERROR; } /* immediately send configured control messages */ control_msg = con->p_control_msgs; while (control_msg != NULL) { if ((control_msg->type == CONTROL_MESSAGE_ON_STARTUP) || (control_msg->type == CONTROL_MESSAGE_BOTH)) { if (dlt_gateway_send_control_message(con, control_msg, NULL, verbose) == DLT_RETURN_OK) control_msg->req = CONTROL_MESSAGE_REQUESTED; } /* multiply periodic sending time */ if (((control_msg->type == CONTROL_MESSAGE_PERIODIC) || (control_msg->type == CONTROL_MESSAGE_BOTH)) && (control_msg->interval > 0)) sendtime *= control_msg->interval; control_msg = control_msg->next; } /* set periodic sending time */ con->sendtime = sendtime; con->sendtime_cnt = con->sendtime; return DLT_RETURN_OK; } int dlt_gateway_establish_connections(DltGateway *gateway, DltDaemonLocal *daemon_local, int verbose) { int i = 0; int ret = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((gateway == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } for (i = 0; i < gateway->num_connections; i++) { DltGatewayConnection *con = &(gateway->connections[i]); DltPassiveControlMessage *control_msg = NULL; if (con == NULL) { dlt_log(LOG_CRIT, "Cannot retrieve gateway connection details\n"); return DLT_RETURN_ERROR; } if ((con->status != DLT_GATEWAY_CONNECTED) && (con->trigger != DLT_GATEWAY_ON_DEMAND) && (con->trigger != DLT_GATEWAY_DISABLED)) { ret = dlt_client_connect(&con->client, verbose); if (ret == 0) { /* setup dlt connection and add to poll event loop here */ if (dlt_gateway_add_to_event_loop(daemon_local, con, verbose) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); return DLT_RETURN_ERROR; } } else { dlt_log(LOG_DEBUG, "Passive Node is not up. Connection failed.\n"); con->timeout_cnt++; if (con->timeout > 0) { if (con->timeout_cnt > con->timeout) { con->trigger = DLT_GATEWAY_DISABLED; dlt_log(LOG_WARNING, "Passive Node connection retry timed out. " "Give up.\n"); } } else if (con->timeout == 0) { dlt_vlog(LOG_DEBUG, "Retried [%d] times\n", con->timeout_cnt); } } } else if ((con->status == DLT_GATEWAY_CONNECTED) && (con->trigger != DLT_GATEWAY_DISABLED)) { /* setup dlt connection and add to poll event loop here */ if (dlt_connection_create(daemon_local, &daemon_local->pEvent, con->client.sock, POLLIN, DLT_CONNECTION_GATEWAY) != 0) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); return DLT_RETURN_ERROR; } /* immediately send periodic configured control messages */ control_msg = con->p_control_msgs; while (control_msg != NULL) { if ((control_msg->type == CONTROL_MESSAGE_PERIODIC) || (control_msg->type == CONTROL_MESSAGE_BOTH)) { if (dlt_gateway_send_control_message(con, control_msg, NULL, verbose) == DLT_RETURN_OK) control_msg->req = CONTROL_MESSAGE_REQUESTED; } control_msg = control_msg->next; } /* check sendtime counter */ if (con->sendtime_cnt > 0) con->sendtime_cnt--; if (con->sendtime_cnt == 0) con->sendtime_cnt = con->sendtime; } } return DLT_RETURN_OK; } DltReceiver *dlt_gateway_get_connection_receiver(DltGateway *gateway, int fd) { int i = 0; if (gateway == NULL) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return NULL; } for (i = 0; i < gateway->num_connections; i++) { DltGatewayConnection *c = &gateway->connections[i]; if ((c->status == DLT_GATEWAY_CONNECTED) && (c->client.sock == fd)) return &c->client.receiver; } return NULL; } /** * Parse GET_LOG_INFO * * @param daemon DltDaemon * @param ecu Ecu ID * @param msg DltMessage * @param req 1 if requested from gateway, 0 otherwise * @param verbose verbose flag * @return Value from DltReturnValue enum */ DLT_STATIC DltReturnValue dlt_gateway_parse_get_log_info(DltDaemon *daemon, char *ecu, DltMessage *msg, int req, int verbose) { char resp_text[DLT_RECEIVE_BUFSIZE] = { '\0' }; DltServiceGetLogInfoResponse *resp = NULL; AppIDsType app; ContextIDsInfoType con; int i = 0; int j = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((msg == NULL) || (msg->databuffer == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceGetLogInfoResponse)) < 0) return DLT_RETURN_ERROR; /* if the request was send from gateway, clear all application and context list */ if (req == CONTROL_MESSAGE_REQUESTED) { /* clear application list */ if (dlt_daemon_applications_clear(daemon, ecu, verbose) == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Cannot clear applications list\n"); return DLT_RETURN_ERROR; } /* clear context list */ if (dlt_daemon_contexts_clear(daemon, ecu, verbose) == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Cannot clear contexts list\n"); return DLT_RETURN_ERROR; } } /* check response */ if (dlt_message_payload(msg, resp_text, DLT_RECEIVE_BUFSIZE, DLT_OUTPUT_ASCII, 0) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "GET_LOG_INFO payload failed\n"); return DLT_RETURN_ERROR; } /* prepare pointer to message request */ resp = (DltServiceGetLogInfoResponse *)calloc(1, sizeof(DltServiceGetLogInfoResponse)); if (resp == NULL) { dlt_log(LOG_ERR, "Get Log Info Response could not be allocated\n"); return DLT_RETURN_ERROR; } if (dlt_set_loginfo_parse_service_id(resp_text, &resp->service_id, &resp->status) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Parsing GET_LOG_INFO failed\n"); dlt_client_cleanup_get_log_info(resp); return DLT_RETURN_ERROR; } if (dlt_client_parse_get_log_info_resp_text(resp, resp_text) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Parsing GET_LOG_INFO failed\n"); dlt_client_cleanup_get_log_info(resp); return DLT_RETURN_ERROR; } for (i = 0; i < resp->log_info_type.count_app_ids; i++) { app = resp->log_info_type.app_ids[i]; /* add application */ if (dlt_daemon_application_add(daemon, app.app_id, 0, app.app_description, -1, ecu, verbose) == 0) { dlt_vlog(LOG_WARNING, "%s: dlt_daemon_application_add failed\n", __func__); dlt_client_cleanup_get_log_info(resp); return DLT_RETURN_ERROR; } for (j = 0; j < app.count_context_ids; j++) { con = app.context_id_info[j]; /* add context */ if (dlt_daemon_context_add(daemon, app.app_id, con.context_id, con.log_level, con.trace_status, 0, -1, con.context_description, ecu, verbose) == 0) { dlt_vlog(LOG_WARNING, "%s: dlt_daemon_context_add failed for %4s\n", __func__, app.app_id); dlt_client_cleanup_get_log_info(resp); return DLT_RETURN_ERROR; } } } /* free response */ dlt_client_cleanup_get_log_info(resp); return DLT_RETURN_OK; } /** * Parse GET_DEFAULT_LOG_LEVEL * * @param daemon DltDaemon * @param daemon_local DltDaemonLocal * @param ecu Ecu ID * @param msg DltMessage * @param verbose verbose flag * @return 0 on success, -1 otherwise */ DLT_STATIC int dlt_gateway_parse_get_default_log_level(DltDaemon *daemon, DltDaemonLocal *daemon_local, char *ecu, DltMessage *msg, int verbose) { DltServiceGetDefaultLogLevelResponse *resp = NULL; DltGatewayConnection *con = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon == NULL) || (daemon_local == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceGetDefaultLogLevelResponse)) < 0) { dlt_log(LOG_ERR, "Received data incomplete.\n"); return DLT_RETURN_ERROR; } /* prepare pointer to message request */ resp = (DltServiceGetDefaultLogLevelResponse *)(msg->databuffer); con = dlt_gateway_get_connection(&daemon_local->pGateway, ecu, verbose); if (con == NULL) { dlt_vlog(LOG_ERR, "No information about passive ECU: %s\n", ecu); return DLT_RETURN_ERROR; } con->default_log_level = resp->log_level; return DLT_RETURN_OK; } /** * Service offline logstorage * * @param daemon DltDaemon * @param daemon_local DltDaemonLocal * @param verbose int * @return 0 on success, -1 otherwise */ DLT_STATIC int dlt_gateway_control_service_logstorage(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { unsigned int connection_type = 0; int i = 0; if (daemon_local->flags.offlineLogstorageMaxDevices <= 0) { dlt_log(LOG_INFO, "Logstorage functionality not enabled or MAX device set is 0\n"); return DLT_RETURN_ERROR; } for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) { connection_type = daemon->storage_handle[i].connection_type; if (connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) /* Check if log level of running application needs an update */ dlt_daemon_logstorage_update_application_loglevel(daemon, daemon_local, i, verbose); } return DLT_RETURN_OK; } DltReturnValue dlt_gateway_process_passive_node_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { int i = 0; DltGateway *gateway = NULL; DltGatewayConnection *con = NULL; DltMessage msg = { 0 }; bool b_reset_receiver = false; if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } PRINT_FUNCTION_VERBOSE(verbose); gateway = &daemon_local->pGateway; if (gateway == NULL) { dlt_log(LOG_ERR, "Gateway structure is NULL\n"); return DLT_RETURN_ERROR; } for (i = 0; i < gateway->num_connections; i++) if ((gateway->connections[i].status == DLT_GATEWAY_CONNECTED) && (gateway->connections[i].client.sock == receiver->fd)) { con = &gateway->connections[i]; break; } if (con == NULL) { dlt_log(LOG_ERR, "Cannot associate fd to passive Node connection\n"); return DLT_RETURN_ERROR; } /* now the corresponding passive node connection is available */ if (dlt_message_init(&msg, verbose) == -1) { dlt_log(LOG_ERR, "Cannot initialize DLT message for passive node forwarding\n"); return DLT_RETURN_ERROR; } /* nearly copy and paste of dlt_client_main_loop function */ if (dlt_receiver_receive(receiver) <= 0) { /* No more data to be received */ if (dlt_message_free(&msg, verbose) < 0) { dlt_log(LOG_ERR, "Cannot free DLT message\n"); return DLT_RETURN_ERROR; } dlt_log(LOG_WARNING, "Connection to passive node lost\n"); if (con->reconnect_cnt < DLT_GATEWAY_RECONNECT_MAX) { dlt_log(LOG_WARNING, "Try to reconnect.\n"); con->reconnect_cnt += 1; con->timeout_cnt = 0; } else { con->status = DLT_GATEWAY_DISCONNECTED; if (dlt_event_handler_unregister_connection(&daemon_local->pEvent, daemon_local, receiver->fd) != 0) dlt_log(LOG_ERR, "Remove passive node Connection failed\n"); } return DLT_RETURN_OK; } while (dlt_message_read(&msg, (unsigned char *)receiver->buf, receiver->bytesRcvd, 0, verbose) == DLT_MESSAGE_ERROR_OK) { DltStandardHeaderExtra *header = (DltStandardHeaderExtra *) (msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)); /* only forward messages if the received ECUid is the expected one */ if (strncmp(header->ecu, con->ecuid, DLT_ID_SIZE) == 0) { uint32_t id; uint32_t id_tmp; DltPassiveControlMessage *control_msg = con->p_control_msgs; dlt_vlog(LOG_DEBUG, "Received ECUid (%.*s) similar to configured ECUid(%s). " "Forwarding message (%s).\n", DLT_ID_SIZE, header->ecu, con->ecuid, msg.databuffer); id_tmp = *((uint32_t *)(msg.databuffer)); id = DLT_ENDIAN_GET_32(msg.standardheader->htyp, id_tmp); /* if ID is GET_LOG_INFO, parse msg */ if (id == DLT_SERVICE_ID_GET_LOG_INFO) { while (control_msg) { if (control_msg->id == id) { if (dlt_gateway_parse_get_log_info(daemon, header->ecu, &msg, control_msg->req, verbose) == DLT_RETURN_ERROR) dlt_log(LOG_WARNING, "Parsing GET_LOG_INFO message failed!\n"); /* Check for logstorage */ dlt_gateway_control_service_logstorage(daemon, daemon_local, verbose); /* initialize the flag */ control_msg->req = CONTROL_MESSAGE_NOT_REQUESTED; break; } control_msg = control_msg->next; } } else if (id == DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL) { if (dlt_gateway_parse_get_default_log_level( daemon, daemon_local, header->ecu, &msg, verbose) == DLT_RETURN_ERROR) dlt_log(LOG_WARNING, "Parsing GET_DEFAULT_LOG_LEVEL message failed!\n"); } /* prepare storage header */ if (dlt_set_storageheader(msg.storageheader, msg.headerextra.ecu) == DLT_RETURN_ERROR) { dlt_vlog(LOG_ERR, "%s: Can't set storage header\n", __func__); return DLT_RETURN_ERROR; } dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, msg.headerbuffer, sizeof(DltStorageHeader), msg.headerbuffer + sizeof(DltStorageHeader), msg.headersize - sizeof(DltStorageHeader), msg.databuffer, msg.datasize, verbose); } else { /* otherwise remove this connection and do not connect again */ dlt_vlog(LOG_WARNING, "Received ECUid (%.*s) differs to configured ECUid(%s). " "Discard this message.\n", DLT_ID_SIZE, header->ecu, con->ecuid); /* disconnect from passive node */ con->status = DLT_GATEWAY_DISCONNECTED; con->trigger = DLT_GATEWAY_DISABLED; if (dlt_event_handler_unregister_connection(&daemon_local->pEvent, daemon_local, receiver->fd) != 0) dlt_log(LOG_ERR, "Remove passive node Connection failed\n"); dlt_log(LOG_WARNING, "Disconnect from passive node due to invalid ECUid\n"); /* it is possible that a partial log was received through the last recv call */ /* however, the rest will never be received since the socket will be closed by above method */ /* as such, we need to reset the receiver to prevent permanent corruption */ b_reset_receiver = true; } if (msg.found_serialheader) { if (dlt_receiver_remove(receiver, msg.headersize + msg.datasize - sizeof(DltStorageHeader) + sizeof(dltSerialHeader)) == -1) { /* Return value ignored */ dlt_message_free(&msg, verbose); return DLT_RETURN_ERROR; } } else if (dlt_receiver_remove(receiver, msg.headersize + msg.datasize - sizeof(DltStorageHeader)) == -1) { /* Return value ignored */ dlt_message_free(&msg, verbose); return DLT_RETURN_ERROR; } } if (b_reset_receiver) dlt_receiver_remove(receiver, receiver->bytesRcvd); if (dlt_receiver_move_to_begin(receiver) == -1) { /* Return value ignored */ dlt_message_free(&msg, verbose); return DLT_RETURN_ERROR; } if (dlt_message_free(&msg, verbose) == -1) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } int dlt_gateway_process_gateway_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *receiver, int verbose) { uint64_t expir = 0; ssize_t res = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((daemon_local == NULL) || (daemon == NULL) || (receiver == NULL)) { dlt_vlog(LOG_ERR, "%s: invalid parameters\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } res = read(receiver->fd, &expir, sizeof(expir)); if (res < 0) dlt_vlog(LOG_WARNING, "%s: Fail to read timer (%s)\n", __func__, strerror(errno)); /* Activity received on timer_wd, but unable to read the fd: * let's go on sending notification */ /* try to connect to passive nodes */ dlt_gateway_establish_connections(&daemon_local->pGateway, daemon_local, verbose); dlt_log(LOG_DEBUG, "Gateway Timer\n"); return DLT_RETURN_OK; } int dlt_gateway_forward_control_message(DltGateway *gateway, DltDaemonLocal *daemon_local, DltMessage *msg, char *ecu, int verbose) { int i = 0; int ret = 0; DltGatewayConnection *con = NULL; uint32_t id_tmp; uint32_t id; PRINT_FUNCTION_VERBOSE(verbose); if ((gateway == NULL) || (daemon_local == NULL) || (msg == NULL) || (ecu == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } for (i = 0; i < gateway->num_connections; i++) if (strncmp(gateway->connections[i].ecuid, ecu, DLT_ID_SIZE) == 0) { con = &gateway->connections[i]; break; } if (con == NULL) { dlt_log(LOG_WARNING, "Unknown passive node identifier\n"); return DLT_RETURN_ERROR; } if (con->status != DLT_GATEWAY_CONNECTED) { dlt_log(LOG_INFO, "Passive node is not connected\n"); return DLT_RETURN_ERROR; } if (con->send_serial) { /* send serial header */ ret = send(con->client.sock, (void *)dltSerialHeader, sizeof(dltSerialHeader), 0); if (ret == -1) { dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n"); return DLT_RETURN_ERROR; } } ret = send(con->client.sock, msg->headerbuffer + sizeof(DltStorageHeader), msg->headersize - sizeof(DltStorageHeader), 0); if (ret == -1) { dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n"); return DLT_RETURN_ERROR; } else { ret = send(con->client.sock, msg->databuffer, msg->datasize, 0); if (ret == -1) { dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n"); return DLT_RETURN_ERROR; } } id_tmp = *((uint32_t *)(msg->databuffer)); id = DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp); dlt_vlog(LOG_INFO, "Control message forwarded : %s\n", dlt_get_service_name(id)); return DLT_RETURN_OK; } int dlt_gateway_process_on_demand_request(DltGateway *gateway, DltDaemonLocal *daemon_local, char node_id[DLT_ID_SIZE], int connection_status, int verbose) { int i = 0; DltGatewayConnection *con = NULL; PRINT_FUNCTION_VERBOSE(verbose); if ((gateway == NULL) || (daemon_local == NULL) || (node_id == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* find connection by ECU id */ for (i = 0; i < gateway->num_connections; i++) { if (strncmp(node_id, gateway->connections[i].ecuid, DLT_ID_SIZE) == 0) { con = &gateway->connections[i]; break; } } if (con == NULL) { dlt_log(LOG_WARNING, "Specified ECUid not found\n"); return DLT_RETURN_ERROR; } if (connection_status == 1) { /* try to connect */ if (con->status != DLT_GATEWAY_CONNECTED) { if (dlt_client_connect(&con->client, verbose) == 0) { /* setup dlt connection and add to poll event loop here */ if (dlt_gateway_add_to_event_loop(daemon_local, con, verbose) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); return DLT_RETURN_ERROR; } } else { dlt_log(LOG_ERR, "Could not connect to passive node\n"); return DLT_RETURN_ERROR; } } else { dlt_log(LOG_INFO, "Passive node already connected\n"); } } else if (connection_status == 0) /* disconnect*/ { con->status = DLT_GATEWAY_DISCONNECTED; con->trigger = DLT_GATEWAY_ON_DEMAND; if (dlt_event_handler_unregister_connection(&daemon_local->pEvent, daemon_local, con->client.sock) != 0) dlt_log(LOG_ERR, "Remove passive node event handler connection failed\n"); } else { dlt_log(LOG_ERR, "Unknown command (connection_status)\n"); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } int dlt_gateway_send_control_message(DltGatewayConnection *con, DltPassiveControlMessage *control_msg, void *data, int verbose) { int ret = DLT_RETURN_OK; PRINT_FUNCTION_VERBOSE(verbose); if (con == NULL) { dlt_vlog(LOG_WARNING, "%s: Invalid parameter given\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* no (more) control message to be send */ if (control_msg->id == 0) return DLT_RETURN_ERROR; /* check sendtime counter and message interval */ /* sendtime counter is 0 on startup, otherwise positive value */ if ((control_msg->type != CONTROL_MESSAGE_ON_DEMAND) && (con->sendtime_cnt > 0)) { if (control_msg->interval <= 0) return DLT_RETURN_ERROR; if ((control_msg->type == CONTROL_MESSAGE_PERIODIC) || (control_msg->type == CONTROL_MESSAGE_BOTH)) { if ((con->sendtime_cnt - 1) % control_msg->interval != 0) return DLT_RETURN_ERROR; } } if (con->send_serial) { /* send serial header */ ret = send(con->client.sock, (void *)dltSerialHeader, sizeof(dltSerialHeader), 0); if (ret == -1) { dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n"); return DLT_RETURN_ERROR; } } switch (control_msg->id) { case DLT_SERVICE_ID_GET_LOG_INFO: return dlt_client_get_log_info(&con->client); break; case DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL: return dlt_client_get_default_log_level(&con->client); break; case DLT_SERVICE_ID_GET_SOFTWARE_VERSION: return dlt_client_get_software_version(&con->client); break; case DLT_SERVICE_ID_SET_LOG_LEVEL: if (data == NULL) { dlt_vlog(LOG_WARNING, "Insufficient data for %s received. Send control request failed.\n", dlt_get_service_name(control_msg->id)); return DLT_RETURN_ERROR; } DltServiceSetLogLevel *req = (DltServiceSetLogLevel *)data; return dlt_client_send_log_level(&con->client, req->apid, req->ctid, req->log_level); break; default: dlt_vlog(LOG_WARNING, "Cannot forward request: %s.\n", dlt_get_service_name(control_msg->id)); } return DLT_RETURN_OK; } DltGatewayConnection *dlt_gateway_get_connection(DltGateway *gateway, char *ecu, int verbose) { DltGatewayConnection *con = NULL; int i = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((gateway == NULL) || (ecu == NULL)) { dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); return con; } for (i = 0; i < gateway->num_connections; i++) { con = &gateway->connections[i]; if (strncmp(con->ecuid, ecu, DLT_ID_SIZE) == 0) return con; } dlt_vlog(LOG_ERR, "%s: No connection found\n", ecu); return con; } dlt-daemon-2.18.10/src/gateway/dlt_gateway.conf000066400000000000000000000017431446635226000213270ustar00rootroot00000000000000[General] ; Time interval for reconnection to passive Node in second. ; Interval=1 [PassiveNode1] IPaddress=192.168.2.11 ; TCP port. Default 3490 is used if no port is specified. ; Port=3490 ; passive nodes ECU identifier. Mandatory. EcuID=ECU2 ; Try connect to passive Node on DLT Daemon startup. Default OnStartup if not specified. ; Connect=OnStartup ; Stop connecting to passive node, if not successful after 10 retries. ; Set to 0 for endless retry. Timeout=10 ; Send following control messages after connection is established ; SendControl=0x03,0x04,0x13 ; Send Serial Header with control messages. Value in dlt.conf is used as default if not specified. ; SendSerialHeader=0 ; Send following control messages periodically () ; SendPeriodicControl=0x03:5,0x13:10 ; Supported Control messages: ; DLT_SERVICE_ID_GET_LOG_INFO 0x03 ; DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL 0x04 ; DLT_SERVICE_ID_GET_SOFTWARE_VERSION 0x13 dlt-daemon-2.18.10/src/gateway/dlt_gateway.h000066400000000000000000000166451446635226000206400ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Christoph Lipka * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_gateway.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_gateway.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef DLT_GATEWAY_H_ #define DLT_GATEWAY_H_ #include "dlt-daemon.h" #include "dlt_gateway_types.h" /** * Initialize the gateway to passive nodes * * TODO: Make path to configuration file configurable * * @param daemon_local pointer to DltDaemonLocal * @param verbose verbose flag * @return 0 on success, -1 on error */ int dlt_gateway_init(DltDaemonLocal *daemon_local, int verbose); /** * De-initialize the gateway. All internal data will be freed. * * @param g DltGateway pointer * @param verbose verbose flag */ void dlt_gateway_deinit(DltGateway *g, int verbose); /** * Establish all connections to passive nodes that are configured to be started * on daemon startup and add this connections to the main event loop. * * TODO: This function is called during gateway initialization and in main loop * whenever the poll returns. This may need to be improved. * * @param g DltGateway * @param daemon_local DltDaemonLocal * @param verbose verbose flag * @return 0 on success, -1 on error */ int dlt_gateway_establish_connections(DltGateway *g, DltDaemonLocal *daemon_local, int verbose); /** * Return the receiver for a given file descriptor * * @param g DltGateway * @param fd file descriptor * @return Pointer to DltReceiver on success, NULL otherwise */ DltReceiver *dlt_gateway_get_connection_receiver(DltGateway *g, int fd); /** * Process incoming messages from passive nodes * * @param daemon DltDaemon * @param daemon_local DltDaemonLocal * @param recv DltReceiver structure * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_process_passive_node_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *recv, int verbose); /** * Process gateway timer * * @param daemon DltDaemon * @param daemon_local DltDaemonLocal * @param rec DltReceiver * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_process_gateway_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, DltReceiver *rec, int verbose); /** * Forward control messages to the specified passive node DLT Daemon. * * @param g DltGateway * @param daemon_local DltDaemonLocal * @param msg DltMessage * @param ecu Identifier of the passive node * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_forward_control_message(DltGateway *g, DltDaemonLocal *daemon_local, DltMessage *msg, char *ecu, int verbose); /** * Process on demand connect/disconnect of passive nodes * * @param g DltGateway * @param daemon_local DltDaemonLocal * @param node_id Passive Node identifier * @param connection_status Connection status * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_process_on_demand_request(DltGateway *g, DltDaemonLocal *daemon_local, char *node_id, int connection_status, int verbose); /** * Send control message to passive node * * @param con DltGatewayConnection * @param control_msg DltPassiveControlMessage * @param data DltMessage * @param verbose verbose flag * @return 0 on success, -1 otherwise */ int dlt_gateway_send_control_message(DltGatewayConnection *con, DltPassiveControlMessage *control_msg, void *data, int verbose); /** * Gets the connection handle of passive node with specified ECU * * @param g DltGateway * @param ecu Identifier string * @param verbose verbose flag * @returns Gateway connection handle on success, NULL otherwise */ DltGatewayConnection *dlt_gateway_get_connection(DltGateway *g, char *ecu, int verbose); #endif dlt-daemon-2.18.10/src/gateway/dlt_gateway_internal.h000066400000000000000000000122021446635226000225150ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2018 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Aditya Paluri * * \copyright Copyright © 2018 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_gateway_internal.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_gateway_internal.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Aditya Paluri venkataaditya.paluri@in.bosch.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** ap Aditya Paluri ADIT ** *******************************************************************************/ #ifndef DLT_GATEWAY_INTERNAL_H_ #define DLT_GATEWAY_INTERNAL_H_ DLT_STATIC DltReturnValue dlt_gateway_check_ip(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_port(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_ecu(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_connect_trigger(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_timeout(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_send_serial(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_allocate_control_messages(DltGatewayConnection *con); DLT_STATIC DltReturnValue dlt_gateway_check_control_messages(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_periodic_control_messages(DltGatewayConnection *con, char *value); DLT_STATIC DltReturnValue dlt_gateway_check_param(DltGateway *gateway, DltGatewayConnection *con, DltGatewayConfType ctype, char *value); int dlt_gateway_configure(DltGateway *gateway, char *config_file, int verbose); int dlt_gateway_store_connection(DltGateway *gateway, DltGatewayConnection *tmp, int verbose); DLT_STATIC DltReturnValue dlt_gateway_parse_get_log_info(DltDaemon *daemon, char *ecu, DltMessage *msg, int req, int verbose); #endif dlt-daemon-2.18.10/src/gateway/dlt_gateway_types.h000066400000000000000000000162411446635226000220540ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Christoph Lipka * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_gateway_types.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_gateway_types.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef DLT_GATEWAY_TYPES_H_ #define DLT_GATEWAY_TYPES_H_ #include "dlt_protocol.h" #include "dlt_client.h" #define DLT_GATEWAY_CONFIG_PATH CONFIGURATION_FILES_DIR "/dlt_gateway.conf" #define DLT_GATEWAY_TIMER_DEFAULT_INTERVAL 1 #define DLT_GATEWAY_GENERAL_SECTION_NAME "General" #define DLT_GATEWAY_RECONNECT_MAX 1 /* reconnect once after connection loss */ /* maximum number of control messages that can be send after connection is * established */ #define DLT_GATEWAY_MAX_STARTUP_CTRL_MSG 10 typedef enum { DLT_GATEWAY_UNINITIALIZED, DLT_GATEWAY_INITIALIZED, DLT_GATEWAY_CONNECTED, DLT_GATEWAY_DISCONNECTED } connection_status; typedef enum { DLT_GATEWAY_UNDEFINED = -1, DLT_GATEWAY_ON_STARTUP, /* connect directly on startup */ DLT_GATEWAY_ON_DEMAND, /* connect on demand only */ DLT_GATEWAY_DISABLED /* disable this connection due to problems */ } connection_trigger; typedef enum { CONTROL_MESSAGE_UNDEFINED = -1, CONTROL_MESSAGE_ON_STARTUP, /* send on startup */ CONTROL_MESSAGE_PERIODIC, /* send periodically */ CONTROL_MESSAGE_BOTH, /* send on startup and periodically */ CONTROL_MESSAGE_ON_DEMAND /* send on demand only */ } control_msg_trigger; typedef enum { CONTROL_MESSAGE_REQUEST_UNDEFINED = -1, CONTROL_MESSAGE_NOT_REQUESTED, /* control msg not requested (default) */ CONTROL_MESSAGE_REQUESTED /* control msg requested */ } control_msg_request; /* Passive control message */ typedef struct DltPassiveControlMessage { uint32_t id; /* msg ID */ uint32_t user_id; control_msg_trigger type; /* on startup or periodic or both */ control_msg_request req; /* whether it is requested from gateway or not */ int interval; /* interval for periodic sending. if on startup, -1 */ struct DltPassiveControlMessage *next; /* for multiple passive control message */ } DltPassiveControlMessage; /* DLT Gateway connection structure */ typedef struct { int handle; /* connection handle */ connection_status status; /* connected/disconnected */ char *ecuid; /* name of passive node */ char *ip_address; /* IP address */ int sock_domain; /* socket domain */ int sock_type; /* socket type */ int sock_protocol; /* socket protocol */ int port; /* port */ connection_trigger trigger; /* connection trigger */ int timeout; /* connection timeout */ int timeout_cnt; /* connection timeout counter */ int reconnect_cnt; /* reconnection counter */ int sendtime; /* periodic sending max time */ int sendtime_cnt; /* periodic sending counter */ DltPassiveControlMessage *p_control_msgs; /* passive control msgs */ DltPassiveControlMessage *head; /* to go back to the head pointer of p_control_msgs */ int send_serial; /* Send serial header with control messages */ DltClient client; /* DltClient structure */ int default_log_level; /* Default Log Level on passive node */ } DltGatewayConnection; /* DltGateway structure */ typedef struct { int send_serial; /* Default: Send serial header with control messages */ DltGatewayConnection *connections; /* pointer to connections */ int num_connections; /* number of connections */ int interval; /* interval of retry connection */ } DltGateway; typedef struct { char *key; /* The configuration key*/ int (*func)(DltGatewayConnection *con, char *value); /* Conf handler */ int is_opt; /* If the configuration is optional or not */ } DltGatewayConf; typedef struct { char *key; /* The configuration key*/ int (*func)(DltGateway *gateway, char *value); /* Conf handler */ int is_opt; /* If the configuration is optional or not */ } DltGatewayGeneralConf; typedef enum { GW_CONF_IP_ADDRESS = 0, GW_CONF_PORT, GW_CONF_ECUID, GW_CONF_CONNECT, GW_CONF_TIMEOUT, GW_CONF_SEND_CONTROL, GW_CONF_SEND_PERIODIC_CONTROL, GW_CONF_SEND_SERIAL_HEADER, GW_CONF_COUNT } DltGatewayConfType; typedef enum { GW_CONF_GENERAL_INTERVAL = 0, GW_CONF_GENEREL_COUNT } DltGatewayGeneralConfType; #endif /* DLT_GATEWAY_TYPES_H_ */ dlt-daemon-2.18.10/src/kpi/000077500000000000000000000000001446635226000152715ustar00rootroot00000000000000dlt-daemon-2.18.10/src/kpi/CMakeLists.txt000066400000000000000000000015071446635226000200340ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### set (dlt_kpi_SRCS dlt-kpi.c dlt-kpi-options.c dlt-kpi-process.c dlt-kpi-process-list.c dlt-kpi-common.c dlt-kpi-interrupt.c) add_executable (dlt-kpi ${dlt_kpi_SRCS}) target_link_libraries (dlt-kpi dlt) set_target_properties(dlt-kpi PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-kpi RUNTIME DESTINATION bin COMPONENT base) INSTALL(FILES dlt-kpi.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) dlt-daemon-2.18.10/src/kpi/dlt-kpi-common.c000066400000000000000000000053641446635226000202770ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-common.c */ #include "dlt-kpi-common.h" static int dlt_kpi_cpu_count = -1; DltReturnValue dlt_kpi_read_file_compact(char *filename, char **target) { if ((filename == NULL) || (target == NULL)) { fprintf(stderr, "%s: Nullpointer parameter!\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } char buffer[BUFFER_SIZE]; int ret = dlt_kpi_read_file(filename, buffer, BUFFER_SIZE); if (ret < DLT_RETURN_OK) return ret; if ((*target = malloc(strlen(buffer) + 1)) == NULL) { fprintf(stderr, "Out of memory!\n"); return DLT_RETURN_ERROR; } memcpy(*target, buffer, strlen(buffer) + 1); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_read_file(char *filename, char *buffer, uint maxLength) { if ((filename == NULL) || (buffer == NULL)) { fprintf(stderr, "%s: Nullpointer parameter!\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } FILE *file = fopen(filename, "r"); if (file == NULL) /* fprintf(stderr, "Could not read file %s\n", filename); */ return DLT_RETURN_ERROR; int buflen = fread(buffer, 1, maxLength - 1, file); buffer[buflen] = '\0'; fclose(file); return DLT_RETURN_OK; } int dlt_kpi_read_cpu_count() { char buffer[BUFFER_SIZE]; int ret = dlt_kpi_read_file("/proc/cpuinfo", buffer, sizeof(buffer)); if (ret != 0) { fprintf(stderr, "dlt_kpi_get_cpu_count(): Could not read /proc/cpuinfo\n"); return -1; } char *delim = "[] \t\n"; char *tok = strtok(buffer, delim); if (tok == NULL) { fprintf(stderr, "dlt_kpi_get_cpu_count(): Could not extract token\n"); return -1; } int num = 0; do { if (strcmp(tok, "processor") == 0) num++; tok = strtok(NULL, delim); } while (tok != NULL); return num; } int dlt_kpi_get_cpu_count() { if (dlt_kpi_cpu_count <= 0) { dlt_kpi_cpu_count = dlt_kpi_read_cpu_count(); if (dlt_kpi_cpu_count <= 0) { fprintf(stderr, "Could not get CPU count\n"); dlt_kpi_cpu_count = -1; } } return dlt_kpi_cpu_count; } dlt-daemon-2.18.10/src/kpi/dlt-kpi-common.h000066400000000000000000000020331446635226000202720ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-common.h */ #ifndef SRC_KPI_DLT_KPI_COMMON_H_ #define SRC_KPI_DLT_KPI_COMMON_H_ #include #include #include #include #define BUFFER_SIZE 4096 DltReturnValue dlt_kpi_read_file(char *filename, char *buffer, uint maxLength); DltReturnValue dlt_kpi_read_file_compact(char *filename, char **target); int dlt_kpi_get_cpu_count(); #endif /* SRC_KPI_DLT_KPI_COMMON_H_ */ dlt-daemon-2.18.10/src/kpi/dlt-kpi-interrupt.c000066400000000000000000000117341446635226000210410ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-interrupt.c */ #include "dlt-kpi-interrupt.h" DltReturnValue dlt_kpi_log_interrupts(DltContext *ctx, DltLogLevelType log_level) { if (ctx == NULL) { fprintf(stderr, "%s: Nullpointer parameter (NULL) !\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } char buffer[BUFFER_SIZE]; *buffer = '\0'; char file_buffer[BUFFER_SIZE]; char *token, *delim = " \t", *delim2 = " \t\n", *check; int head_line = 1, first_row = 1, cpu_count = 0, column = 0, buffer_offset = 0; DltReturnValue ret; if ((ret = dlt_kpi_read_file("/proc/interrupts", file_buffer, BUFFER_SIZE)) < DLT_RETURN_OK) return ret; token = strtok(file_buffer, delim); while (token != NULL) { if (head_line) { if ((strlen(token) > 3) && (token[0] == 'C') && (token[1] == 'P') && (token[2] == 'U')) { cpu_count++; } else if (cpu_count <= 0) { fprintf(stderr, "%s: Could not parse CPU count !\n", __func__); return DLT_RETURN_ERROR; } else if (strcmp(token, "\n") == 0) { head_line = 0; } token = strtok(NULL, delim); } else { int tokenlen = strlen(token); if (token[tokenlen - 1] == ':') { column = 0; if (first_row) first_row = 0; else buffer_offset += snprintf(buffer + buffer_offset, BUFFER_SIZE - buffer_offset, "\n"); } if (column == 0) { /* IRQ number */ buffer_offset += snprintf(buffer + buffer_offset, BUFFER_SIZE - buffer_offset, "%.*s;", tokenlen - 1, token); } else if (column <= cpu_count) { long int interrupt_count = strtol(token, &check, 10); if (*check != '\0') { fprintf(stderr, "%s: Could not parse interrupt count for CPU !\n", __func__); return DLT_RETURN_ERROR; } buffer_offset += snprintf(buffer + buffer_offset, BUFFER_SIZE - buffer_offset, "cpu%d:%ld;", column - 1, interrupt_count); } column++; token = strtok(NULL, delim2); } } /* synchronization message */ DLT_LOG(*ctx, log_level, DLT_STRING("IRQ"), DLT_STRING("BEG")); DltContextData ctx_data; if ((ret = dlt_user_log_write_start(ctx, &ctx_data, log_level)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_start() returned error\n", __func__); return ret; } if ((ret = dlt_user_log_write_string(&ctx_data, "IRQ")) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_string() returned error\n", __func__); return ret; } token = strtok(buffer, "\n"); while (token != NULL) { if (dlt_user_log_write_string(&ctx_data, token) < DLT_RETURN_OK) { /* message buffer full, start new one */ if ((ret = dlt_user_log_write_finish(&ctx_data)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_finish() returned error\n", __func__); return ret; } if ((ret = dlt_user_log_write_start(ctx, &ctx_data, log_level)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_start() returned error\n", __func__); return ret; } if ((ret = dlt_user_log_write_string(&ctx_data, "IRQ")) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_string() returned error\n", __func__); return ret; } } else { token = strtok(NULL, "\n"); } } if ((ret = dlt_user_log_write_finish(&ctx_data)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_finish() returned error\n", __func__); return ret; } /* synchronization message */ DLT_LOG(*ctx, log_level, DLT_STRING("IRQ"), DLT_STRING("END")); return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/kpi/dlt-kpi-interrupt.h000066400000000000000000000016051446635226000210420ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-interrupt.h */ #ifndef SRC_KPI_DLT_KPI_INTERRUPT_H_ #define SRC_KPI_DLT_KPI_INTERRUPT_H_ #include "dlt.h" #include "dlt-kpi-common.h" DltReturnValue dlt_kpi_log_interrupts(DltContext *ctx, DltLogLevelType log_level); #endif /* SRC_KPI_DLT_KPI_INTERRUPT_H_ */ dlt-daemon-2.18.10/src/kpi/dlt-kpi-options.c000066400000000000000000000155721446635226000205040ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-options.c */ #include "dlt-kpi.h" /** * Print information how to use this program. */ void usage(char *prog_name) { char version[255]; dlt_get_version(version, 255); printf("Usage: %s [options]\n", prog_name); printf("Application to forward information from the /proc/ file system to DLT.\n"); printf("%s\n", version); printf("Options:\n"); /*printf(" -d Daemonize. Detach from terminal and run in background.\n"); */ printf(" -c filename Use configuration file. \n"); printf(" Default: %s\n", DEFAULT_CONF_FILE); printf(" -h This help message.\n"); } /** * Initialize command line options with default values. */ void dlt_kpi_init_cli_options(DltKpiOptions *options) { options->configurationFileName = DEFAULT_CONF_FILE; options->customConfigFile = 0; } void dlt_kpi_free_cli_options(DltKpiOptions *options) { if (options->customConfigFile) free(options->configurationFileName); } DltReturnValue dlt_kpi_read_command_line(DltKpiOptions *options, int argc, char **argv) { if (options == NULL) { fprintf(stderr, "%s: Nullpointer parameter\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } dlt_kpi_init_cli_options(options); int opt; while ((opt = getopt(argc, argv, "c:h")) != -1) switch (opt) { case 'c': { if ((options->configurationFileName = malloc(strlen(optarg) + 1)) == 0) { fprintf(stderr, "Out of memory!\n"); return DLT_RETURN_ERROR; } strcpy(options->configurationFileName, optarg); /* strcpy unritical here, because size matches exactly the size to be copied */ options->customConfigFile = 1; break; } case 'h': { usage(argv[0]); exit(0); return -1; /*for parasoft */ } default: { fprintf(stderr, "Unknown option: %c\n", optopt); usage(argv[0]); return DLT_RETURN_ERROR; } } return DLT_RETURN_OK; } /** * Initialize configuration to default values. */ void dlt_kpi_init_configuration(DltKpiConfig *config) { config->process_log_interval = 1000; config->irq_log_interval = 1000; config->log_level = DLT_LOG_DEFAULT; } /** * Read options from the configuration file */ DltReturnValue dlt_kpi_read_configuration_file(DltKpiConfig *config, char *file_name) { FILE *file; char *line = NULL; char *token = NULL; char *value = NULL; char *pch, *strchk; int tmp; if ((config == NULL) || (file_name == NULL)) { fprintf(stderr, "%s: Nullpointer parameter!\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } dlt_kpi_init_configuration(config); file = fopen(file_name, "r"); if (file == NULL) { fprintf(stderr, "%s: Could not open configuration file!\n", __func__); return DLT_RETURN_ERROR; } if (((line = malloc(COMMAND_LINE_SIZE)) == 0) || ((token = malloc(COMMAND_LINE_SIZE)) == 0) || ((value = malloc(COMMAND_LINE_SIZE)) == 0)) { fclose(file); free(line); free(token); free(value); fprintf(stderr, "%s: Out of memory!\n", __func__); return DLT_RETURN_ERROR; } while (fgets(line, COMMAND_LINE_SIZE, file) != NULL) { token[0] = '\0'; value[0] = '\0'; pch = strtok (line, " =\r\n"); while (pch != NULL) { if (pch[0] == '#') break; if (token[0] == '\0') { strncpy(token, pch, COMMAND_LINE_SIZE - 1); token[COMMAND_LINE_SIZE - 1] = '\0'; } else { strncpy(value, pch, COMMAND_LINE_SIZE - 1); value[COMMAND_LINE_SIZE - 1] = '\0'; break; } pch = strtok(NULL, " =\r\n"); } if ((token[0] != '\0') && (value[0] != '\0')) { if (strcmp(token, "process_interval") == '\0') { tmp = strtol(value, &strchk, 10); if ((strchk[0] == '\0') && (tmp > 0)) config->process_log_interval = tmp; else fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token); } else if (strcmp(token, "irq_interval") == '\0') { tmp = strtol(value, &strchk, 10); if ((strchk[0] == '\0') && (tmp > 0)) config->irq_log_interval = tmp; else fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token); } else if (strcmp(token, "check_interval") == '\0') { tmp = strtol(value, &strchk, 10); if ((strchk[0] == '\0') && (tmp > 0)) config->check_log_interval = tmp; else fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token); } else if (strcmp(token, "log_level") == '\0') { tmp = strtol(value, &strchk, 10); if ((strchk[0] == '\0') && (tmp >= -1) && (tmp <= 6)) config->log_level = tmp; else fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token); } } } fclose(file); free(value); free(token); free(line); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_init(int argc, char **argv, DltKpiConfig *config) { DltKpiOptions options; DltReturnValue ret; if (config == NULL) { fprintf(stderr, "%s: Invalid Parameter!", __func__); return DLT_RETURN_WRONG_PARAMETER; } if ((ret = dlt_kpi_read_command_line(&options, argc, argv)) < DLT_RETURN_OK) { fprintf(stderr, "Failed to read command line!"); return ret; } if ((ret = dlt_kpi_read_configuration_file(config, options.configurationFileName)) < DLT_RETURN_OK) { fprintf(stderr, "Failed to read configuration file!"); return ret; } dlt_kpi_free_cli_options(&options); return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/kpi/dlt-kpi-process-list.c000066400000000000000000000152111446635226000214260ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-process-list.c */ #include "dlt-kpi-process-list.h" DltKpiProcessList *dlt_kpi_create_process_list() { DltKpiProcessList *new_list = malloc(sizeof(DltKpiProcessList)); if (new_list == NULL) { fprintf(stderr, "%s: Cannot create process list, out of memory\n", __func__); return NULL; } memset(new_list, 0, sizeof(DltKpiProcessList)); new_list->start = new_list->cursor = NULL; return new_list; } DltReturnValue dlt_kpi_free_process_list_soft(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } free(list); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_free_process_list(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } DltKpiProcess *tmp; list->cursor = list->start; while (list->cursor != NULL) { tmp = list->cursor->next; dlt_kpi_free_process(list->cursor); list->cursor = tmp; } return dlt_kpi_free_process_list_soft(list); } DltKpiProcess *dlt_kpi_get_process_at_cursor(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return NULL; } return list->cursor; } DltReturnValue dlt_kpi_reset_cursor(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } list->cursor = list->start; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_set_cursor_at_end(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } list->cursor = list->start; if (list->cursor == NULL) return DLT_RETURN_OK; while (list->cursor->next != NULL) dlt_kpi_increment_cursor(list); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_increment_cursor(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (list->cursor == NULL) return DLT_RETURN_ERROR; list->cursor = list->cursor->next; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_decrement_cursor(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (list->cursor == NULL) return DLT_RETURN_ERROR; list->cursor = list->cursor->prev; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_add_process_at_start(DltKpiProcessList *list, DltKpiProcess *process) { if ((list == NULL) || (process == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (list->start != NULL) list->start->prev = process; process->next = list->start; list->start = process; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_add_process_before_cursor(DltKpiProcessList *list, DltKpiProcess *process) { if ((list == NULL) || (process == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (list->start == NULL) { /* Empty list? */ DltReturnValue ret = dlt_kpi_add_process_at_start(list, process); list->cursor = NULL; return ret; } else if (list->cursor == NULL) { dlt_kpi_set_cursor_at_end(list); DltReturnValue ret = dlt_kpi_add_process_after_cursor(list, process); list->cursor = NULL; return ret; } if (list->cursor->prev != NULL) list->cursor->prev->next = process; else list->start = process; process->next = list->cursor; process->prev = list->cursor->prev; list->cursor->prev = process; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_add_process_after_cursor(DltKpiProcessList *list, DltKpiProcess *process) { if ((list == NULL) || (process == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_ERROR; } if (list->cursor == NULL) return dlt_kpi_add_process_at_start(list, process); if (list->cursor->next != NULL) list->cursor->next->prev = process; process->next = list->cursor->next; process->prev = list->cursor; list->cursor->next = process; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_remove_process_at_cursor_soft(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (list->cursor == NULL) { fprintf(stderr, "%s: Cursor is Invalid (NULL)\n", __func__); return DLT_RETURN_ERROR; } DltKpiProcess *tmp = list->cursor; if (tmp->prev != NULL) { if (tmp->next != NULL) { tmp->prev->next = tmp->next; tmp->next->prev = tmp->prev; } else { tmp->prev->next = NULL; } } else { if (tmp->next != NULL) { tmp->next->prev = NULL; list->start = tmp->next; } else { list->start = NULL; } } list->cursor = tmp->next; /* becomes NULL if list is at end */ return DLT_RETURN_OK; } DltReturnValue dlt_kpi_remove_process_at_cursor(DltKpiProcessList *list) { if (list == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (list->cursor == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_ERROR; } DltKpiProcess *tmp = list->cursor; DltReturnValue ret = dlt_kpi_remove_process_at_cursor_soft(list); if (ret < DLT_RETURN_OK) return ret; dlt_kpi_free_process(tmp); return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/kpi/dlt-kpi-process-list.h000066400000000000000000000036751446635226000214460ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-process-list.h */ #ifndef SRC_KPI_DLT_KPI_PROCESS_LIST_H_ #define SRC_KPI_DLT_KPI_PROCESS_LIST_H_ #include "dlt-kpi-process.h" #include "dlt-kpi-common.h" typedef struct { struct DltKpiProcess *start, *cursor; } DltKpiProcessList; DltKpiProcessList *dlt_kpi_create_process_list(); DltReturnValue dlt_kpi_free_process_list_soft(DltKpiProcessList *list); DltReturnValue dlt_kpi_free_process_list(DltKpiProcessList *list); DltKpiProcess *dlt_kpi_get_process_at_cursor(DltKpiProcessList *list); DltReturnValue dlt_kpi_increment_cursor(DltKpiProcessList *list); DltReturnValue dlt_kpi_decrement_cursor(DltKpiProcessList *list); DltReturnValue dlt_kpi_reset_cursor(DltKpiProcessList *list); DltReturnValue dlt_kpi_add_process_at_start(DltKpiProcessList *list, DltKpiProcess *process); DltReturnValue dlt_kpi_add_process_before_cursor(DltKpiProcessList *list, DltKpiProcess *process); DltReturnValue dlt_kpi_add_process_after_cursor(DltKpiProcessList *list, DltKpiProcess *process); DltReturnValue dlt_kpi_remove_process_at_cursor_soft(DltKpiProcessList *list); DltReturnValue dlt_kpi_remove_process_at_cursor(DltKpiProcessList *list); /* DltReturnValue dlt_kpi_remove_process_after_cursor(DltKpiProcessList *list); */ /* DltReturnValue dlt_kpi_remove_first_process(DltKpiProcessList *list); */ #endif /* SRC_KPI_DLT_KPI_PROCESS_LIST_H_ */ dlt-daemon-2.18.10/src/kpi/dlt-kpi-process.c000066400000000000000000000323211446635226000204560ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-process.c */ #include "dlt-kpi-process.h" #include #include DltReturnValue dlt_kpi_read_process_file_to_str(pid_t pid, char **target_str, char *subdir); unsigned long int dlt_kpi_read_process_stat_to_ulong(pid_t pid, unsigned int index); DltReturnValue dlt_kpi_read_process_stat_cmdline(pid_t pid, char **buffer); DltReturnValue dlt_kpi_process_update_io_wait(DltKpiProcess *process, unsigned long int time_dif_ms) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } unsigned long int total_io_wait = dlt_kpi_read_process_stat_to_ulong(process->pid, 42); int cpu_count = dlt_kpi_get_cpu_count(); process->io_wait = (total_io_wait - process->last_io_wait) * 1000 / sysconf(_SC_CLK_TCK); /* busy milliseconds since last update */ if ((time_dif_ms > 0) && (cpu_count > 0)) process->io_wait = process->io_wait * 1000 / time_dif_ms / cpu_count; /* busy milliseconds per second per CPU */ process->last_io_wait = total_io_wait; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_process_update_cpu_time(DltKpiProcess *process, unsigned long int time_dif_ms) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } unsigned long int utime = dlt_kpi_read_process_stat_to_ulong(process->pid, 14); unsigned long int stime = dlt_kpi_read_process_stat_to_ulong(process->pid, 15); unsigned long total_cpu_time = utime + stime; if ((process->last_cpu_time > 0) && (process->last_cpu_time <= total_cpu_time)) { int cpu_count = dlt_kpi_get_cpu_count(); process->cpu_time = (total_cpu_time - process->last_cpu_time) * 1000 / sysconf(_SC_CLK_TCK); /* busy milliseconds since last update */ if ((time_dif_ms > 0) && (cpu_count > 0)) process->cpu_time = process->cpu_time * 1000 / time_dif_ms / cpu_count; /* busy milliseconds per second per CPU */ } else { process->cpu_time = 0; } process->last_cpu_time = total_cpu_time; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_process_update_rss(DltKpiProcess *process) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } process->rss = dlt_kpi_read_process_stat_to_ulong(process->pid, 24); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_process_update_ctx_switches(DltKpiProcess *process) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } char *buffer, *tok, *last_tok; char *delim = " :\t\n"; last_tok = NULL; DltReturnValue ret; if ((ret = dlt_kpi_read_process_file_to_str(process->pid, &buffer, "status")) < DLT_RETURN_OK) return ret; process->ctx_switches = 0; tok = strtok(buffer, delim); while (tok != NULL) { if (last_tok != NULL) { if ((strcmp(last_tok, "voluntary_ctxt_switches") == 0) || (strcmp(last_tok, "nonvoluntary_ctxt_switches") == 0)) { char *chk; process->ctx_switches += strtol(tok, &chk, 10); if (*chk != '\0') { fprintf(stderr, "Could not parse ctx_switches info from /proc/%d/status", process->pid); free(buffer); return DLT_RETURN_ERROR; } } } last_tok = tok; tok = strtok(NULL, delim); } free(buffer); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_process_update_io_bytes(DltKpiProcess *process) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } char *buffer, *tok, *last_tok; char *delim = " :\t\n"; last_tok = NULL; DltReturnValue ret; if ((ret = dlt_kpi_read_process_file_to_str(process->pid, &buffer, "io")) < DLT_RETURN_OK) return ret; process->io_bytes = 0; tok = strtok(buffer, delim); while (tok != NULL) { if (last_tok != NULL) { if ((strcmp(last_tok, "rchar") == 0) || (strcmp(last_tok, "wchar") == 0)) { char *chk; process->io_bytes += strtoul(tok, &chk, 10); if (*chk != '\0') { fprintf(stderr, "Could not parse io_bytes info from /proc/%d/io", process->pid); free(buffer); return DLT_RETURN_ERROR; } } } last_tok = tok; tok = strtok(NULL, delim); } free(buffer); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_update_process(DltKpiProcess *process, unsigned long int time_dif_ms) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } dlt_kpi_process_update_io_wait(process, time_dif_ms); dlt_kpi_process_update_cpu_time(process, time_dif_ms); dlt_kpi_process_update_rss(process); dlt_kpi_process_update_ctx_switches(process); dlt_kpi_process_update_io_bytes(process); return DLT_RETURN_OK; } DltKpiProcess *dlt_kpi_create_process(int pid) { DltKpiProcess *new_process = malloc(sizeof(DltKpiProcess)); if (new_process == NULL) { fprintf(stderr, "%s: Out of Memory \n", __func__); return NULL; } memset(new_process, 0, sizeof(DltKpiProcess)); new_process->pid = pid; new_process->ppid = (pid_t)dlt_kpi_read_process_stat_to_ulong(pid, 4); dlt_kpi_read_process_file_to_str(pid, &(new_process->command_line), "cmdline"); if (new_process->command_line != NULL) if (strlen(new_process->command_line) == 0) { free(new_process->command_line); dlt_kpi_read_process_stat_cmdline(pid, &(new_process->command_line)); } dlt_kpi_update_process(new_process, 0); return new_process; } DltKpiProcess *dlt_kpi_clone_process(DltKpiProcess *original) { if (original == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return NULL; } /* DltKpiProcess *new_process = dlt_kpi_create_process(original->pid); */ DltKpiProcess *new_process = malloc(sizeof(DltKpiProcess)); if (new_process == NULL) { fprintf(stderr, "%s: Out of Memory\n", __func__); return NULL; } memcpy(new_process, original, sizeof(DltKpiProcess)); if (original->command_line != NULL) { new_process->command_line = malloc(strlen(original->command_line) + 1); if (new_process->command_line == NULL) { fprintf(stderr, "%s: Out of Memory\n", __func__); free(new_process); return NULL; } strncpy(new_process->command_line, original->command_line, strlen(original->command_line) + 1); } else { new_process->command_line = NULL; } new_process->next = new_process->prev = NULL; return new_process; } DltReturnValue dlt_kpi_free_process(DltKpiProcess *process) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (process->command_line != NULL) free(process->command_line); free(process); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_print_process(DltKpiProcess *process) { if (process == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } printf("[PID %d]\n", process->pid); printf(" > PPID : %d\n", process->ppid); printf(" > CMDLINE : %s\n", process->command_line); printf(" > CPUTIME : %lu (busy ms/s)\n", process->cpu_time); printf(" > RSS : %ld\n", process->rss); printf(" > CTXSWTC : %ld\n", process->ctx_switches); printf(" > IOBYTES : %lu\n", process->io_bytes); printf(" > IOWAIT : %ld (%ld)\n", process->io_wait, process->last_io_wait); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_read_process_file_to_str(pid_t pid, char **target_str, char *subdir) { if (target_str == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_ERROR; } *target_str = NULL; if (pid <= 0) { fprintf(stderr, "%s: Invalid Parameter (PID)\n", __func__); return DLT_RETURN_ERROR; } if (subdir == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_ERROR; } char filename[BUFFER_SIZE]; snprintf(filename, BUFFER_SIZE, "/proc/%d/%s", pid, subdir); return dlt_kpi_read_file_compact(filename, target_str); } unsigned long int dlt_kpi_read_process_stat_to_ulong(pid_t pid, unsigned int index) { if (pid <= 0) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return 0; } char *buffer = NULL; if (dlt_kpi_read_process_file_to_str(pid, &buffer, "stat") < DLT_RETURN_OK) { /* fprintf(stderr, "dlt_kpi_read_process_stat_to_ulong(): Error while reading process stat file. Pid: %d. Requested index: %u\n", pid, index); // can happen if process closed shortly before */ if (buffer != NULL) free(buffer); return 0; } char *tok = strtok(buffer, " \t\n"); unsigned int i = 1, found = 0; while (tok != NULL) { if (i == index) { found = 1; break; } i++; tok = strtok(NULL, " \t\n"); } unsigned long int ret = 0; if (found) { char *check = NULL; ret = strtoul(tok, &check, 10); if (*check != '\0') { fprintf(stderr, "dlt_kpi_read_process_stat_to_ulong(): Could not extract token\n"); ret = 0; } } else { fprintf(stderr, "dlt_kpi_read_process_stat_to_ulong(): Index not found\n"); } free(buffer); return ret; } DltReturnValue dlt_kpi_read_process_stat_cmdline(pid_t pid, char **buffer) { if (pid <= 0) { fprintf(stderr, "%s: Invalid Parameter (PID)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (buffer == NULL) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } char *tmp_buffer = NULL; DltReturnValue tmp = dlt_kpi_read_process_file_to_str(pid, &tmp_buffer, "stat"); if (tmp < DLT_RETURN_OK) { if (tmp_buffer != NULL) free(tmp_buffer); return tmp; } char *tok = strtok(tmp_buffer, " \t\n"); unsigned int i = 1; while (tok != NULL) { if (i == 2) break; i++; tok = strtok(NULL, " \t\n"); } if (i == 2) { (*buffer) = malloc(strlen(tok) + 1); strncpy(*buffer, tok, strlen(tok) + 1); } else { fprintf(stderr, "dlt_kpi_read_process_stat_cmdline(): cmdline entry not found\n"); return DLT_RETURN_ERROR; } free(tmp_buffer); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_get_msg_process_update(DltKpiProcess *process, char *buffer, int maxlen) { if ((process == NULL) || (buffer == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } snprintf(buffer, maxlen, "%d;%lu;%ld;%ld;%lu;%lu", process->pid, process->cpu_time, process->rss, process->ctx_switches, process->io_bytes, process->io_wait); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_get_msg_process_new(DltKpiProcess *process, char *buffer, int maxlen) { if ((process == NULL) || (buffer == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } snprintf(buffer, maxlen, "%d;%d;%s", process->pid, process->ppid, process->command_line); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_get_msg_process_stop(DltKpiProcess *process, char *buffer, int maxlen) { if ((process == NULL) || (buffer == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } snprintf(buffer, maxlen, "%d", process->pid); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_get_msg_process_commandline(DltKpiProcess *process, char *buffer, int maxlen) { if ((process == NULL) || (buffer == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } snprintf(buffer, maxlen, "%d;%s", process->pid, process->command_line); return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/kpi/dlt-kpi-process.h000066400000000000000000000035061446635226000204660ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi-process.h */ #ifndef SRC_KPI_DLT_KPI_PROCESS_H_ #define SRC_KPI_DLT_KPI_PROCESS_H_ #include "dlt.h" #include #include "dlt-kpi-common.h" typedef struct DltKpiEventWatch DltKpiEventWatch; /* forward declaration */ typedef struct DltKpiProcess { pid_t pid, ppid; char *command_line; unsigned long int cpu_time, last_cpu_time, io_wait, last_io_wait, io_bytes; long int rss, ctx_switches; struct DltKpiProcess *next, *prev; } DltKpiProcess; DltKpiProcess *dlt_kpi_create_process(); DltKpiProcess *dlt_kpi_clone_process(DltKpiProcess *original); DltReturnValue dlt_kpi_free_process(DltKpiProcess *process); DltReturnValue dlt_kpi_print_process(DltKpiProcess *process); DltReturnValue dlt_kpi_update_process(DltKpiProcess *process, unsigned long int time_dif_ms); DltReturnValue dlt_kpi_get_msg_process_new(DltKpiProcess *process, char *buffer, int maxlen); DltReturnValue dlt_kpi_get_msg_process_stop(DltKpiProcess *process, char *buffer, int maxlen); DltReturnValue dlt_kpi_get_msg_process_update(DltKpiProcess *process, char *buffer, int maxlen); DltReturnValue dlt_kpi_get_msg_process_commandline(DltKpiProcess *process, char *buffer, int maxlen); #endif /* SRC_KPI_DLT_KPI_PROCESS_H_ */ dlt-daemon-2.18.10/src/kpi/dlt-kpi.c000066400000000000000000000365771446635226000170230ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi.c */ #include "dlt-kpi.h" #include #include #include #include #include DLT_DECLARE_CONTEXT(kpi_ctx); DltKpiConfig config; static volatile sig_atomic_t stop_loop = 0; static DltKpiProcessList *list, *new_process_list, *stopped_process_list, *update_process_list; static struct timespec _tmp_time; static pthread_mutex_t process_list_mutex; void dlt_kpi_stop_loops(int sig); void dlt_kpi_init_sigterm_handler(); DltReturnValue dlt_kpi_init_process_lists(); DltReturnValue dlt_kpi_free_process_lists(); void *dlt_kpi_start_process_thread(); DltReturnValue dlt_kpi_process_loop(); DltReturnValue dlt_kpi_update_process_list(DltKpiProcessList *list, unsigned long int time_dif_ms); void *dlt_kpi_start_irq_thread(); DltReturnValue dlt_kpi_irq_loop(); void *dlt_kpi_start_check_thread(); DltReturnValue dlt_kpi_check_loop(); DltReturnValue dlt_kpi_log_check_commandlines(); unsigned long int timespec_to_millis(struct timespec *time) { return (time->tv_sec) * 1000 + (time->tv_nsec / 1000000); } unsigned long int get_millis() { clock_gettime(CLOCK_REALTIME, &_tmp_time); return timespec_to_millis(&_tmp_time); } int main(int argc, char **argv) { printf("Launching dlt-kpi...\n"); if (dlt_kpi_init(argc, argv, &config) < DLT_RETURN_OK) { fprintf(stderr, "Initialization error!\n"); return -1; } dlt_kpi_init_sigterm_handler(); if (dlt_kpi_init_process_lists() < DLT_RETURN_OK) { fprintf(stderr, "Error occurred initializing process lists\n"); return -1; } if (pthread_mutex_init(&process_list_mutex, NULL) < 0) { fprintf(stderr, "Error occurred initializing mutex\n"); return -1; } DLT_REGISTER_APP("PROC", "/proc/-filesystem logger application"); DLT_REGISTER_CONTEXT_LL_TS(kpi_ctx, "PROC", "/proc/-filesystem logger context", config.log_level, 1); pthread_t process_thread; pthread_t irq_thread; pthread_t check_thread; if (pthread_create(&process_thread, NULL, &dlt_kpi_start_process_thread, NULL) != 0) { fprintf(stderr, "Could not create thread\n"); return -1; } if (pthread_create(&irq_thread, NULL, &dlt_kpi_start_irq_thread, NULL) != 0) { fprintf(stderr, "Could not create thread\n"); return -1; } if (pthread_create(&check_thread, NULL, &dlt_kpi_start_check_thread, NULL) != 0) { fprintf(stderr, "Could not create thread\n"); return -1; } pthread_join(process_thread, NULL); pthread_join(irq_thread, NULL); pthread_join(check_thread, NULL); DLT_UNREGISTER_CONTEXT(kpi_ctx); DLT_UNREGISTER_APP(); pthread_mutex_destroy(&process_list_mutex); dlt_kpi_free_process_lists(); printf("Done.\n"); return 0; } void dlt_kpi_init_sigterm_handler() { struct sigaction action; memset(&action, 0, sizeof(struct sigaction)); action.sa_handler = dlt_kpi_stop_loops; sigaction(SIGTERM, &action, NULL); } void dlt_kpi_stop_loops(int sig) { if (sig > -1) fprintf(stderr, "dlt-kpi is now terminating due to signal %d...\n", sig); else fprintf(stderr, "dlt-kpi is now terminating due to an error...\n"); stop_loop = 1; } DltReturnValue dlt_kpi_init_process_lists() { if ((list = dlt_kpi_create_process_list()) == NULL) return DLT_RETURN_ERROR; if ((new_process_list = dlt_kpi_create_process_list()) == NULL) return DLT_RETURN_ERROR; if ((stopped_process_list = dlt_kpi_create_process_list()) == NULL) return DLT_RETURN_ERROR; if ((update_process_list = dlt_kpi_create_process_list()) == NULL) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } DltReturnValue dlt_kpi_free_process_lists() { DltReturnValue ret = DLT_RETURN_OK; if (dlt_kpi_free_process_list(list) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; if (dlt_kpi_free_process_list(new_process_list) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; if (dlt_kpi_free_process_list(stopped_process_list) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; if (dlt_kpi_free_process_list(update_process_list) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; return ret; } void *dlt_kpi_start_process_thread() { if (dlt_kpi_process_loop() < DLT_RETURN_OK) dlt_kpi_stop_loops(-1); return NULL; } DltReturnValue dlt_kpi_process_loop() { static unsigned long int old_millis, sleep_millis, dif_millis; struct timespec ts; old_millis = get_millis(); while (!stop_loop) { /*DltReturnValue ret = */ dlt_kpi_update_process_list(list, config.process_log_interval); /*if(ret < DLT_RETURN_OK) */ /* return ret; */ dif_millis = get_millis() - old_millis; if (dif_millis >= (unsigned long)(config.process_log_interval)) sleep_millis = 0; else sleep_millis = config.process_log_interval - dif_millis; ts.tv_sec = (sleep_millis * NANOSEC_PER_MILLISEC) / NANOSEC_PER_SEC; ts.tv_nsec = (sleep_millis * NANOSEC_PER_MILLISEC) % NANOSEC_PER_SEC; nanosleep(&ts, NULL); old_millis = get_millis(); } return DLT_RETURN_OK; } DltReturnValue dlt_kpi_log_list(DltKpiProcessList *list, DltReturnValue (*process_callback)(DltKpiProcess *, char *, int), char *title, int delete_elements) { if ((list == NULL) || (process_callback == NULL) || (title == NULL)) { fprintf(stderr, "%s: Invalid Parameter (NULL)\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } dlt_kpi_reset_cursor(list); if (list->cursor == NULL) return DLT_RETURN_OK; /* list empty; nothing to do */ /* Synchronization message */ DLT_LOG(kpi_ctx, config.log_level, DLT_STRING(title), DLT_STRING("BEG")); DltReturnValue ret; DltContextData data; char buffer[BUFFER_SIZE]; buffer[0] = '\0'; if ((ret = dlt_user_log_write_start(&kpi_ctx, &data, config.log_level)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_start() returned error.\n", __func__); return ret; } if ((ret = dlt_user_log_write_string(&data, title)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_string() returned error.\n", __func__); return ret; } do { if ((ret = (*process_callback)(list->cursor, buffer, sizeof(buffer) - 1)) < DLT_RETURN_OK) return ret; if ((ret = dlt_user_log_write_string(&data, buffer)) < DLT_RETURN_OK) { /* Log buffer full => Write log and start new one*/ if ((ret = dlt_user_log_write_finish(&data)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_finish() returned error.\n", __func__); return ret; } if ((ret = dlt_user_log_write_start(&kpi_ctx, &data, config.log_level)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_start() returned error.\n", __func__); return ret; } if ((ret = dlt_user_log_write_string(&data, title)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_string() returned error.\n", __func__); return ret; } } else if (delete_elements) { if ((ret = dlt_kpi_remove_process_at_cursor(list)) < DLT_RETURN_OK) return ret; } else { list->cursor = list->cursor->next; } } while (list->cursor != NULL); if ((ret = dlt_user_log_write_finish(&data)) < DLT_RETURN_OK) { fprintf(stderr, "%s: dlt_user_log_write_finish() returned error.\n", __func__); return ret; } /* Synchronization message */ DLT_LOG(kpi_ctx, config.log_level, DLT_STRING(title), DLT_STRING("END")); return DLT_RETURN_OK; } DltReturnValue dlt_kpi_update_process_list(DltKpiProcessList *list, unsigned long int time_dif_ms) { static char *strchk; static DltReturnValue tmp_ret; static struct dirent *current_dir; static pid_t current_dir_pid; if (list == NULL) { fprintf(stderr, "dlt_kpi_update_process_list(): Nullpointer parameter"); return DLT_RETURN_WRONG_PARAMETER; } DIR *proc_dir = opendir("/proc"); if (proc_dir == NULL) { dlt_log(LOG_ERR, "Could not open /proc/ !\n"); return DLT_RETURN_ERROR; } current_dir = readdir(proc_dir); dlt_kpi_reset_cursor(list); int debug_process_count = 0; if (pthread_mutex_lock(&process_list_mutex) < 0) { fprintf(stderr, "Can't lock mutex\n"); return DLT_RETURN_ERROR; } while (1) { if (current_dir == NULL) { /* no more active processes.. delete all remaining processes in the list */ if (list->cursor != NULL) while (list->cursor != NULL) { if ((tmp_ret = dlt_kpi_add_process_after_cursor(stopped_process_list, dlt_kpi_clone_process(list->cursor))) < DLT_RETURN_OK) return tmp_ret; dlt_kpi_remove_process_at_cursor(list); } break; } current_dir_pid = strtol(current_dir->d_name, &strchk, 10); if ((*strchk != '\0') || (current_dir_pid <= 0)) { /* no valid PID */ current_dir = readdir(proc_dir); /* next process in proc-fs */ continue; } /* compare the /proc/-filesystem with our process-list */ if ((list->cursor == NULL) || (current_dir_pid < list->cursor->pid)) { /* New Process */ DltKpiProcess *new_process = dlt_kpi_create_process(current_dir_pid); if (new_process == NULL) { fprintf(stderr, "Error: Could not create process (out of memory?)\n"); return DLT_RETURN_ERROR; } if ((tmp_ret = dlt_kpi_add_process_before_cursor(list, new_process)) < DLT_RETURN_OK) return tmp_ret; if ((tmp_ret = dlt_kpi_add_process_before_cursor(new_process_list, dlt_kpi_clone_process(new_process))) < DLT_RETURN_OK) return tmp_ret; current_dir = readdir(proc_dir); /* next process in proc-fs */ debug_process_count++; } else if (current_dir_pid > list->cursor->pid) /* Process ended */ { if ((tmp_ret = dlt_kpi_add_process_after_cursor(stopped_process_list, dlt_kpi_clone_process(list->cursor))) < DLT_RETURN_OK) return tmp_ret; if ((tmp_ret = dlt_kpi_remove_process_at_cursor(list)) < DLT_RETURN_OK) return tmp_ret; } else if (current_dir_pid == list->cursor->pid) /* Staying process */ { /* update data */ if ((tmp_ret = dlt_kpi_update_process(list->cursor, time_dif_ms)) < DLT_RETURN_OK) return tmp_ret; if (list->cursor->cpu_time > 0) /* only log active processes */ if ((tmp_ret = dlt_kpi_add_process_after_cursor(update_process_list, dlt_kpi_clone_process(list->cursor))) < DLT_RETURN_OK) { fprintf(stderr, "dlt_kpi_update_process_list: Can't add process to list updateProcessList\n"); return tmp_ret; } if ((tmp_ret = dlt_kpi_increment_cursor(list)) < DLT_RETURN_OK) /* next process in list */ return tmp_ret; current_dir = readdir(proc_dir); /* next process in proc-fs */ debug_process_count++; } } if (pthread_mutex_unlock(&process_list_mutex) < 0) { fprintf(stderr, "Can't unlock mutex\n"); return DLT_RETURN_ERROR; } /* Log new processes */ if ((tmp_ret = dlt_kpi_log_list(new_process_list, &dlt_kpi_get_msg_process_new, "NEW", 1)) < DLT_RETURN_OK) return tmp_ret; /* Log stopped processes */ if ((tmp_ret = dlt_kpi_log_list(stopped_process_list, &dlt_kpi_get_msg_process_stop, "STP", 1)) < DLT_RETURN_OK) return tmp_ret; /* Log active processes */ if ((tmp_ret = dlt_kpi_log_list(update_process_list, &dlt_kpi_get_msg_process_update, "ACT", 1)) < DLT_RETURN_OK) return tmp_ret; if (closedir(proc_dir) < 0) fprintf(stderr, "Could not close /proc/ directory\n"); return DLT_RETURN_OK; } void *dlt_kpi_start_irq_thread() { if (dlt_kpi_irq_loop() < DLT_RETURN_OK) dlt_kpi_stop_loops(-1); return NULL; } DltReturnValue dlt_kpi_irq_loop() { static unsigned long int old_millis, sleep_millis, dif_millis; struct timespec ts; old_millis = get_millis(); while (!stop_loop) { /*DltReturnValue ret = */ dlt_kpi_log_interrupts(&kpi_ctx, config.log_level); /*if(ret < DLT_RETURN_OK) */ /* return ret; */ dif_millis = get_millis() - old_millis; if (dif_millis >= (unsigned long)(config.irq_log_interval)) sleep_millis = 0; else sleep_millis = config.irq_log_interval - dif_millis; ts.tv_sec = (sleep_millis * NANOSEC_PER_MILLISEC) / NANOSEC_PER_SEC; ts.tv_nsec = (sleep_millis * NANOSEC_PER_MILLISEC) % NANOSEC_PER_SEC; nanosleep(&ts, NULL); old_millis = get_millis(); } return DLT_RETURN_OK; } void *dlt_kpi_start_check_thread() { if (dlt_kpi_check_loop() < DLT_RETURN_OK) dlt_kpi_stop_loops(-1); return NULL; } DltReturnValue dlt_kpi_check_loop() { static unsigned long int old_millis, sleep_millis, dif_millis; struct timespec ts; old_millis = get_millis(); while (!stop_loop) { /*DltReturnValue ret = */ dlt_kpi_log_check_commandlines(); /*if(ret < DLT_RETURN_OK) */ /* return ret; */ dif_millis = get_millis() - old_millis; if (dif_millis >= (unsigned long)(config.check_log_interval)) sleep_millis = 0; else sleep_millis = config.check_log_interval - dif_millis; ts.tv_sec = (sleep_millis * NANOSEC_PER_MILLISEC) / NANOSEC_PER_SEC; ts.tv_nsec = (sleep_millis * NANOSEC_PER_MILLISEC) % NANOSEC_PER_SEC; nanosleep(&ts, NULL); old_millis = get_millis(); } return DLT_RETURN_OK; } DltReturnValue dlt_kpi_log_check_commandlines() { if (pthread_mutex_lock(&process_list_mutex) < 0) { fprintf(stderr, "Can't lock mutex\n"); return DLT_RETURN_ERROR; } DltReturnValue ret = dlt_kpi_log_list(list, dlt_kpi_get_msg_process_commandline, "CHK", 0); if (pthread_mutex_unlock(&process_list_mutex) < 0) { fprintf(stderr, "Can't unlock mutex\n"); return DLT_RETURN_ERROR; } return ret; } dlt-daemon-2.18.10/src/kpi/dlt-kpi.conf000066400000000000000000000012431446635226000175040ustar00rootroot00000000000000# Configuration file for DLT KPI logger # ######################################################################## # General configuration ######################################################################## # The interval in milliseconds of how often process updates should be logged. (Default: 1000) process_interval = 1000 # The interval in milliseconds of how often interrupt stats should be logged. (Default: 3000) irq_interval = 3000 # The interval in milliseconds of how often the commandlines of all processes should be logged. (Default: 10000) check_interval = 10000 # The used log level. -1 = DEFAULT, 0 = OFF, [...], 6 = VERBOSE (Default: 4) log_level = 4dlt-daemon-2.18.10/src/kpi/dlt-kpi.h000066400000000000000000000032101446635226000170020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-kpi.h */ #ifndef SRC_KPI_DLT_KPI_H_ #define SRC_KPI_DLT_KPI_H_ #include "dlt.h" #include #include "dlt-kpi-common.h" #include "dlt-kpi-interrupt.h" #include "dlt-kpi-process.h" #include "dlt-kpi-process-list.h" /* CONSTANT DEFINITIONS */ #define DEFAULT_CONF_FILE (CONFIGURATION_FILES_DIR "/dlt-kpi.conf") #define COMMAND_LINE_SIZE 1024 #define NANOSEC_PER_MILLISEC 1000000 #define NANOSEC_PER_SEC 1000000000 /* STRUCTURES */ typedef struct { char *configurationFileName; int customConfigFile; } DltKpiOptions; typedef struct { int process_log_interval, irq_log_interval, check_log_interval; DltLogLevelType log_level; } DltKpiConfig; /* FUNCTION DECLARATIONS: */ DltReturnValue dlt_kpi_read_command_line(DltKpiOptions *options, int argc, char **argv); DltReturnValue dlt_kpi_read_configuration_file(DltKpiConfig *config, char *file_name); void dlt_kpi_free_cli_options(DltKpiOptions *options); DltReturnValue dlt_kpi_init(int argc, char **argv, DltKpiConfig *config); #endif /* SRC_KPI_DLT_KPI_H_ */ dlt-daemon-2.18.10/src/lib/000077500000000000000000000000001446635226000152545ustar00rootroot00000000000000dlt-daemon-2.18.10/src/lib/CMakeLists.txt000066400000000000000000000057361446635226000200270ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### set(dlt_LIB_SRCS dlt_user.c dlt_client.c dlt_filetransfer.c dlt_env_ll.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_common.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_multiple_files.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_protocol.c ${PROJECT_SOURCE_DIR}/src/shared/dlt_user_shared.c ) if(WITH_DLT_SHM_ENABLE) set(dlt_LIB_SRCS ${dlt_LIB_SRCS} ${PROJECT_SOURCE_DIR}/src/shared/dlt_shm.c) endif() add_library(dlt ${dlt_LIB_SRCS}) if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux|CYGWIN") set(RT_LIBRARY rt) set(SOCKET_LIBRARY "") else() set(RT_LIBRARY "") set(SOCKET_LIBRARY socket) endif() if(HAVE_FUNC_PTHREAD_SETNAME_NP) add_definitions(-DDLT_USE_PTHREAD_SETNAME_NP) message(STATUS "Using pthread_setname_np API to set thread name") else() message(STATUS "pthread_setname_np API not available on this platform") endif() target_link_libraries(dlt ${RT_LIBRARY} ${SOCKET_LIBRARY} Threads::Threads) target_include_directories(dlt PUBLIC $ $ $ ) # With this option set, a legacy include path is added in addition to the regular one. if(WITH_LEGACY_INCLUDE_PATH) target_include_directories(dlt PUBLIC $ ) endif() if(WITH_LIB_SHORT_VERSION) set_target_properties(dlt PROPERTIES VERSION ${PROJECT_VERSION_MAJOR} SOVERSION ${PROJECT_VERSION_MAJOR}) else() set_target_properties(dlt PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) endif() add_library(Genivi::dlt ALIAS dlt) install(TARGETS dlt EXPORT ${PROJECT_NAME}-targets RUNTIME DESTINATION bin COMPONENT base LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT base ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/static COMPONENT base) # Install *-targets.cmake file install( EXPORT ${PROJECT_NAME}-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} NAMESPACE Genivi:: ) # Create *-config.cmake file include(CMakePackageConfigHelpers) configure_package_config_file( ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-config.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} NO_SET_AND_CHECK_MACRO ) # Install *-config.cmake file install( FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) dlt-daemon-2.18.10/src/lib/dlt_client.c000066400000000000000000001274051446635226000175520ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_client.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_client.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision$ * $LastChangedDate$ * $LastChangedBy$ * Initials Date Comment * aw 12.07.2010 initial */ #include #if defined (__WIN32__) || defined (_MSC_VER) # pragma warning(disable : 4996) /* Switch off C4996 warnings */ # include /* for socket(), connect(), send(), and recv() */ #else # include /* for socket(), connect(), send(), and recv() */ # include /* for sockaddr_in and inet_addr() */ # include # include # include #endif #if defined(_MSC_VER) # include #else # include # include #endif #include #include /* for malloc(), free() */ #include /* for strlen(), memcmp(), memmove() */ #include #include #include #include "dlt_types.h" #include "dlt_client.h" #include "dlt_client_cfg.h" static int (*message_callback_function)(DltMessage *message, void *data) = NULL; static bool (*fetch_next_message_callback_function)(void *data) = NULL; void dlt_client_register_message_callback(int (*registerd_callback)(DltMessage *message, void *data)) { message_callback_function = registerd_callback; } void dlt_client_register_fetch_next_message_callback(bool (*registerd_callback)(void *data)) { fetch_next_message_callback_function = registerd_callback; } DltReturnValue dlt_client_init_port(DltClient *client, int port, int verbose) { if (verbose && (port != DLT_DAEMON_TCP_PORT)) dlt_vlog(LOG_INFO, "%s: Init dlt client struct with port %d\n", __func__, port); if (client == NULL) return DLT_RETURN_ERROR; client->sock = -1; client->servIP = NULL; client->serialDevice = NULL; client->baudrate = DLT_CLIENT_INITIAL_BAUDRATE; client->port = port; client->socketPath = NULL; client->mode = DLT_CLIENT_MODE_TCP; client->receiver.buffer = NULL; client->receiver.buf = NULL; client->receiver.backup_buf = NULL; client->hostip = NULL; return DLT_RETURN_OK; } DltReturnValue dlt_client_init(DltClient *client, int verbose) { char *env_daemon_port; int tmp_port; /* the port may be specified by an environment variable, defaults to DLT_DAEMON_TCP_PORT */ unsigned short servPort = DLT_DAEMON_TCP_PORT; /* the port may be specified by an environment variable */ env_daemon_port = getenv(DLT_CLIENT_ENV_DAEMON_TCP_PORT); if (env_daemon_port != NULL) { tmp_port = atoi(env_daemon_port); if ((tmp_port < IPPORT_RESERVED) || ((unsigned)tmp_port > USHRT_MAX)) { dlt_vlog(LOG_ERR, "%s: Specified port is out of possible range: %d.\n", __func__, tmp_port); return DLT_RETURN_ERROR; } else { servPort = (unsigned short)tmp_port; } } if (verbose) dlt_vlog(LOG_INFO, "%s: Init dlt client struct with default port: %hu.\n", __func__, servPort); return dlt_client_init_port(client, servPort, verbose); } DltReturnValue dlt_client_connect(DltClient *client, int verbose) { const int yes = 1; char portnumbuffer[33] = {0}; struct addrinfo hints, *servinfo, *p; struct sockaddr_un addr; int rv; struct ip_mreq mreq; DltReceiverType receiver_type = DLT_RECEIVE_FD; struct pollfd pfds[1]; int ret; int n; socklen_t m = sizeof(n); int connect_errno = 0; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; if (client == 0) return DLT_RETURN_ERROR; switch (client->mode) { case DLT_CLIENT_MODE_TCP: snprintf(portnumbuffer, 32, "%d", client->port); if ((rv = getaddrinfo(client->servIP, portnumbuffer, &hints, &servinfo)) != 0) { dlt_vlog(LOG_ERR, "%s: getaddrinfo: %s\n", __func__, gai_strerror(rv)); return DLT_RETURN_ERROR; } for (p = servinfo; p != NULL; p = p->ai_next) { if ((client->sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { dlt_vlog(LOG_WARNING, "%s: socket() failed! %s\n", __func__, strerror(errno)); continue; } /* Set socket to Non-blocking mode */ if(fcntl(client->sock, F_SETFL, fcntl(client->sock,F_GETFL,0) | O_NONBLOCK) < 0) { dlt_vlog(LOG_WARNING, "%s: Socket cannot be changed to NON BLOCK: %s\n", __func__, strerror(errno)); close(client->sock); continue; } if (connect(client->sock, p->ai_addr, p->ai_addrlen) < 0) { if (errno == EINPROGRESS) { pfds[0].fd = client->sock; pfds[0].events = POLLOUT; ret = poll(pfds, 1, 500); if (ret < 0) { dlt_vlog(LOG_ERR, "%s: Failed to poll with err [%s]\n", __func__, strerror(errno)); close(client->sock); continue; } else if ((pfds[0].revents & POLLOUT) && getsockopt(client->sock, SOL_SOCKET, SO_ERROR, (void*)&n, &m) == 0) { if (n == 0) { dlt_vlog(LOG_DEBUG, "%s: Already connect\n", __func__); if(fcntl(client->sock, F_SETFL, fcntl(client->sock,F_GETFL,0) & ~O_NONBLOCK) < 0) { dlt_vlog(LOG_WARNING, "%s: Socket cannot be changed to BLOCK with err [%s]\n", __func__, strerror(errno)); close(client->sock); continue; } } else { connect_errno = n; close(client->sock); continue; } } else { connect_errno = errno; close(client->sock); continue; } } else { connect_errno = errno; close(client->sock); continue; } } break; } freeaddrinfo(servinfo); if (p == NULL) { dlt_vlog(LOG_ERR, "%s: ERROR: failed to connect! %s\n", __func__, strerror(connect_errno)); return DLT_RETURN_ERROR; } if (verbose) { dlt_vlog(LOG_INFO, "%s: Connected to DLT daemon (%s)\n", __func__, client->servIP); } receiver_type = DLT_RECEIVE_SOCKET; break; case DLT_CLIENT_MODE_SERIAL: /* open serial connection */ client->sock = open(client->serialDevice, O_RDWR); if (client->sock < 0) { dlt_vlog(LOG_ERR, "%s: ERROR: Failed to open device %s\n", __func__, client->serialDevice); return DLT_RETURN_ERROR; } if (isatty(client->sock)) { #if !defined (__WIN32__) if (dlt_setup_serial(client->sock, client->baudrate) < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s: ERROR: Failed to configure serial device %s (%s) \n", __func__, client->serialDevice, strerror(errno)); return DLT_RETURN_ERROR; } #else return DLT_RETURN_ERROR; #endif } else { if (verbose) dlt_vlog(LOG_ERR, "%s: ERROR: Device is not a serial device, device = %s (%s) \n", __func__, client->serialDevice, strerror(errno)); return DLT_RETURN_ERROR; } if (verbose) dlt_vlog(LOG_INFO, "%s: Connected to %s\n", __func__, client->serialDevice); receiver_type = DLT_RECEIVE_FD; break; case DLT_CLIENT_MODE_UNIX: if ((client->sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { dlt_vlog(LOG_ERR, "%s: ERROR: (unix) socket error: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; memcpy(addr.sun_path, client->socketPath, sizeof(addr.sun_path) - 1); if (connect(client->sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) { dlt_vlog(LOG_ERR, "%s: ERROR: (unix) connect error: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; } if (client->sock < 0) { dlt_vlog(LOG_ERR, "%s: ERROR: Failed to open device %s\n", __func__, client->socketPath); return DLT_RETURN_ERROR; } receiver_type = DLT_RECEIVE_SOCKET; break; case DLT_CLIENT_MODE_UDP_MULTICAST: if ((client->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { dlt_vlog(LOG_ERR, "%s: ERROR: socket error: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; } /* allow multiple sockets to use the same PORT number */ if (setsockopt(client->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { dlt_vlog(LOG_ERR, "%s: ERROR: Reusing address failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; } memset(&client->receiver.addr, 0, sizeof(client->receiver.addr)); client->receiver.addr.sin_family = AF_INET; client->receiver.addr.sin_addr.s_addr = htonl(INADDR_ANY); client->receiver.addr.sin_port = htons(client->port); /* bind to receive address */ if (bind(client->sock, (struct sockaddr*) &client->receiver.addr, sizeof(client->receiver.addr)) < 0) { dlt_vlog(LOG_ERR, "%s: ERROR: bind failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; } mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (client->hostip) { mreq.imr_interface.s_addr = inet_addr(client->hostip); } if (client->servIP == NULL) { dlt_vlog(LOG_ERR, "%s: ERROR: server address not set\n", __func__); return DLT_RETURN_ERROR; } char delimiter[] = ","; char* servIP = strtok(client->servIP, delimiter); while(servIP != NULL) { mreq.imr_multiaddr.s_addr = inet_addr(servIP); if (mreq.imr_multiaddr.s_addr == (in_addr_t)-1) { dlt_vlog(LOG_ERR, "%s: ERROR: server address not not valid %s\n", __func__, servIP); return DLT_RETURN_ERROR; } if (setsockopt(client->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0) { dlt_vlog(LOG_ERR, "%s: ERROR: setsockopt add membership failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; } servIP = strtok(NULL, delimiter); } receiver_type = DLT_RECEIVE_UDP_SOCKET; break; default: dlt_vlog(LOG_ERR, "%s: ERROR: Mode not supported: %d\n", __func__, client->mode); return DLT_RETURN_ERROR; } if (dlt_receiver_init(&(client->receiver), client->sock, receiver_type, DLT_RECEIVE_BUFSIZE) != DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s: ERROR initializing receiver\n", __func__); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_client_cleanup(DltClient *client, int verbose) { int ret = DLT_RETURN_OK; if (verbose) dlt_vlog(LOG_INFO, "%s: Cleanup dlt client\n", __func__); if (client == NULL) return DLT_RETURN_WRONG_PARAMETER; if (client->sock != -1) close(client->sock); if (dlt_receiver_free(&(client->receiver)) != DLT_RETURN_OK) { dlt_vlog(LOG_WARNING, "%s: Failed to free receiver\n", __func__); ret = DLT_RETURN_ERROR; } if (client->serialDevice) { free(client->serialDevice); client->serialDevice = NULL; } if (client->servIP) { free(client->servIP); client->servIP = NULL; } if (client->socketPath) { free(client->socketPath); client->socketPath = NULL; } if (client->hostip) { free(client->hostip); client->hostip = NULL; } return ret; } DltReturnValue dlt_client_main_loop(DltClient *client, void *data, int verbose) { DltMessage msg; int ret; if (client == 0) return DLT_RETURN_ERROR; if (dlt_message_init(&msg, verbose) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; bool fetch_next_message = true; while (fetch_next_message) { /* wait for data from socket or serial connection */ ret = dlt_receiver_receive(&(client->receiver)); if (ret <= 0) { /* No more data to be received */ if (dlt_message_free(&msg, verbose) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; return DLT_RETURN_TRUE; } while (dlt_message_read(&msg, (unsigned char *)(client->receiver.buf), client->receiver.bytesRcvd, client->resync_serial_header, verbose) == DLT_MESSAGE_ERROR_OK) { /* Call callback function */ if (message_callback_function) (*message_callback_function)(&msg, data); if (msg.found_serialheader) { if (dlt_receiver_remove(&(client->receiver), (int) (msg.headersize + msg.datasize - sizeof(DltStorageHeader) + sizeof(dltSerialHeader))) == DLT_RETURN_ERROR) { /* Return value ignored */ dlt_message_free(&msg, verbose); return DLT_RETURN_ERROR; } } else if (dlt_receiver_remove(&(client->receiver), (int) (msg.headersize + msg.datasize - sizeof(DltStorageHeader))) == DLT_RETURN_ERROR) { /* Return value ignored */ dlt_message_free(&msg, verbose); return DLT_RETURN_ERROR; } } if (dlt_receiver_move_to_begin(&(client->receiver)) == DLT_RETURN_ERROR) { /* Return value ignored */ dlt_message_free(&msg, verbose); return DLT_RETURN_ERROR; } if (fetch_next_message_callback_function) fetch_next_message = (*fetch_next_message_callback_function)(data); } if (dlt_message_free(&msg, verbose) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } DltReturnValue dlt_client_send_message_to_socket(DltClient *client, DltMessage *msg) { int ret = 0; if ((client == NULL) || (client->sock < 0) || (msg == NULL) || (msg->databuffer == NULL)) { dlt_log(LOG_ERR, "Invalid parameters\n"); return DLT_RETURN_ERROR; } if (client->send_serial_header) { ret = send(client->sock, (const char *)dltSerialHeader, sizeof(dltSerialHeader), 0); if (ret < 0) { dlt_vlog(LOG_ERR, "Sending serial header failed: %s\n", strerror(errno)); return DLT_RETURN_ERROR; } } ret = send(client->sock, (const char *)(msg->headerbuffer + sizeof(DltStorageHeader)), msg->headersize - sizeof(DltStorageHeader), 0); if (ret < 0) { dlt_vlog(LOG_ERR, "Sending message header failed: %s\n", strerror(errno)); return DLT_RETURN_ERROR; } ret = send(client->sock, (const char *)msg->databuffer, msg->datasize, 0); if ( ret < 0) { dlt_vlog(LOG_ERR, "Sending message failed: %s\n", strerror(errno)); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_client_send_ctrl_msg(DltClient *client, char *apid, char *ctid, uint8_t *payload, uint32_t size) { DltMessage msg; int ret; int32_t len; uint32_t id_tmp; uint32_t id; if ((client == 0) || (client->sock < 0) || (apid == 0) || (ctid == 0)) return DLT_RETURN_ERROR; /* initialise new message */ if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; /* prepare payload of data */ msg.datasize = size; if (msg.databuffer && (msg.databuffersize < msg.datasize)) { free(msg.databuffer); msg.databuffer = 0; } if (msg.databuffer == 0) { msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; } if (msg.databuffer == 0) { dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } /* copy data */ memcpy(msg.databuffer, payload, size); /* prepare storage header */ msg.storageheader = (DltStorageHeader *)msg.headerbuffer; if (dlt_set_storageheader(msg.storageheader, "") == DLT_RETURN_ERROR) { dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } /* prepare standard header */ msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1; #if (BYTE_ORDER == BIG_ENDIAN) msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF); #endif msg.standardheader->mcnt = 0; /* Set header extra parameters */ dlt_set_id(msg.headerextra.ecu, client->ecuid); /*msg.headerextra.seid = 0; */ msg.headerextra.tmsp = dlt_uptime(); /* Copy header extra parameters to headerbuffer */ if (dlt_message_set_extraparameters(&msg, 0) == DLT_RETURN_ERROR) { dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } /* prepare extended header */ msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); msg.extendedheader->msin = DLT_MSIN_CONTROL_REQUEST; msg.extendedheader->noar = 1; /* number of arguments */ dlt_set_id(msg.extendedheader->apid, (apid[0] == '\0') ? DLT_CLIENT_DUMMY_APP_ID : apid); dlt_set_id(msg.extendedheader->ctid, (ctid[0] == '\0') ? DLT_CLIENT_DUMMY_CON_ID : ctid); /* prepare length information */ msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); len = (int32_t) (msg.headersize - sizeof(DltStorageHeader) + msg.datasize); if (len > UINT16_MAX) { dlt_vlog(LOG_ERR, "%s: Critical: Huge injection message discarded!\n", __func__); dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } msg.standardheader->len = DLT_HTOBE_16(len); /* Send data (without storage header) */ if ((client->mode == DLT_CLIENT_MODE_TCP) || (client->mode == DLT_CLIENT_MODE_SERIAL)) { /* via FileDescriptor */ if (client->send_serial_header) { ret = write(client->sock, dltSerialHeader, sizeof(dltSerialHeader)); if (ret < 0) { dlt_log(LOG_ERR, "Sending message failed\n"); dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } } ret = (int) write(client->sock, msg.headerbuffer + sizeof(DltStorageHeader), msg.headersize - sizeof(DltStorageHeader)); if (0 > ret) { dlt_vlog(LOG_ERR, "%s: Sending message failed\n", __func__); dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } ret = (int) write(client->sock, msg.databuffer, msg.datasize); if (0 > ret) { dlt_vlog(LOG_ERR, "%s: Sending message failed\n", __func__); dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } id_tmp = *((uint32_t *)(msg.databuffer)); id = DLT_ENDIAN_GET_32(msg.standardheader->htyp, id_tmp); dlt_vlog(LOG_INFO, "%s: Control message forwarded : %s\n", __func__, dlt_get_service_name(id)); } else { /* via Socket */ if (dlt_client_send_message_to_socket(client, &msg) == DLT_RETURN_ERROR) { dlt_log(LOG_ERR, "Sending message to socket failed\n"); dlt_message_free(&msg, 0); return DLT_RETURN_ERROR; } } /* free message */ if (dlt_message_free(&msg, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } DltReturnValue dlt_client_send_inject_msg(DltClient *client, char *apid, char *ctid, uint32_t serviceID, uint8_t *buffer, uint32_t size) { uint8_t *payload; int offset; payload = (uint8_t *)malloc(sizeof(uint32_t) + sizeof(uint32_t) + size); if (payload == 0) return DLT_RETURN_ERROR; offset = 0; memcpy(payload, &serviceID, sizeof(serviceID)); offset += (int) sizeof(uint32_t); memcpy(payload + offset, &size, sizeof(size)); offset += (int) sizeof(uint32_t); memcpy(payload + offset, buffer, size); /* free message */ if (dlt_client_send_ctrl_msg(client, apid, ctid, payload, (uint32_t) (sizeof(uint32_t) + sizeof(uint32_t) + size)) == DLT_RETURN_ERROR) { free(payload); return DLT_RETURN_ERROR; } free(payload); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_log_level(DltClient *client, char *apid, char *ctid, uint8_t logLevel) { DltServiceSetLogLevel *req; int ret = DLT_RETURN_ERROR; if (client == NULL) return ret; req = calloc(1, sizeof(DltServiceSetLogLevel)); if (req == NULL) return ret; req->service_id = DLT_SERVICE_ID_SET_LOG_LEVEL; dlt_set_id(req->apid, apid); dlt_set_id(req->ctid, ctid); req->log_level = logLevel; dlt_set_id(req->com, "remo"); /* free message */ ret = dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t *)req, sizeof(DltServiceSetLogLevel)); free(req); return ret; } DltReturnValue dlt_client_get_log_info(DltClient *client) { DltServiceGetLogInfoRequest *req; int ret = DLT_RETURN_ERROR; if (client == NULL) return ret; req = (DltServiceGetLogInfoRequest *)malloc(sizeof(DltServiceGetLogInfoRequest)); if (req == NULL) return ret; req->service_id = DLT_SERVICE_ID_GET_LOG_INFO; req->options = 7; dlt_set_id(req->apid, ""); dlt_set_id(req->ctid, ""); dlt_set_id(req->com, "remo"); /* send control message to daemon*/ ret = dlt_client_send_ctrl_msg(client, "", "", (uint8_t *)req, sizeof(DltServiceGetLogInfoRequest)); free(req); return ret; } DltReturnValue dlt_client_get_default_log_level(DltClient *client) { DltServiceGetDefaultLogLevelRequest *req; int ret = DLT_RETURN_ERROR; if (client == NULL) return ret; req = (DltServiceGetDefaultLogLevelRequest *) malloc(sizeof(DltServiceGetDefaultLogLevelRequest)); if (req == NULL) return ret; req->service_id = DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL; /* send control message to daemon*/ ret = dlt_client_send_ctrl_msg(client, "", "", (uint8_t *)req, sizeof(DltServiceGetDefaultLogLevelRequest)); free(req); return ret; } DltReturnValue dlt_client_get_software_version(DltClient *client) { DltServiceGetSoftwareVersion *req; int ret = DLT_RETURN_ERROR; if (client == NULL) return ret; req = (DltServiceGetSoftwareVersion *)malloc(sizeof(DltServiceGetSoftwareVersion)); req->service_id = DLT_SERVICE_ID_GET_SOFTWARE_VERSION; /* send control message to daemon*/ ret = dlt_client_send_ctrl_msg(client, "", "", (uint8_t *)req, sizeof(DltServiceGetSoftwareVersion)); free(req); return ret; } DltReturnValue dlt_client_send_trace_status(DltClient *client, char *apid, char *ctid, uint8_t traceStatus) { DltServiceSetLogLevel *req; req = calloc(1,sizeof(DltServiceSetLogLevel)); if (req == 0) return DLT_RETURN_ERROR; req->service_id = DLT_SERVICE_ID_SET_TRACE_STATUS; dlt_set_id(req->apid, apid); dlt_set_id(req->ctid, ctid); req->log_level = traceStatus; dlt_set_id(req->com, "remo"); /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t*) req, sizeof(DltServiceSetLogLevel)) == DLT_RETURN_ERROR) { free(req); return DLT_RETURN_ERROR; } free(req); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_default_log_level(DltClient *client, uint8_t defaultLogLevel) { DltServiceSetDefaultLogLevel *req; req = calloc(1, sizeof(DltServiceSetDefaultLogLevel)); if (req == 0) return DLT_RETURN_ERROR; req->service_id = DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL; req->log_level = defaultLogLevel; dlt_set_id(req->com, "remo"); /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t*) req, sizeof(DltServiceSetDefaultLogLevel)) == DLT_RETURN_ERROR) { free(req); return DLT_RETURN_ERROR; } free(req); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_all_log_level(DltClient *client, uint8_t LogLevel) { DltServiceSetDefaultLogLevel *req; req = calloc(1, sizeof(DltServiceSetDefaultLogLevel)); if (req == 0) return DLT_RETURN_ERROR; req->service_id = DLT_SERVICE_ID_SET_ALL_LOG_LEVEL; req->log_level = LogLevel; dlt_set_id(req->com, "remo"); /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t*) req, sizeof(DltServiceSetDefaultLogLevel)) == -1) { free(req); return DLT_RETURN_ERROR; } free(req); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_default_trace_status(DltClient *client, uint8_t defaultTraceStatus) { DltServiceSetDefaultLogLevel *req; req = calloc(1, sizeof(DltServiceSetDefaultLogLevel)); if (req == 0) return DLT_RETURN_ERROR; req->service_id = DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS; req->log_level = defaultTraceStatus; dlt_set_id(req->com, "remo"); /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t*) req, sizeof(DltServiceSetDefaultLogLevel)) == DLT_RETURN_ERROR) { free(req); return DLT_RETURN_ERROR; } free(req); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_all_trace_status(DltClient *client, uint8_t traceStatus) { DltServiceSetDefaultLogLevel *req; if (client == NULL) { dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return DLT_RETURN_ERROR; } req = calloc(1, sizeof(DltServiceSetDefaultLogLevel)); if (req == 0) { dlt_vlog(LOG_ERR, "%s: Could not allocate memory %zu\n", __func__, sizeof(DltServiceSetDefaultLogLevel)); return DLT_RETURN_ERROR; } req->service_id = DLT_SERVICE_ID_SET_ALL_TRACE_STATUS; req->log_level = traceStatus; dlt_set_id(req->com, "remo"); /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t*) req, sizeof(DltServiceSetDefaultLogLevel)) == -1) { free(req);; return DLT_RETURN_ERROR; } free(req); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_timing_pakets(DltClient *client, uint8_t timingPakets) { DltServiceSetVerboseMode *req; req = calloc(1, sizeof(DltServiceSetVerboseMode)); if (req == 0) return DLT_RETURN_ERROR; req->service_id = DLT_SERVICE_ID_SET_TIMING_PACKETS; req->new_status = timingPakets; /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t*) req, sizeof(DltServiceSetVerboseMode)) == DLT_RETURN_ERROR) { free(req); return DLT_RETURN_ERROR; } free(req); return DLT_RETURN_OK; } DltReturnValue dlt_client_send_store_config(DltClient *client) { uint32_t service_id; service_id = DLT_SERVICE_ID_STORE_CONFIG; /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t *)&service_id, sizeof(uint32_t)) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } DltReturnValue dlt_client_send_reset_to_factory_default(DltClient *client) { uint32_t service_id; service_id = DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT; /* free message */ if (dlt_client_send_ctrl_msg(client, "APP", "CON", (uint8_t *)&service_id, sizeof(uint32_t)) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } DltReturnValue dlt_client_setbaudrate(DltClient *client, int baudrate) { if (client == 0) return DLT_RETURN_ERROR; client->baudrate = dlt_convert_serial_speed(baudrate); return DLT_RETURN_OK; } DltReturnValue dlt_client_set_mode(DltClient *client, DltClientMode mode) { if (client == 0) return DLT_RETURN_ERROR; client->mode = mode; return DLT_RETURN_OK; } int dlt_client_set_server_ip(DltClient *client, char *ipaddr) { client->servIP = strdup(ipaddr); if (client->servIP == NULL) { dlt_vlog(LOG_ERR, "%s: ERROR: failed to duplicate server IP\n", __func__); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } int dlt_client_set_host_if_address(DltClient *client, char *hostip) { client->hostip = strdup(hostip); if (client->hostip == NULL) { dlt_vlog(LOG_ERR, "%s: ERROR: failed to duplicate UDP interface address\n", __func__); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } int dlt_client_set_serial_device(DltClient *client, char *serial_device) { client->serialDevice = strdup(serial_device); if (client->serialDevice == NULL) { dlt_vlog(LOG_ERR, "%s: ERROR: failed to duplicate serial device\n", __func__); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } int dlt_client_set_socket_path(DltClient *client, char *socket_path) { client->socketPath = strdup(socket_path); if (client->socketPath == NULL) { dlt_vlog(LOG_ERR, "%s: ERROR: failed to duplicate socket path\n", __func__); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } /** * free allocation when calloc failed * * @param resp DltServiceGetLogInfoResponse * @param count_app_ids number of app_ids which needs to be freed */ DLT_STATIC void dlt_client_free_calloc_failed_get_log_info(DltServiceGetLogInfoResponse *resp, int count_app_ids) { AppIDsType *app = NULL; ContextIDsInfoType *con = NULL; int i = 0; int j = 0; for (i = 0; i < count_app_ids; i++) { app = &(resp->log_info_type.app_ids[i]); for (j = 0; j < app->count_context_ids; j++) { con = &(app->context_id_info[j]); free(con->context_description); con->context_description = NULL; } free(app->app_description); app->app_description = NULL; free(app->context_id_info); app->context_id_info = NULL; } free(resp->log_info_type.app_ids); resp->log_info_type.app_ids = NULL; resp->log_info_type.count_app_ids = 0; return; } DltReturnValue dlt_client_parse_get_log_info_resp_text(DltServiceGetLogInfoResponse *resp, char *resp_text) { AppIDsType *app = NULL; ContextIDsInfoType *con = NULL; int i = 0; int j = 0; char *rp = NULL; int rp_count = 0; if ((resp == NULL) || (resp_text == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* ------------------------------------------------------ * get_log_info data structure(all data is ascii) * * get_log_info, aa, bb bb cc cc cc cc dd dd ee ee ee ee ff gg hh hh ii ii ii .. .. * ~~ ~~~~~ ~~~~~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~ * cc cc cc cc dd dd ee ee ee ee ff gg hh hh ii ii ii .. .. * jj jj kk kk kk .. .. * ~~~~~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~ * aa : get mode (fix value at 0x07) * bb bb : list num of apid (little endian) * cc cc cc cc: apid * dd dd : list num of ctid (little endian) * ee ee ee ee: ctid * ff : log level * gg : trace status * hh hh : description length of ctid * ii ii .. : description text of ctid * jj jj : description length of apid * kk kk .. : description text of apid * ------------------------------------------------------ */ rp = resp_text + DLT_GET_LOG_INFO_HEADER; rp_count = 0; /* check if status is acceptable */ if ((resp->status < GET_LOG_INFO_STATUS_MIN) || (resp->status > GET_LOG_INFO_STATUS_MAX)) { if (resp->status == GET_LOG_INFO_STATUS_NO_MATCHING_CTX) dlt_vlog(LOG_WARNING, "%s: The status(%d) is invalid: NO matching Context IDs\n", __func__, resp->status); else if (resp->status == GET_LOG_INFO_STATUS_RESP_DATA_OVERFLOW) dlt_vlog(LOG_WARNING, "%s: The status(%d) is invalid: Response data over flow\n", __func__, resp->status); else dlt_vlog(LOG_WARNING, "%s: The status(%d) is invalid\n", __func__, resp->status); return DLT_RETURN_ERROR; } /* count_app_ids */ resp->log_info_type.count_app_ids = (uint16_t) dlt_getloginfo_conv_ascii_to_uint16_t(rp, &rp_count); resp->log_info_type.app_ids = (AppIDsType *)calloc (resp->log_info_type.count_app_ids, sizeof(AppIDsType)); if (resp->log_info_type.app_ids == NULL) { dlt_vlog(LOG_ERR, "%s: calloc failed for app_ids\n", __func__); dlt_client_free_calloc_failed_get_log_info(resp, 0); return DLT_RETURN_ERROR; } for (i = 0; i < resp->log_info_type.count_app_ids; i++) { app = &(resp->log_info_type.app_ids[i]); /* get app id */ dlt_getloginfo_conv_ascii_to_id(rp, &rp_count, app->app_id, DLT_ID_SIZE); /* count_con_ids */ app->count_context_ids = (uint16_t) dlt_getloginfo_conv_ascii_to_uint16_t(rp, &rp_count); app->context_id_info = (ContextIDsInfoType *)calloc (app->count_context_ids, sizeof(ContextIDsInfoType)); if (app->context_id_info == NULL) { dlt_vlog(LOG_ERR, "%s: calloc failed for context_id_info\n", __func__); dlt_client_free_calloc_failed_get_log_info(resp, i); return DLT_RETURN_ERROR; } for (j = 0; j < app->count_context_ids; j++) { con = &(app->context_id_info[j]); /* get con id */ dlt_getloginfo_conv_ascii_to_id(rp, &rp_count, con->context_id, DLT_ID_SIZE); /* log_level */ if ((resp->status == 4) || (resp->status == 6) || (resp->status == 7)) con->log_level = dlt_getloginfo_conv_ascii_to_int16_t(rp, &rp_count); /* trace status */ if ((resp->status == 5) || (resp->status == 6) || (resp->status == 7)) con->trace_status = dlt_getloginfo_conv_ascii_to_int16_t(rp, &rp_count); /* context desc */ if (resp->status == 7) { con->len_context_description = (uint16_t) dlt_getloginfo_conv_ascii_to_uint16_t(rp, &rp_count); con->context_description = (char *)calloc ((size_t) (con->len_context_description + 1), sizeof(char)); if (con->context_description == NULL) { dlt_vlog(LOG_ERR, "%s: calloc failed for context description\n", __func__); dlt_client_free_calloc_failed_get_log_info(resp, i); return DLT_RETURN_ERROR; } dlt_getloginfo_conv_ascii_to_string(rp, &rp_count, con->context_description, con->len_context_description); } } /* application desc */ if (resp->status == 7) { app->len_app_description = (uint16_t) dlt_getloginfo_conv_ascii_to_uint16_t(rp, &rp_count); app->app_description = (char *)calloc ((size_t) (app->len_app_description + 1), sizeof(char)); if (app->app_description == NULL) { dlt_vlog(LOG_ERR, "%s: calloc failed for application description\n", __func__); dlt_client_free_calloc_failed_get_log_info(resp, i); return DLT_RETURN_ERROR; } dlt_getloginfo_conv_ascii_to_string(rp, &rp_count, app->app_description, app->len_app_description); } } return DLT_RETURN_OK; } int dlt_client_cleanup_get_log_info(DltServiceGetLogInfoResponse *resp) { AppIDsType app; int i = 0; int j = 0; if (resp == NULL) return DLT_RETURN_OK; for (i = 0; i < resp->log_info_type.count_app_ids; i++) { app = resp->log_info_type.app_ids[i]; for (j = 0; j < app.count_context_ids; j++) { free(app.context_id_info[j].context_description); app.context_id_info[j].context_description = NULL; } free(app.context_id_info); app.context_id_info = NULL; free(app.app_description); app.app_description = NULL; } free(resp->log_info_type.app_ids); resp->log_info_type.app_ids = NULL; free(resp); resp = NULL; return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/lib/dlt_client_cfg.h000066400000000000000000000105641446635226000203730ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_client_cfg.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_client_cfg.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_CLIENT_CFG_H #define DLT_CLIENT_CFG_H /*************/ /* Changable */ /*************/ /* Dummy application id of DLT client */ #define DLT_CLIENT_DUMMY_APP_ID "CA1" /* Dummy context id of DLT client */ #define DLT_CLIENT_DUMMY_CON_ID "CC1" /* Size of buffer */ #define DLT_CLIENT_TEXTBUFSIZE 512 /* Initial baudrate */ #if !defined (__WIN32__) && !defined(_MSC_VER) #define DLT_CLIENT_INITIAL_BAUDRATE B115200 #else #define DLT_CLIENT_INITIAL_BAUDRATE 0 #endif /* Name of environment variable for specifying the daemon port */ #define DLT_CLIENT_ENV_DAEMON_TCP_PORT "DLT_DAEMON_TCP_PORT" /************************/ /* Don't change please! */ /************************/ #endif /* DLT_CLIENT_CFG_H */ dlt-daemon-2.18.10/src/lib/dlt_env_ll.c000066400000000000000000000250361446635226000175500ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Intel Corporation * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Stefan Vacek Intel Corporation * * \copyright Copyright © 2015 Intel Corporation. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_env_ll.c */ #include "dlt_user.h" #include #include #define DLT_ENV_LL_SET_INCREASE 10 /* a generic entry looks like: * ll_item ::= apid:ctid:ll * ll_set ::= ll_item | * ll_set;ll_item */ /** * @brief extract id out of given string * * Extract 4-byte string out of given environment string, the pointer of the * environment string is moved to the next un-used character and the extracted * id is copied into \param id * * Example: * env[] = "abcd:1234:3" * char res[4u]; * char * tmp = &env[0]; * int ret = extract_id(&tmp, res); * assert(ret == 0); * assert(*tmp == ':'); * assert(res[3] == 'd'); * * @param env Environment variable * @param id Extracted ID * @return 0 if successful, -1 else */ int dlt_env_extract_id(char **const env, char *id) { int i; if (!env || !id) { return -1; } if (!(*env)) { return -1; } memset(id, 0, 4); for (i = 0; (i < 4) && (**env != ':') && (**env != 0); ++i) { *id++ = *((*env)++); } /* the next/last character must be ':' */ if ((0 != **env) && (':' == **env)) { return 0; } return -1; } /** * @brief convert a given string to lower-case * * Stops end of string or if ';' is detected */ int dlt_env_helper_to_lower(char **const env, char *result, int const res_len) { int count = 0; char ch; if (!env || !result) { return -1; } if (!(*env)) { return -1; } ch = *(*env); while (ch && (count < res_len - 1) && (ch != ';')) { if ((ch >= 'A') && (ch <= 'Z')) { result[count] = ch + 'a' - 'A'; } else { result[count] = ch; } ch = *(++(*env)); ++count; } result[count] = 0; if (!ch || (ch == ';')) { /* full input was parsed */ return 0; } else { return -1; } } int dlt_env_extract_symbolic_ll(char **const env, int8_t *ll) { char result[strlen("verbose") + 1]; if (!env || !ll) { return -1; } if (!(*env)) { return -1; } if (dlt_env_helper_to_lower(env, &result[0], sizeof(result)) == 0) { if (strncmp("default", result, sizeof(result)) == 0) { *ll = -1; } else if (strncmp("off", result, sizeof(result)) == 0) { *ll = 0; } else if (strncmp("fatal", result, sizeof(result)) == 0) { *ll = 1; } else if (strncmp("error", result, sizeof(result)) == 0) { *ll = 2; } else if (strncmp("warning", result, sizeof(result)) == 0) { *ll = 3; } else if (strncmp("info", result, sizeof(result)) == 0) { *ll = 4; } else if (strncmp("debug", result, sizeof(result)) == 0) { *ll = 5; } else if (strncmp("verbose", result, sizeof(result)) == 0) { *ll = 6; } else { return -1; } if (**env != 0) { (*env)++; } return 0; } else { return -1; } } /** * @brief extract log-level out of given string * * A valid log-level is a numeric value in the range of -1 .. 6, with: * -1: default * 0: off * 1: fatal * 2: error * 3: warning * 4: info * 5: debug * 6: verbose * During parsing, the environment string is moved to the next un-used character and the extracted * log-level is written into \param ll * * Example: * env[] = "abcd:1234:6" * int ll; * char ** tmp = &env[10]; // tmp points to '6'! * int ret = extract_ll(&tmp, &ll); * assert(ret == 0); * assert(*tmp == NULL); * assert(ll == 6); * * @param env Environment variable * @param ll Extracted log level * @return 0 if successful, -1 else */ int dlt_env_extract_ll(char **const env, int8_t *ll) { if (!env || !ll) { return -1; } if (!(*env)) { return -1; } /* extract number */ if (**env == '-') { (*env)++; if (**env == '1') { *ll = -1; (*env)++; } } else { if ((**env >= '0') && (**env < '7')) { *ll = **env - '0'; (*env)++; } else if (dlt_env_extract_symbolic_ll(env, ll) != 0) { return -1; } } /* check end, either next char is NULL or ';' */ if ((**env == ';') || (**env == 0)) { return 0; } return -1; } /** * @brief extract one item out of string * * @return 0 if successful, -1 else */ int dlt_env_extract_ll_item(char **const env, dlt_env_ll_item *const item) { int ret = -1; if (!env || !item) { return -1; } if (!(*env)) { return -1; } memset(item, 0, sizeof(dlt_env_ll_item)); ret = dlt_env_extract_id(env, item->appId); if (ret == -1) { return -1; } (*env)++; ret = dlt_env_extract_id(env, item->ctxId); if (ret == -1) { return -1; } (*env)++; ret = dlt_env_extract_ll(env, &item->ll); if (ret == -1) { return -1; } return 0; } /** * @brief initialize ll_set * * Must call release_ll_set before exit to release all memory * * @return -1 if memory could not be allocated * @return 0 on success */ int dlt_env_init_ll_set(dlt_env_ll_set *const ll_set) { if (!ll_set) { return -1; } ll_set->array_size = DLT_ENV_LL_SET_INCREASE; ll_set->item = (dlt_env_ll_item *)malloc(sizeof(dlt_env_ll_item) * ll_set->array_size); if (!ll_set->item) { /* should trigger a warning: no memory left */ ll_set->array_size = 0; return -1; } ll_set->num_elem = 0u; return 0; } /** * @brief release ll_set */ void dlt_env_free_ll_set(dlt_env_ll_set *const ll_set) { if (!ll_set) { return; } if (ll_set->item != NULL) { free(ll_set->item); ll_set->item = NULL; } ll_set->array_size = 0u; ll_set->num_elem = 0u; } /** * @brief increase size of ll_set by LL_SET_INCREASE elements * * @return -1 if memory could not be allocated * @return 0 on success */ int dlt_env_increase_ll_set(dlt_env_ll_set *const ll_set) { dlt_env_ll_item *old_set; size_t old_size; if (!ll_set) { return -1; } old_set = ll_set->item; old_size = ll_set->array_size; ll_set->array_size += DLT_ENV_LL_SET_INCREASE; ll_set->item = (dlt_env_ll_item *)malloc(sizeof(dlt_env_ll_item) * ll_set->array_size); if (!ll_set->item) { /* should trigger a warning: no memory left */ ll_set->array_size -= DLT_ENV_LL_SET_INCREASE; return -1; } else { memcpy(ll_set->item, old_set, sizeof(dlt_env_ll_item) * old_size); free(old_set); return 0; } } /** * @brief extract all items out of string * * The given set is initialized within this function (memory is allocated). * Make sure, that the caller frees this memory when it is no longer needed! * * @return 0 if successful, -1 else */ int dlt_env_extract_ll_set(char **const env, dlt_env_ll_set *const ll_set) { if (!env || !ll_set) { return -1; } if (!(*env)) { return -1; } if (dlt_env_init_ll_set(ll_set) == -1) { return -1; } do { if (ll_set->num_elem == ll_set->array_size) { if (dlt_env_increase_ll_set(ll_set) == -1) { return -1; } } if (dlt_env_extract_ll_item(env, &ll_set->item[ll_set->num_elem++]) == -1) { return -1; } if (**env == ';') { (*env)++; } } while (**env != 0); return 0; } /** * @brief check if two ids match * * @return 1 if matching, 0 if not */ int dlt_env_ids_match(char const *const a, char const *const b) { if (a[0] != b[0]) { return 0; } if (a[1] != b[1]) { return 0; } if (a[2] != b[2]) { return 0; } if (a[3] != b[3]) { return 0; } return 1; } /** * @brief check if (and how) apid and ctid match with given item * * Resulting priorities: * - no apid, no ctid only ll given in item: use ll with prio 1 * - no apid, ctid matches: use ll with prio 2 * - no ctid, apid matches: use ll with prio 3 * - apid, ctid matches: use ll with prio 4 * * In case of error, -1 is returned. */ int dlt_env_ll_item_get_matching_prio(dlt_env_ll_item const *const item, char const *const apid, char const *const ctid) { if ((!item) || (!apid) || (!ctid)) { return -1; } if (item->appId[0] == 0) { if (item->ctxId[0] == 0) { return 1; } else if (dlt_env_ids_match(item->ctxId, ctid)) { return 2; } } else if (dlt_env_ids_match(item->appId, apid)) { if (item->ctxId[0] == 0) { return 3; } else if (dlt_env_ids_match(item->ctxId, ctid)) { return 4; } } return 0; } /** * @brief adjust log-level based on values given through environment * * Iterate over the set of items, and find the best match (\see ll_item_get_matching_prio) * For any item that matches, the one with the highest priority is selected and that * log-level is returned. * * If no item matches or in case of error, the original log-level (\param ll) is returned */ int dlt_env_adjust_ll_from_env(dlt_env_ll_set const *const ll_set, char const *const apid, char const *const ctid, int const ll) { if ((!ll_set) || (!apid) || (!ctid)) { return ll; } int res = ll; int prio = 0; /* no match so far */ size_t i; for (i = 0; i < ll_set->num_elem; ++i) { int p = dlt_env_ll_item_get_matching_prio(&ll_set->item[i], apid, ctid); if (p > prio) { prio = p; res = ll_set->item[i].ll; if (p == 4) { /* maximum reached, immediate return */ return res; } } } return res; } dlt-daemon-2.18.10/src/lib/dlt_filetransfer.c000066400000000000000000000643651446635226000207650ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_filetransfer.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-client.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include #include "dlt_filetransfer.h" #include "dlt_common.h" #include "dlt_user_macros.h" /*!Defines the buffer size of a single file package which will be logged to dlt */ #define BUFFER_SIZE 1024 /*!Defines the minimum timeout between two dlt logs. This is important because dlt should not be flooded with too many logs in a short period of time. */ #define MIN_TIMEOUT 20 #define DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES INT_MAX #define NANOSEC_PER_MILLISEC 1000000 #define NANOSEC_PER_SEC 1000000000 /*!Buffer for dlt file transfer. The size is defined by BUFFER_SIZE */ unsigned char buffer[BUFFER_SIZE]; /*!Get some information about the file size of a file */ /**See stat(2) for more informations. * @param file Absolute file path * @param ok Result of stat * @return Returns the size of the file (if it is a regular file or a symbolic link) in bytes. */ uint32_t getFilesize(const char *file, int *ok) { struct stat st; if (-1 == stat(file, &st)) { /*we can only return 0, as the value is unsigned */ *ok = 0; return 0; } *ok = 1; return (uint32_t)st.st_size; } /** A simple Hash function for C-strings * @param str input string. E.g. a file path. * @param hash start and result value for hash computation * */ void stringHash(const char *str, uint32_t *hash) { if (!str || !hash) { return; } unsigned int len = strlen(str); unsigned int i = 0; if (len <= 0) { return; } for (i = 0; i < len; i++) { *hash = 53 * *hash + str[i]; } } /*!Get some information about the file serial number of a file */ /** See stat(2) for more informations. * @param file Absolute file path * @param ok *ok == 0 -> error; *ok == 1 -> ok * @return Returns a unique number associated with each filename */ uint32_t getFileSerialNumber(const char *file, int *ok) { struct stat st; uint32_t ret; if (-1 == stat(file, &st)) { *ok = 0; ret = 0; } else { *ok = 1; ret = st.st_ino; ret = ret << (sizeof(ret) * 8) / 2; ret |= st.st_size; ret ^= st.st_ctime; stringHash(file, &ret); } return ret; } /*!Returns the creation date of a file */ /** See stat(2) for more informations. * @param file Absolute file path * @param ok Result of stat * @return Returns the creation date of a file */ time_t getFileCreationDate(const char *file, int *ok) { struct stat st; if (-1 == stat(file, &st)) { *ok = 0; return 0; } *ok = 1; return st.st_ctime; } /*!Returns the creation date of a file */ /** Format of the creation date is Day Mon dd hh:mm:ss yyyy * @param file Absolute file path * @param ok Result of stat * @param date Local time * @return Returns the creation date of a file */ void getFileCreationDate2(const char *file, int *ok, char *date) { struct stat st; struct tm ts; if (-1 == stat(file, &st)) { *ok = 0; return; } *ok = 1; tzset(); localtime_r(&st.st_ctime, &ts); asctime_r(&ts, date); } /*!Checks if the file exists */ /**@param file Absolute file path * @return Returns 1 if the file exists, 0 if the file does not exist */ int isFile (const char *file) { struct stat st; return stat (file, &st) == 0; } /*!Waits a period of time */ /**Waits a period of time. The minimal time to wait is MIN_TIMEOUT. This makes sure that the FIFO of dlt is not flooded. * @param timeout Timeout to in ms but can not be smaller as MIN_TIMEOUT */ void doTimeout(int timeout) { struct timespec ts; ts.tv_sec = (timeout * NANOSEC_PER_MILLISEC) / NANOSEC_PER_SEC; ts.tv_nsec = (timeout * NANOSEC_PER_MILLISEC) % NANOSEC_PER_SEC; nanosleep(&ts, NULL); } /*!Checks free space of the user buffer */ /** * @return -1 if more than 50% space in the user buffer is free. Otherwise 1 will be returned. */ int checkUserBufferForFreeSpace() { int total_size, used_size; dlt_user_check_buffer(&total_size, &used_size); if ((total_size - used_size) < (total_size / 2)) { return -1; } return 1; } /*!Deletes the given file */ /** * @param filename Absolute file path * @return If the file is successfully deleted, a zero value is returned.If the file can not be deleted a nonzero value is returned. */ int doRemoveFile(const char *filename) { return remove(filename); } void dlt_user_log_file_errorMessage(DltContext *fileContext, const char *filename, int errorCode) { if (errno != ENOENT) { int ok = 0; uint32_t fserial = getFileSerialNumber(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_errorMessage, error in getFileSerialNumber for: "), DLT_STRING(filename)); } uint32_t fsize = getFilesize(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_errorMessage, error in getFilesize for: "), DLT_STRING(filename)); } char fcreationdate[50] = {0}; getFileCreationDate2(filename, &ok, fcreationdate); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_errorMessage, error in getFilesize for: "), DLT_STRING(filename)); } int package_count = dlt_user_log_file_packagesCount(fileContext, filename); DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("FLER"), DLT_INT(errorCode), DLT_INT(-errno), DLT_UINT(fserial), DLT_STRING(filename), DLT_UINT(fsize), DLT_STRING(fcreationdate), DLT_INT(package_count), DLT_UINT(BUFFER_SIZE), DLT_STRING("FLER") ); } else { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("FLER"), DLT_INT(errorCode), DLT_INT(-errno), DLT_STRING(filename), DLT_STRING("FLER") ); } } /*!Logs specific file inforamtions to dlt */ /**The filename, file size, file serial number and the number of packages will be logged to dlt. * @param fileContext Specific context * @param filename Absolute file path * @return Returns 0 if everything was okey.If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_infoAbout(DltContext *fileContext, const char *filename) { if (isFile(filename)) { int ok; uint32_t fsize = getFilesize(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_infoAbout, Error getting size of file:"), DLT_STRING(filename)); } uint32_t fserialnumber = getFileSerialNumber(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_infoAbout, Error getting serial number of file:"), DLT_STRING(filename)); } char creationdate[50] = {0}; getFileCreationDate2(filename, &ok, creationdate); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_infoAbout, Error getting creation date of file:"), DLT_STRING(filename)); } DLT_LOG(*fileContext, DLT_LOG_INFO, DLT_STRING("FLIF"), DLT_STRING("file serialnumber"), DLT_UINT(fserialnumber), DLT_STRING("filename"), DLT_STRING(filename), DLT_STRING("file size in bytes"), DLT_UINT(fsize), DLT_STRING("file creation date"), DLT_STRING(creationdate), DLT_STRING("number of packages"), DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)), DLT_STRING("FLIF") ); return 0; } else { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_INFO_ABOUT); return DLT_FILETRANSFER_ERROR_INFO_ABOUT; } } /*!Transfer the complete file as several dlt logs. */ /**This method transfer the complete file as several dlt logs. At first it will be checked that the file exist. * In the next step some generic informations about the file will be logged to dlt. * Now the header will be logged to dlt. See the method dlt_user_log_file_header for more informations. * Then the method dlt_user_log_data will be called with the parameter to log all packages in a loop with some timeout. * At last dlt_user_log_end is called to signal that the complete file transfer was okey. This is important for the plugin of the dlt viewer. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param deleteFlag Flag if the file will be deleted after transfer. 1->delete, 0->notDelete * @param timeout Timeout in ms to wait between some logs. Important that the FIFO of dlt will not be flooded with to many messages in a short period of time. * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_complete(DltContext *fileContext, const char *filename, int deleteFlag, int timeout) { if (!isFile(filename)) { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_COMPLETE); return DLT_FILETRANSFER_ERROR_FILE_COMPLETE; } if (dlt_user_log_file_header(fileContext, filename) != 0) { return DLT_FILETRANSFER_ERROR_FILE_COMPLETE1; } if (dlt_user_log_file_data(fileContext, filename, DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES, timeout) != 0) { return DLT_FILETRANSFER_ERROR_FILE_COMPLETE2; } if (dlt_user_log_file_end(fileContext, filename, deleteFlag) != 0) { return DLT_FILETRANSFER_ERROR_FILE_COMPLETE3; } return 0; } /*!This method gives information about the number of packages the file have */ /**Every file will be divided into several packages. Every package will be logged as a single dlt log. * The number of packages depends on the BUFFER_SIZE. * At first it will be checked if the file exist. Then the file will be divided into * several packages depending on the buffer size. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @return Returns the number of packages if everything was okey. If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_packagesCount(DltContext *fileContext, const char *filename) { int packages; uint32_t filesize; if (isFile(filename)) { packages = 1; int ok; filesize = getFilesize(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("Error in: dlt_user_log_file_packagesCount, isFile"), DLT_STRING(filename), DLT_INT(DLT_FILETRANSFER_ERROR_PACKAGE_COUNT)); return -1; } if (filesize < BUFFER_SIZE) { return packages; } else { packages = filesize / BUFFER_SIZE; if (filesize % BUFFER_SIZE == 0) { return packages; } else { return packages + 1; } } } else { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("Error in: dlt_user_log_file_packagesCount, !isFile"), DLT_STRING(filename), DLT_INT(DLT_FILETRANSFER_ERROR_PACKAGE_COUNT)); return -1; } } /*!Transfer the head of the file as a dlt logs. */ /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number, * the file name, the file size, package number the file have and the buffer size. * All these informations are needed from the plugin of the dlt viewer. * See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param alias Alias for the file. An alternative name to show in the receiving end * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_header_alias(DltContext *fileContext, const char *filename, const char *alias) { if (isFile(filename)) { int ok; uint32_t fserialnumber = getFileSerialNumber(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING( "dlt_user_log_file_header_alias, Error getting serial number of file:"), DLT_STRING(filename)); return DLT_FILETRANSFER_FILE_SERIAL_NUMBER; } uint32_t fsize = getFilesize(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING( "dlt_user_log_file_header_alias, Error getting size of file:"), DLT_STRING(filename)); } char fcreationdate[50] = {0}; getFileCreationDate2(filename, &ok, fcreationdate); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING( "dlt_user_log_file_header_alias, Error getting creation date of file:"), DLT_STRING(filename)); } DLT_LOG(*fileContext, DLT_LOG_INFO, DLT_STRING("FLST"), DLT_UINT(fserialnumber), DLT_STRING(alias), DLT_UINT(fsize), DLT_STRING(fcreationdate); DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)), DLT_UINT(BUFFER_SIZE), DLT_STRING("FLST") ); return 0; } else { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_HEAD); return DLT_FILETRANSFER_ERROR_FILE_HEAD; } } /*!Transfer the head of the file as a dlt logs. */ /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number, * the file name, the file size, package number the file have and the buffer size. * All these informations are needed from the plugin of the dlt viewer. * See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_header(DltContext *fileContext, const char *filename) { if (isFile(filename)) { int ok; uint32_t fserialnumber = getFileSerialNumber(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING( "dlt_user_log_file_header, Error getting serial number of file:"), DLT_STRING(filename)); } uint32_t fsize = getFilesize(filename, &ok); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("dlt_user_log_file_header, Error getting size of file:"), DLT_STRING(filename)); } char fcreationdate[50] = {0}; getFileCreationDate2(filename, &ok, fcreationdate); if (!ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING( "dlt_user_log_file_header, Error getting creation date of file:"), DLT_STRING(filename)); } DLT_LOG(*fileContext, DLT_LOG_INFO, DLT_STRING("FLST"), DLT_UINT(fserialnumber), DLT_STRING(filename), DLT_UINT(fsize), DLT_STRING(fcreationdate); DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)), DLT_UINT(BUFFER_SIZE), DLT_STRING("FLST") ); return 0; } else { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_HEAD); return DLT_FILETRANSFER_ERROR_FILE_HEAD; } } /*!Transfer the content data of a file. */ /**See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param packageToTransfer Package number to transfer. If this param is LONG_MAX, the whole file will be transferred with a specific timeout * @param timeout Timeout to wait between dlt logs. Important because the dlt FIFO should not be flooded. Default is defined by MIN_TIMEOUT. The given timeout in ms can not be smaller than MIN_TIMEOUT. * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_data(DltContext *fileContext, const char *filename, int packageToTransfer, int timeout) { FILE *file; int pkgNumber; uint32_t readBytes; if (isFile(filename)) { file = fopen (filename, "rb"); if (file == NULL) { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_DATA); return DLT_FILETRANSFER_ERROR_FILE_DATA; } if (((packageToTransfer != DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES) && (packageToTransfer > dlt_user_log_file_packagesCount(fileContext, filename))) || (packageToTransfer <= 0)) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("Error at dlt_user_log_file_data: packageToTransfer out of scope"), DLT_STRING("packageToTransfer:"), DLT_UINT(packageToTransfer), DLT_STRING("numberOfMaximalPackages:"), DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)), DLT_STRING("for File:"), DLT_STRING(filename) ); fclose(file); return DLT_FILETRANSFER_ERROR_FILE_DATA; } readBytes = 0; if (packageToTransfer != DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES) { /* If a single package should be transferred. The user has to check that the free space in the user buffer > 50% */ /* if(checkUserBufferForFreeSpace()<0) */ /* return DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED; */ if (0 != fseek (file, (packageToTransfer - 1) * BUFFER_SIZE, SEEK_SET)) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("failed to fseek in file: "), DLT_STRING(filename), DLT_STRING("ferror:"), DLT_INT(ferror(file)) ); fclose (file); return -1; } readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file); int ok; uint32_t fserial = getFileSerialNumber(filename, &ok); if (1 != ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("failed to get FileSerialNumber for: "), DLT_STRING(filename)); fclose (file); return DLT_FILETRANSFER_FILE_SERIAL_NUMBER; } DLT_LOG(*fileContext, DLT_LOG_INFO, DLT_STRING("FLDA"), DLT_UINT(fserial), DLT_UINT(packageToTransfer), DLT_RAW(buffer, readBytes), DLT_STRING("FLDA") ); doTimeout(timeout); } else { pkgNumber = 0; while (!feof(file)) { /* If the complete file should be transferred, the user buffer will be checked. */ /* If free space < 50% the package won't be transferred. */ if (checkUserBufferForFreeSpace() > 0) { pkgNumber++; readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file); if (readBytes == 0) { // If the file size is divisible by the package size don't send // one empty FLDA. Also we send the correct number of FLDAs too. break; } int ok; uint32_t fserial = getFileSerialNumber(filename, &ok); if (1 != ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("failed to get FileSerialNumber for: "), DLT_STRING(filename)); fclose(file); return DLT_FILETRANSFER_FILE_SERIAL_NUMBER; } DLT_LOG(*fileContext, DLT_LOG_INFO, DLT_STRING("FLDA"), DLT_UINT(fserial), DLT_UINT(pkgNumber), DLT_RAW(buffer, readBytes), DLT_STRING("FLDA") ); } else { fclose(file); return DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED; } doTimeout(timeout); } } fclose(file); return 0; } else { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_DATA); return DLT_FILETRANSFER_ERROR_FILE_DATA; } } /*!Transfer the end of the file as a dlt logs. */ /**The end of the file must be logged to dlt because the end contains inforamtion about the file serial number. * This informations is needed from the plugin of the dlt viewer. * See the Mainpages.c for more informations. * @param fileContext Specific context to log the file to dlt * @param filename Absolute file path * @param deleteFlag Flag to delete the file after the whole file is transferred (logged to dlt).1->delete,0->NotDelete * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. */ int dlt_user_log_file_end(DltContext *fileContext, const char *filename, int deleteFlag) { if (isFile(filename)) { int ok; uint32_t fserial = getFileSerialNumber(filename, &ok); if (1 != ok) { DLT_LOG(*fileContext, DLT_LOG_ERROR, DLT_STRING("failed to get FileSerialNumber for: "), DLT_STRING(filename)); return DLT_FILETRANSFER_FILE_SERIAL_NUMBER; } DLT_LOG(*fileContext, DLT_LOG_INFO, DLT_STRING("FLFI"), DLT_UINT(fserial), DLT_STRING("FLFI") ); if (deleteFlag) { if (doRemoveFile(filename) != 0) { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_END); return -1; } } return 0; } else { dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_END); return DLT_FILETRANSFER_ERROR_FILE_END; } } dlt-daemon-2.18.10/src/lib/dlt_user.c000066400000000000000000005435101446635226000172510ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user.c */ #include /* for getenv(), free(), atexit() */ #include /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */ #include /* for signal(), SIGPIPE, SIG_IGN */ #if !defined (__WIN32__) # include /* for LOG_... */ # include # include /* POSIX Threads */ #endif #include #include #include #include #include #include /* writev() */ #include #include #ifdef linux # include /* for PR_SET_NAME */ #endif #include /* needed for getpid() */ #include #include #include #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC # include #endif #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC # include #endif #ifdef DLT_LIB_USE_VSOCK_IPC # ifdef linux # include # endif # ifdef __QNX__ # include # endif #endif #include "dlt_user.h" #include "dlt_common.h" #include "dlt_user_shared.h" #include "dlt_user_shared_cfg.h" #include "dlt_user_cfg.h" #ifdef DLT_FATAL_LOG_RESET_ENABLE # define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL) \ do { \ if (LOGLEVEL == DLT_LOG_FATAL) { \ int *p = NULL; \ *p = 0; \ } \ } while (false) #else /* DLT_FATAL_LOG_RESET_ENABLE */ # define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL) #endif /* DLT_FATAL_LOG_RESET_ENABLE */ enum InitState { INIT_UNITIALIZED, INIT_IN_PROGRESS, INIT_DONE }; static DltUser dlt_user; static _Atomic enum InitState dlt_user_init_state = INIT_UNITIALIZED; #define DLT_USER_INITALIZED (dlt_user_init_state == INIT_DONE) static _Atomic int dlt_user_freeing = 0; static bool dlt_user_file_reach_max = false; #ifdef DLT_LIB_USE_FIFO_IPC static char dlt_user_dir[DLT_PATH_MAX]; static char dlt_daemon_fifo[DLT_PATH_MAX]; #endif static sem_t dlt_mutex; static pthread_t dlt_housekeeperthread_handle; /* Sync housekeeper thread start */ pthread_mutex_t dlt_housekeeper_running_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t dlt_housekeeper_running_cond; /* calling dlt_user_atexit_handler() second time fails with error message */ static int atexit_registered = 0; /* used to disallow DLT usage in fork() child */ static int g_dlt_is_child = 0; /* String truncate message */ static const char STR_TRUNCATED_MESSAGE[] = "... <>"; /* Enum for type of string */ enum StringType { ASCII_STRING = 0, UTF8_STRING = 1 }; /* Data type holding "Variable Info" (VARI) properties * Some of the supported data types (eg. bool, string, raw) have only "name", but not "unit". */ typedef struct VarInfo { const char *name; // the "name" attribute (can be NULL) const char *unit; // the "unit" attribute (can be NULL) bool with_unit; // true if the "unit" field is to be considered } VarInfo; #define DLT_UNUSED(x) (void)(x) /* Network trace */ #ifdef DLT_NETWORK_TRACE_ENABLE #define DLT_USER_SEGMENTED_THREAD (1<<2) /* Segmented Network Trace */ #define DLT_MAX_TRACE_SEGMENT_SIZE 1024 #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue" #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF /* Mutex to wait on while message queue is not initialized */ pthread_mutex_t mq_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t mq_init_condition; #endif /* DLT_NETWORK_TRACE_ENABLE */ /* use these variables from common.c*/ extern int logging_mode; extern FILE *logging_handle; void dlt_lock_mutex(pthread_mutex_t *mutex) { int32_t lock_mutex_result = pthread_mutex_lock(mutex); if (lock_mutex_result != 0) dlt_vlog(LOG_ERR, "Mutex lock failed unexpected pid=%i with result %i!\n", getpid(), lock_mutex_result); } void dlt_unlock_mutex(pthread_mutex_t *mutex) { pthread_mutex_unlock(mutex); } /* Structure to pass data to segmented thread */ typedef struct { DltContext *handle; uint32_t id; DltNetworkTraceType nw_trace_type; uint32_t header_len; void *header; uint32_t payload_len; void *payload; } s_segmented_data; /* Function prototypes for internally used functions */ static void dlt_user_housekeeperthread_function(void *ptr); static void dlt_user_atexit_handler(void); static DltReturnValue dlt_user_log_init(DltContext *handle, DltContextData *log); static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype); static DltReturnValue dlt_user_log_send_register_application(void); static DltReturnValue dlt_user_log_send_unregister_application(void); static DltReturnValue dlt_user_log_send_register_context(DltContextData *log); static DltReturnValue dlt_user_log_send_unregister_context(DltContextData *log); static DltReturnValue dlt_send_app_ll_ts_limit(const char *apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus); static DltReturnValue dlt_user_log_send_log_mode(DltUserLogMode mode); static DltReturnValue dlt_user_log_send_marker(); static DltReturnValue dlt_user_print_msg(DltMessage *msg, DltContextData *log); static DltReturnValue dlt_user_log_check_user_message(void); static void dlt_user_log_reattach_to_daemon(void); static DltReturnValue dlt_user_log_send_overflow(void); static DltReturnValue dlt_user_log_out_error_handling(void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3, size_t len3); static void dlt_user_cleanup_handler(void *arg); static int dlt_start_threads(); static void dlt_stop_threads(); static void dlt_fork_child_fork_handler(); #ifdef DLT_NETWORK_TRACE_ENABLE static void dlt_user_trace_network_segmented_thread(void *unused); static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data); #endif static DltReturnValue dlt_user_log_write_string_utils_attr(DltContextData *log, const char *text, const enum StringType type, const char *name, bool with_var_info); static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, size_t length, const enum StringType type, const char *name, bool with_var_info); static DltReturnValue dlt_unregister_app_util(bool force_sending_messages); DltReturnValue dlt_user_check_library_version(const char *user_major_version, const char *user_minor_version) { char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH]; char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH]; dlt_get_major_version(lib_major_version, DLT_USER_MAX_LIB_VERSION_LENGTH); dlt_get_minor_version(lib_minor_version, DLT_USER_MAX_LIB_VERSION_LENGTH); if ((strcmp(lib_major_version, user_major_version) != 0) || (strcmp(lib_minor_version, user_minor_version) != 0)) { dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "DLT Library version check failed! Installed DLT library version is %s.%s - Application using DLT library version %s.%s\n", lib_major_version, lib_minor_version, user_major_version, user_minor_version); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC static DltReturnValue dlt_socket_set_nonblock_and_linger(int sockfd) { int status; struct linger l_opt; status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK); if (status == -1) { dlt_log(LOG_INFO, "Socket cannot be changed to NON BLOCK\n"); return DLT_RETURN_ERROR; } l_opt.l_onoff = 1; l_opt.l_linger = 10; if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &l_opt, sizeof l_opt) < 0) dlt_log(LOG_WARNING, "Failed to set socket linger option\n"); return DLT_RETURN_OK; } #endif #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC static DltReturnValue dlt_initialize_socket_connection(void) { struct sockaddr_un remote; char dltSockBaseDir[DLT_IPC_PATH_MAX]; DLT_SEM_LOCK(); int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (sockfd == DLT_FD_INIT) { dlt_log(LOG_CRIT, "Failed to create socket\n"); DLT_SEM_FREE(); return DLT_RETURN_ERROR; } if (dlt_socket_set_nonblock_and_linger(sockfd) != DLT_RETURN_OK) { close(sockfd); DLT_SEM_FREE(); return DLT_RETURN_ERROR; } remote.sun_family = AF_UNIX; snprintf(dltSockBaseDir, DLT_IPC_PATH_MAX, "%s/dlt", DLT_USER_IPC_PATH); strncpy(remote.sun_path, dltSockBaseDir, sizeof(remote.sun_path)); if (strlen(DLT_USER_IPC_PATH) > DLT_IPC_PATH_MAX) dlt_vlog(LOG_INFO, "Provided path too long...trimming it to path[%s]\n", dltSockBaseDir); if (connect(sockfd, (struct sockaddr *)&remote, sizeof(remote)) == -1) { if (dlt_user.connection_state != DLT_USER_RETRY_CONNECT) { dlt_vlog(LOG_INFO, "Socket %s cannot be opened (errno=%d). Retrying later...\n", dltSockBaseDir, errno); dlt_user.connection_state = DLT_USER_RETRY_CONNECT; } close(sockfd); dlt_user.dlt_log_handle = -1; } else { dlt_user.dlt_log_handle = sockfd; dlt_user.connection_state = DLT_USER_CONNECTED; if (dlt_receiver_init(&(dlt_user.receiver), sockfd, DLT_RECEIVE_SOCKET, DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) { dlt_user_init_state = INIT_UNITIALIZED; close(sockfd); DLT_SEM_FREE(); return DLT_RETURN_ERROR; } } DLT_SEM_FREE(); return DLT_RETURN_OK; } #elif defined DLT_LIB_USE_VSOCK_IPC static DltReturnValue dlt_initialize_vsock_connection() { struct sockaddr_vm remote; DLT_SEM_LOCK(); int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0); if (sockfd == DLT_FD_INIT) { dlt_log(LOG_CRIT, "Failed to create VSOCK socket\n"); DLT_SEM_FREE(); return DLT_RETURN_ERROR; } memset(&remote, 0, sizeof(remote)); remote.svm_family = AF_VSOCK; remote.svm_port = DLT_VSOCK_PORT; remote.svm_cid = VMADDR_CID_HOST; if (connect(sockfd, (struct sockaddr *)&remote, sizeof(remote)) == -1) { if (dlt_user.connection_state != DLT_USER_RETRY_CONNECT) { dlt_vlog(LOG_INFO, "VSOCK socket cannot be opened. Retrying later...\n"); dlt_user.connection_state = DLT_USER_RETRY_CONNECT; } close(sockfd); dlt_user.dlt_log_handle = -1; } else { /* Set to non-blocking after connect() to avoid EINPROGRESS. DltUserConntextionState needs "connecting" state if connect() should be non-blocking. */ if (dlt_socket_set_nonblock_and_linger(sockfd) != DLT_RETURN_OK) { close(sockfd); DLT_SEM_FREE(); return DLT_RETURN_ERROR; } dlt_user.dlt_log_handle = sockfd; dlt_user.connection_state = DLT_USER_CONNECTED; if (dlt_receiver_init(&(dlt_user.receiver), sockfd, DLT_RECEIVE_SOCKET, DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) { dlt_user_init_state = INIT_UNITIALIZED; close(sockfd); DLT_SEM_FREE(); return DLT_RETURN_ERROR; } } DLT_SEM_FREE(); return DLT_RETURN_OK; } #else /* DLT_LIB_USE_FIFO_IPC */ static DltReturnValue dlt_initialize_fifo_connection(void) { char filename[DLT_PATH_MAX]; int ret; snprintf(dlt_user_dir, DLT_PATH_MAX, "%s/dltpipes", dltFifoBaseDir); snprintf(dlt_daemon_fifo, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir); ret = mkdir(dlt_user_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_ISVTX); if ((ret == -1) && (errno != EEXIST)) { dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "FIFO user dir %s cannot be created!\n", dlt_user_dir); return DLT_RETURN_ERROR; } /* if dlt pipes directory is created by the application also chmod the directory */ if (ret == 0) { /* S_ISGID cannot be set by mkdir, let's reassign right bits */ ret = chmod(dlt_user_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH | S_ISGID | S_ISVTX); if (ret == -1) { dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "FIFO user dir %s cannot be chmoded!\n", dlt_user_dir); return DLT_RETURN_ERROR; } } /* create and open DLT user FIFO */ snprintf(filename, DLT_PATH_MAX, "%s/dlt%d", dlt_user_dir, getpid()); /* Try to delete existing pipe, ignore result of unlink */ unlink(filename); ret = mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP); if (ret == -1) dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Loging disabled, FIFO user %s cannot be created!\n", filename); /* S_IWGRP cannot be set by mkfifo (???), let's reassign right bits */ ret = chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP); if (ret == -1) { dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "FIFO user %s cannot be chmoded!\n", dlt_user_dir); return DLT_RETURN_ERROR; } dlt_user.dlt_user_handle = open(filename, O_RDWR | O_NONBLOCK | O_CLOEXEC); if (dlt_user.dlt_user_handle == DLT_FD_INIT) { dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled, FIFO user %s cannot be opened!\n", filename); unlink(filename); return DLT_RETURN_OK; } /* open DLT output FIFO */ dlt_user.dlt_log_handle = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC); if (dlt_user.dlt_log_handle == -1) /* This is a normal usecase. It is OK that the daemon (and thus the FIFO /tmp/dlt) * starts later and some DLT users have already been started before. * Thus it is OK if the FIFO can't be opened. */ dlt_vnlog(LOG_INFO, DLT_USER_BUFFER_LENGTH, "FIFO %s cannot be opened. Retrying later...\n", dlt_daemon_fifo); return DLT_RETURN_OK; } #endif DltReturnValue dlt_init(void) { /* process is exiting. Do not allocate new resources. */ if (dlt_user_freeing != 0) { dlt_vlog(LOG_INFO, "%s logging disabled, process is exiting\n", __func__); /* return negative value, to stop the current log */ return DLT_RETURN_LOGGING_DISABLED; } /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS. * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED * That way it's no problem, if two threads enter this function, because only the very first one will * pass fully. The other one will immediately return, because when it executes the atomic function * dlt_user_init_state won't be INIT_UNITIALIZED anymore. * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running. * Furthermore, this makes sure we enter some function only when dlt_init is fully done. * */ enum InitState expectedInitState = INIT_UNITIALIZED; if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS))) { return DLT_RETURN_OK; } /* check environment variables */ dlt_check_envvar(); /* Check logging mode and internal log file is opened or not*/ if (logging_mode == DLT_LOG_TO_FILE && logging_handle == NULL) { dlt_log_init(logging_mode); } /* Initialize common part of dlt_init()/dlt_init_file() */ if (dlt_init_common() == DLT_RETURN_ERROR) { dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } dlt_user.dlt_is_file = 0; dlt_user.filesize_max = UINT_MAX; dlt_user_file_reach_max = false; dlt_user.overflow = 0; dlt_user.overflow_counter = 0; #ifdef DLT_SHM_ENABLE memset(&(dlt_user.dlt_shm), 0, sizeof(DltShm)); /* init shared memory */ if (dlt_shm_init_client(&(dlt_user.dlt_shm), dltShmName) < DLT_RETURN_OK) dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled," " Shared memory %s cannot be created!\n", dltShmName); #endif #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC if (dlt_initialize_socket_connection() != DLT_RETURN_OK) /* We could connect to the pipe, but not to the socket, which is normally */ /* open before by the DLT daemon => bad failure => return error code */ /* in case application is started before daemon, it is expected behaviour */ return DLT_RETURN_ERROR; #elif defined DLT_LIB_USE_VSOCK_IPC if (dlt_initialize_vsock_connection() != DLT_RETURN_OK) return DLT_RETURN_ERROR; #else /* DLT_LIB_USE_FIFO_IPC */ if (dlt_initialize_fifo_connection() != DLT_RETURN_OK) return DLT_RETURN_ERROR; if (dlt_receiver_init(&(dlt_user.receiver), dlt_user.dlt_user_handle, DLT_RECEIVE_FD, DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) { dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } #endif #ifdef DLT_NETWORK_TRACE_ENABLE /* These will be lazy initialized only when needed */ dlt_user.dlt_segmented_queue_read_handle = -1; dlt_user.dlt_segmented_queue_write_handle = -1; pthread_cond_init(&mq_init_condition, NULL); #endif if (dlt_start_threads() < 0) { dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } /* prepare for fork() call */ pthread_atfork(NULL, NULL, &dlt_fork_child_fork_handler); expectedInitState = INIT_IN_PROGRESS; if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_DONE))) { return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_get_appid(char *appid) { if (appid != NULL) { strncpy(appid, dlt_user.appID, 4); return DLT_RETURN_OK; } else { dlt_log(LOG_ERR, "Invalid parameter.\n"); return DLT_RETURN_WRONG_PARAMETER; } } DltReturnValue dlt_init_file(const char *name) { /* check null pointer */ if (!name) return DLT_RETURN_WRONG_PARAMETER; /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS. * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED * That way it's no problem, if two threads enter this function, because only the very first one will * pass fully. The other one will immediately return, because when it executes the atomic function * dlt_user_init_state won't be INIT_UNITIALIZED anymore. * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running. * Furthermore, this makes sure we enter some function only when dlt_init is fully done. * */ enum InitState expectedInitState = INIT_UNITIALIZED; if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS))) return DLT_RETURN_OK; /* Initialize common part of dlt_init()/dlt_init_file() */ if (dlt_init_common() == DLT_RETURN_ERROR) { expectedInitState = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } dlt_user.dlt_is_file = 1; /* open DLT output file */ dlt_user.dlt_log_handle = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (dlt_user.dlt_log_handle == -1) { dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "Log file %s cannot be opened!\n", name); dlt_user.dlt_is_file = 0; return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_set_filesize_max(unsigned int filesize) { if (dlt_user.dlt_is_file == 0) { dlt_vlog(LOG_ERR, "%s: Library is not configured to log to file\n", __func__); return DLT_RETURN_ERROR; } if (filesize == 0) { dlt_user.filesize_max = UINT_MAX; } else { dlt_user.filesize_max = filesize; } dlt_vlog(LOG_DEBUG, "%s: Defined filesize_max is [%d]\n", __func__, dlt_user.filesize_max); return DLT_RETURN_OK; } #ifdef DLT_NETWORK_TRACE_ENABLE DltReturnValue dlt_init_message_queue(void) { dlt_lock_mutex(&mq_mutex); if ((dlt_user.dlt_segmented_queue_read_handle >= 0) && (dlt_user.dlt_segmented_queue_write_handle >= 0)) { /* Already intialized */ dlt_unlock_mutex(&mq_mutex); return DLT_RETURN_OK; } /* Generate per process name for queue */ char queue_name[NAME_MAX]; snprintf(queue_name, NAME_MAX, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid()); /* Maximum queue size is 10, limit to size of pointers */ struct mq_attr mqatr; mqatr.mq_flags = 0; mqatr.mq_maxmsg = 10; mqatr.mq_msgsize = sizeof(s_segmented_data *); mqatr.mq_curmsgs = 0; /** * Create the message queue. It must be newly created * if old one was left by a crashing process. * */ dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT | O_RDONLY | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr); if (dlt_user.dlt_segmented_queue_read_handle < 0) { if (errno == EEXIST) { dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n"); if (mq_unlink(queue_name) < 0) dlt_vnlog(LOG_CRIT, 256, "Could not delete existing message queue!: %s \n", strerror(errno)); else /* Retry */ dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT | O_RDONLY | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr); } if (dlt_user.dlt_segmented_queue_read_handle < 0) { dlt_vnlog(LOG_CRIT, 256, "Can't create message queue read handle!: %s \n", strerror(errno)); dlt_unlock_mutex(&mq_mutex); return DLT_RETURN_ERROR; } } dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY | O_NONBLOCK); if (dlt_user.dlt_segmented_queue_write_handle < 0) { dlt_vnlog(LOG_CRIT, 256, "Can't open message queue write handle!: %s \n", strerror(errno)); dlt_unlock_mutex(&mq_mutex); return DLT_RETURN_ERROR; } pthread_cond_signal(&mq_init_condition); dlt_unlock_mutex(&mq_mutex); return DLT_RETURN_OK; } #endif /* DLT_NETWORK_TRACE_ENABLE */ /* Return true if verbose mode is to be used for this DltContextData */ static inline bool is_verbose_mode(int8_t dltuser_verbose_mode, const DltContextData* log) { return (dltuser_verbose_mode == 1) || (log != NULL && log->verbose_mode); } DltReturnValue dlt_init_common(void) { char *env_local_print; char *env_initial_log_level; char *env_buffer_min; uint32_t buffer_min = DLT_USER_RINGBUFFER_MIN_SIZE; char *env_buffer_max; uint32_t buffer_max = DLT_USER_RINGBUFFER_MAX_SIZE; char *env_buffer_step; uint32_t buffer_step = DLT_USER_RINGBUFFER_STEP_SIZE; char *env_disable_extended_header_for_nonverbose; char *env_log_buffer_len; uint32_t buffer_max_configured = 0; uint32_t header_size = 0; /* Binary semaphore for threads */ if (sem_init(&dlt_mutex, 0, 1) == -1) { dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } /* set to unknown state of connected client */ dlt_user.log_state = -1; dlt_user.dlt_log_handle = -1; dlt_user.dlt_user_handle = DLT_FD_INIT; dlt_set_id(dlt_user.ecuID, DLT_USER_DEFAULT_ECU_ID); dlt_set_id(dlt_user.appID, ""); dlt_user.application_description = NULL; /* Verbose mode is enabled by default */ dlt_user.verbose_mode = 1; /* header_size is used for resend buffer * so it won't include DltStorageHeader */ header_size = sizeof(DltUserHeader) + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra); /* Use extended header for non verbose is enabled by default */ dlt_user.use_extended_header_for_non_verbose = DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE; /* Use extended header for non verbose is modified as per environment variable */ env_disable_extended_header_for_nonverbose = getenv(DLT_USER_ENV_DISABLE_EXTENDED_HEADER_FOR_NONVERBOSE); if (env_disable_extended_header_for_nonverbose) { if (strcmp(env_disable_extended_header_for_nonverbose, "1") == 0) dlt_user.use_extended_header_for_non_verbose = DLT_USER_NO_USE_EXTENDED_HEADER_FOR_NONVERBOSE; } if (dlt_user.use_extended_header_for_non_verbose == DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE) header_size += (uint32_t) sizeof(DltExtendedHeader); /* With session id is enabled by default */ dlt_user.with_session_id = DLT_USER_WITH_SESSION_ID; /* With timestamp is enabled by default */ dlt_user.with_timestamp = DLT_USER_WITH_TIMESTAMP; /* With timestamp is enabled by default */ dlt_user.with_ecu_id = DLT_USER_WITH_ECU_ID; /* Local print is disabled by default */ dlt_user.enable_local_print = 0; dlt_user.local_print_mode = DLT_PM_UNSET; dlt_user.timeout_at_exit_handler = DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT; env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE); if (env_local_print) { if (strcmp(env_local_print, "AUTOMATIC") == 0) dlt_user.local_print_mode = DLT_PM_AUTOMATIC; else if (strcmp(env_local_print, "FORCE_ON") == 0) dlt_user.local_print_mode = DLT_PM_FORCE_ON; else if (strcmp(env_local_print, "FORCE_OFF") == 0) dlt_user.local_print_mode = DLT_PM_FORCE_OFF; } env_initial_log_level = getenv("DLT_INITIAL_LOG_LEVEL"); if (env_initial_log_level != NULL) { if (dlt_env_extract_ll_set(&env_initial_log_level, &dlt_user.initial_ll_set) != 0) dlt_vlog(LOG_WARNING, "Unable to parse initial set of log-levels from environment! Env:\n%s\n", getenv("DLT_INITIAL_LOG_LEVEL")); } /* Initialize LogLevel/TraceStatus field */ DLT_SEM_LOCK(); dlt_user.dlt_ll_ts = NULL; dlt_user.dlt_ll_ts_max_num_entries = 0; dlt_user.dlt_ll_ts_num_entries = 0; env_buffer_min = getenv(DLT_USER_ENV_BUFFER_MIN_SIZE); env_buffer_max = getenv(DLT_USER_ENV_BUFFER_MAX_SIZE); env_buffer_step = getenv(DLT_USER_ENV_BUFFER_STEP_SIZE); if (env_buffer_min != NULL) { buffer_min = (uint32_t)strtol(env_buffer_min, NULL, 10); if ((errno == EINVAL) || (errno == ERANGE)) { dlt_vlog(LOG_ERR, "Wrong value specified for %s. Using default\n", DLT_USER_ENV_BUFFER_MIN_SIZE); buffer_min = DLT_USER_RINGBUFFER_MIN_SIZE; } } if (env_buffer_max != NULL) { buffer_max = (uint32_t)strtol(env_buffer_max, NULL, 10); if ((errno == EINVAL) || (errno == ERANGE)) { dlt_vlog(LOG_ERR, "Wrong value specified for %s. Using default\n", DLT_USER_ENV_BUFFER_MAX_SIZE); buffer_max = DLT_USER_RINGBUFFER_MAX_SIZE; } } if (env_buffer_step != NULL) { buffer_step = (uint32_t)strtol(env_buffer_step, NULL, 10); if ((errno == EINVAL) || (errno == ERANGE)) { dlt_vlog(LOG_ERR, "Wrong value specified for %s. Using default\n", DLT_USER_ENV_BUFFER_STEP_SIZE); buffer_step = DLT_USER_RINGBUFFER_STEP_SIZE; } } /* init log buffer size */ dlt_user.log_buf_len = DLT_USER_BUF_MAX_SIZE; env_log_buffer_len = getenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); if (env_log_buffer_len != NULL) { buffer_max_configured = (uint32_t)strtol(env_log_buffer_len, NULL, 10); if (buffer_max_configured > DLT_LOG_MSG_BUF_MAX_SIZE) { dlt_user.log_buf_len = DLT_LOG_MSG_BUF_MAX_SIZE; dlt_vlog(LOG_WARNING, "Configured size exceeds maximum allowed size,restricting to max [65535 bytes]\n"); } else { dlt_user.log_buf_len = (uint16_t) buffer_max_configured; dlt_vlog(LOG_INFO, "Configured buffer size to [%u bytes]\n", buffer_max_configured); } } if (dlt_user.resend_buffer == NULL) { dlt_user.resend_buffer = calloc(sizeof(unsigned char), (dlt_user.log_buf_len + header_size)); if (dlt_user.resend_buffer == NULL) { dlt_user_init_state = INIT_UNITIALIZED; DLT_SEM_FREE(); dlt_vlog(LOG_ERR, "cannot allocate memory for resend buffer\n"); return DLT_RETURN_ERROR; } } dlt_user.disable_injection_msg = 0; if (getenv(DLT_USER_ENV_DISABLE_INJECTION_MSG)) { dlt_log(LOG_WARNING, "Injection message is disabled\n"); dlt_user.disable_injection_msg = 1; } if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer), buffer_min, buffer_max, buffer_step) == DLT_RETURN_ERROR) { dlt_user_init_state = INIT_UNITIALIZED; DLT_SEM_FREE(); return DLT_RETURN_ERROR; } DLT_SEM_FREE(); signal(SIGPIPE, SIG_IGN); /* ignore pipe signals */ if (atexit_registered == 0) { atexit_registered = 1; atexit(dlt_user_atexit_handler); } #ifdef DLT_TEST_ENABLE dlt_user.corrupt_user_header = 0; dlt_user.corrupt_message_size = 0; dlt_user.corrupt_message_size_size = 0; #endif return DLT_RETURN_OK; } void dlt_user_atexit_handler(void) { /* parent will do clean-up */ if (g_dlt_is_child) return; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); /* close file */ dlt_log_free(); return; } /* Try to resend potential log messages in the user buffer */ int count = dlt_user_atexit_blow_out_user_buffer(); if (count != 0) dlt_vnlog(LOG_WARNING, 128, "Lost log messages in user buffer when exiting: %i\n", count); /* Unregister app (this also unregisters all contexts in daemon) */ /* Ignore return value */ dlt_unregister_app_util(false); /* Cleanup */ /* Ignore return value */ dlt_free(); } int dlt_user_atexit_blow_out_user_buffer(void) { int count, ret; struct timespec ts; uint32_t exitTime = dlt_uptime() + dlt_user.timeout_at_exit_handler; /* Send content of ringbuffer */ DLT_SEM_LOCK(); count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer)); DLT_SEM_FREE(); if (count > 0) { while (dlt_uptime() < exitTime) { if (dlt_user.dlt_log_handle == -1) { /* Reattach to daemon if neccesary */ dlt_user_log_reattach_to_daemon(); if ((dlt_user.dlt_log_handle != -1) && (dlt_user.overflow_counter)) { if (dlt_user_log_send_overflow() == 0) { dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "%u messages discarded!\n", dlt_user.overflow_counter); dlt_user.overflow_counter = 0; } } } if (dlt_user.dlt_log_handle != -1) { ret = dlt_user_log_resend_buffer(); if (ret == 0) { DLT_SEM_LOCK(); count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer)); DLT_SEM_FREE(); return count; } } ts.tv_sec = 0; ts.tv_nsec = DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP; nanosleep(&ts, NULL); } DLT_SEM_LOCK(); count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer)); DLT_SEM_FREE(); } return count; } static void dlt_user_free_buffer(unsigned char **buffer) { if (*buffer) { free(*buffer); *buffer = NULL; } } DltReturnValue dlt_free(void) { uint32_t i; int ret = 0; int expected = 0; #ifdef DLT_LIB_USE_FIFO_IPC char filename[DLT_PATH_MAX]; #endif /* library is freeing its resources. Avoid to allocate it in dlt_init() */ if (!(atomic_compare_exchange_strong(&dlt_user_freeing, &expected, 1))) { /* resources are already being freed. Do nothing and return. */ return DLT_RETURN_ERROR; } if (!DLT_USER_INITALIZED) { dlt_user_freeing = 0; return DLT_RETURN_ERROR; } dlt_stop_threads(); dlt_user_init_state = INIT_UNITIALIZED; #ifdef DLT_LIB_USE_FIFO_IPC if (dlt_user.dlt_user_handle != DLT_FD_INIT) { close(dlt_user.dlt_user_handle); dlt_user.dlt_user_handle = DLT_FD_INIT; snprintf(filename, DLT_PATH_MAX, "%s/dlt%d", dlt_user_dir, getpid()); unlink(filename); } #endif #ifdef DLT_SHM_ENABLE /* free shared memory */ dlt_shm_free_client(&dlt_user.dlt_shm); #endif if (dlt_user.dlt_log_handle != -1) { /* close log file/output fifo to daemon */ #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC ret = shutdown(dlt_user.dlt_log_handle, SHUT_WR); if (ret < 0) { dlt_vlog(LOG_WARNING, "%s: shutdown failed: %s\n", __func__, strerror(errno)); } else { ssize_t bytes_read = 0; int prev_errno = 0; struct pollfd nfd[1]; nfd[0].events = POLLIN; nfd[0].fd = dlt_user.dlt_log_handle; while (1) { ret = poll(nfd, 1, DLT_USER_RECEIVE_MDELAY); /* In case failure of polling or reaching timeout, * continue to close socket anyway. * */ if (ret < 0) { dlt_vlog(LOG_WARNING, "[%s] Failed to poll with error [%s]\n", __func__, strerror(errno)); break; } else if (ret == 0) { dlt_vlog(LOG_DEBUG, "[%s] Polling timeout\n", __func__); break; } else { /* It could take some time to get the socket is shutdown * So it means there could be some data available to read. * Try to consume the data and poll the socket again. * If read fails, time to close the socket then. */ dlt_vlog(LOG_DEBUG, "[%s] polling returns [%d] with revent [0x%x]." "There are something to read\n", __func__, ret, (unsigned int)nfd[0].revents); bytes_read = read(dlt_user.dlt_log_handle, dlt_user.resend_buffer, dlt_user.log_buf_len); prev_errno = errno; if (bytes_read < 0) { dlt_vlog(LOG_WARNING, "[%s] Failed to read with error [%s]\n", __func__, strerror(prev_errno)); if ((prev_errno == EAGAIN) || (EWOULDBLOCK != EAGAIN && prev_errno == EWOULDBLOCK)) continue; else break; } if (bytes_read >= 0) { if (!bytes_read) break; dlt_vlog(LOG_NOTICE, "[%s] data is still readable... [%zd] bytes read\n", __func__, bytes_read); } } } } #endif ret = close(dlt_user.dlt_log_handle); if (ret < 0) dlt_vlog(LOG_WARNING, "%s: close failed: %s\n", __func__, strerror(errno)); dlt_user.dlt_log_handle = -1; } /* Ignore return value */ DLT_SEM_LOCK(); dlt_receiver_free(&(dlt_user.receiver)); DLT_SEM_FREE(); /* Ignore return value */ DLT_SEM_LOCK(); dlt_user_free_buffer(&(dlt_user.resend_buffer)); dlt_buffer_free_dynamic(&(dlt_user.startup_buffer)); /* Clear and free local stored application information */ if (dlt_user.application_description != NULL) free(dlt_user.application_description); dlt_user.application_description = NULL; if (dlt_user.dlt_ll_ts) { for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) { if (dlt_user.dlt_ll_ts[i].context_description != NULL) { free (dlt_user.dlt_ll_ts[i].context_description); dlt_user.dlt_ll_ts[i].context_description = NULL; } if (dlt_user.dlt_ll_ts[i].log_level_ptr != NULL) { free(dlt_user.dlt_ll_ts[i].log_level_ptr); dlt_user.dlt_ll_ts[i].log_level_ptr = NULL; } if (dlt_user.dlt_ll_ts[i].trace_status_ptr != NULL) { free(dlt_user.dlt_ll_ts[i].trace_status_ptr); dlt_user.dlt_ll_ts[i].trace_status_ptr = NULL; } if (dlt_user.dlt_ll_ts[i].injection_table != NULL) { free(dlt_user.dlt_ll_ts[i].injection_table); dlt_user.dlt_ll_ts[i].injection_table = NULL; } dlt_user.dlt_ll_ts[i].nrcallbacks = 0; dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0; } free(dlt_user.dlt_ll_ts); dlt_user.dlt_ll_ts = NULL; dlt_user.dlt_ll_ts_max_num_entries = 0; dlt_user.dlt_ll_ts_num_entries = 0; } dlt_env_free_ll_set(&dlt_user.initial_ll_set); DLT_SEM_FREE(); #ifdef DLT_NETWORK_TRACE_ENABLE char queue_name[NAME_MAX]; snprintf(queue_name, NAME_MAX, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid()); /** * Ignore errors from these, to not to spam user if dlt_free * is accidentally called multiple times. */ if (dlt_user.dlt_segmented_queue_write_handle > 0) mq_close(dlt_user.dlt_segmented_queue_write_handle); if (dlt_user.dlt_segmented_queue_read_handle > 0) mq_close(dlt_user.dlt_segmented_queue_read_handle); if ((dlt_user.dlt_segmented_queue_write_handle > 0) || (dlt_user.dlt_segmented_queue_read_handle > 0)) mq_unlink(queue_name); dlt_user.dlt_segmented_queue_write_handle = DLT_FD_INIT; dlt_user.dlt_segmented_queue_read_handle = DLT_FD_INIT; pthread_cond_destroy(&mq_init_condition); #endif /* DLT_NETWORK_TRACE_ENABLE */ sem_destroy(&dlt_mutex); /* allow the user app to do dlt_init() again. */ /* The flag is unset only to keep almost the same behaviour as before, on EntryNav */ /* This should be removed for other projects (see documentation of dlt_free() */ dlt_user_freeing = 0; return DLT_RETURN_OK; } DltReturnValue dlt_check_library_version(const char *user_major_version, const char *user_minor_version) { return dlt_user_check_library_version(user_major_version, user_minor_version); } DltReturnValue dlt_register_app(const char *apid, const char *description) { DltReturnValue ret = DLT_RETURN_OK; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } if ((apid == NULL) || (apid[0] == '\0')) return DLT_RETURN_WRONG_PARAMETER; /* check if application already registered */ /* if yes do not register again */ if (apid[1] == 0) { if (apid[0] == dlt_user.appID[0]) return DLT_RETURN_OK; } else if (apid[2] == 0) { if ((apid[0] == dlt_user.appID[0]) && (apid[1] == dlt_user.appID[1])) return DLT_RETURN_OK; } else if (apid[3] == 0) { if ((apid[0] == dlt_user.appID[0]) && (apid[1] == dlt_user.appID[1]) && (apid[2] == dlt_user.appID[2])) return DLT_RETURN_OK; } else if ((apid[0] == dlt_user.appID[0]) && (apid[1] == dlt_user.appID[1]) && (apid[2] == dlt_user.appID[2]) && (apid[3] == dlt_user.appID[3])) { return DLT_RETURN_OK; } DLT_SEM_LOCK(); /* Store locally application id and application description */ dlt_set_id(dlt_user.appID, apid); if (dlt_user.application_description != NULL) free(dlt_user.application_description); dlt_user.application_description = NULL; if (description != NULL) { size_t desc_len = strlen(description); dlt_user.application_description = malloc(desc_len + 1); if (dlt_user.application_description) { strncpy(dlt_user.application_description, description, desc_len + 1); } else { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } } DLT_SEM_FREE(); ret = dlt_user_log_send_register_application(); if ((ret == DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1)) ret = dlt_user_log_resend_buffer(); return ret; } DltReturnValue dlt_register_context(DltContext *handle, const char *contextid, const char *description) { /* check nullpointer */ if (handle == NULL) return DLT_RETURN_WRONG_PARAMETER; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } if ((contextid == NULL) || (contextid[0] == '\0')) return DLT_RETURN_WRONG_PARAMETER; return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET); } DltReturnValue dlt_register_context_ll_ts_llccb(DltContext *handle, const char *contextid, const char *description, int loglevel, int tracestatus, void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status)) { DltContextData log; uint32_t i; int envLogLevel = DLT_USER_LOG_LEVEL_NOT_SET; /*check nullpointer */ if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0')) return DLT_RETURN_WRONG_PARAMETER; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) { dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel); return DLT_RETURN_WRONG_PARAMETER; } if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) { dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus); return DLT_RETURN_WRONG_PARAMETER; } if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* Reset message counter */ handle->mcnt = 0; /* Store context id in log level/trace status field */ /* Check if already registered, else register context */ DLT_SEM_LOCK(); /* Check of double context registration removed */ /* Double registration is already checked by daemon */ /* Allocate or expand context array */ if (dlt_user.dlt_ll_ts == NULL) { dlt_user.dlt_ll_ts = (dlt_ll_ts_type *)malloc(sizeof(dlt_ll_ts_type) * DLT_USER_CONTEXT_ALLOC_SIZE); if (dlt_user.dlt_ll_ts == NULL) { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE; /* Initialize new entries */ for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) { dlt_set_id(dlt_user.dlt_ll_ts[i].contextID, ""); /* At startup, logging and tracing is locally enabled */ /* the correct log level/status is set after received from daemon */ dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL; dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS; dlt_user.dlt_ll_ts[i].log_level_ptr = 0; dlt_user.dlt_ll_ts[i].trace_status_ptr = 0; dlt_user.dlt_ll_ts[i].context_description = 0; dlt_user.dlt_ll_ts[i].injection_table = 0; dlt_user.dlt_ll_ts[i].nrcallbacks = 0; dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0; } } else if ((dlt_user.dlt_ll_ts_num_entries % DLT_USER_CONTEXT_ALLOC_SIZE) == 0) { /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */ dlt_ll_ts_type *old_ll_ts; uint32_t old_max_entries; old_ll_ts = dlt_user.dlt_ll_ts; old_max_entries = dlt_user.dlt_ll_ts_max_num_entries; dlt_user.dlt_ll_ts_max_num_entries = ((dlt_user.dlt_ll_ts_num_entries / DLT_USER_CONTEXT_ALLOC_SIZE) + 1) * DLT_USER_CONTEXT_ALLOC_SIZE; dlt_user.dlt_ll_ts = (dlt_ll_ts_type *)malloc(sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_max_num_entries); if (dlt_user.dlt_ll_ts == NULL) { dlt_user.dlt_ll_ts = old_ll_ts; dlt_user.dlt_ll_ts_max_num_entries = old_max_entries; DLT_SEM_FREE(); return DLT_RETURN_ERROR; } memcpy(dlt_user.dlt_ll_ts, old_ll_ts, sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_num_entries); free(old_ll_ts); /* Initialize new entries */ for (i = dlt_user.dlt_ll_ts_num_entries; i < dlt_user.dlt_ll_ts_max_num_entries; i++) { dlt_set_id(dlt_user.dlt_ll_ts[i].contextID, ""); /* At startup, logging and tracing is locally enabled */ /* the correct log level/status is set after received from daemon */ dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL; dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS; dlt_user.dlt_ll_ts[i].log_level_ptr = 0; dlt_user.dlt_ll_ts[i].trace_status_ptr = 0; dlt_user.dlt_ll_ts[i].context_description = 0; dlt_user.dlt_ll_ts[i].injection_table = 0; dlt_user.dlt_ll_ts[i].nrcallbacks = 0; dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0; } } /* New context entry to be initialized */ dlt_ll_ts_type *ctx_entry; ctx_entry = &dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries]; /* Store locally context id and context description */ dlt_set_id(ctx_entry->contextID, contextid); if (ctx_entry->context_description != 0) free(ctx_entry->context_description); ctx_entry->context_description = 0; if (description != 0) { size_t desc_len = strlen(description); ctx_entry->context_description = malloc(desc_len + 1); if (ctx_entry->context_description == 0) { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } strncpy(ctx_entry->context_description, description, desc_len + 1); } if (ctx_entry->log_level_ptr == 0) { ctx_entry->log_level_ptr = malloc(sizeof(int8_t)); if (ctx_entry->log_level_ptr == 0) { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } } if (ctx_entry->trace_status_ptr == 0) { ctx_entry->trace_status_ptr = malloc(sizeof(int8_t)); if (ctx_entry->trace_status_ptr == 0) { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } } /* check if the log level is set in the environement */ envLogLevel = dlt_env_adjust_ll_from_env(&dlt_user.initial_ll_set, dlt_user.appID, contextid, DLT_USER_LOG_LEVEL_NOT_SET); if (envLogLevel != DLT_USER_LOG_LEVEL_NOT_SET) { ctx_entry->log_level = (int8_t) envLogLevel; loglevel = envLogLevel; } else if (loglevel != DLT_USER_LOG_LEVEL_NOT_SET) { ctx_entry->log_level = (int8_t) loglevel; } if (tracestatus != DLT_USER_TRACE_STATUS_NOT_SET) ctx_entry->trace_status = (int8_t) tracestatus; /* Prepare transfer struct */ dlt_set_id(handle->contextID, contextid); handle->log_level_pos = (int32_t) dlt_user.dlt_ll_ts_num_entries; handle->log_level_ptr = ctx_entry->log_level_ptr; handle->trace_status_ptr = ctx_entry->trace_status_ptr; log.context_description = ctx_entry->context_description; *(ctx_entry->log_level_ptr) = ctx_entry->log_level; *(ctx_entry->trace_status_ptr) = ctx_entry->trace_status = (int8_t) tracestatus; ctx_entry->log_level_changed_callback = dlt_log_level_changed_callback; log.log_level = loglevel; log.trace_status = tracestatus; dlt_user.dlt_ll_ts_num_entries++; DLT_SEM_FREE(); return dlt_user_log_send_register_context(&log); } DltReturnValue dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char *description, int loglevel, int tracestatus) { return dlt_register_context_ll_ts_llccb(handle, contextid, description, loglevel, tracestatus, NULL); } DltReturnValue dlt_register_context_llccb(DltContext *handle, const char *contextid, const char *description, void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status)) { if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0')) return DLT_RETURN_WRONG_PARAMETER; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } return dlt_register_context_ll_ts_llccb(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET, dlt_log_level_changed_callback); } /* If force_sending_messages is set to true, do not clean appIDs when there are * still data in startup_buffer. atexit_handler will free the appIDs */ DltReturnValue dlt_unregister_app_util(bool force_sending_messages) { DltReturnValue ret = DLT_RETURN_OK; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } /* Inform daemon to unregister application and all of its contexts */ ret = dlt_user_log_send_unregister_application(); DLT_SEM_LOCK(); int count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer)); if (!force_sending_messages || (force_sending_messages && count == 0)) { /* Clear and free local stored application information */ dlt_set_id(dlt_user.appID, ""); if (dlt_user.application_description != NULL) free(dlt_user.application_description); dlt_user.application_description = NULL; } DLT_SEM_FREE(); return ret; } DltReturnValue dlt_unregister_app(void) { return dlt_unregister_app_util(false); } DltReturnValue dlt_unregister_app_flush_buffered_logs(void) { DltReturnValue ret = DLT_RETURN_OK; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } if (dlt_user.dlt_log_handle != -1) { do ret = dlt_user_log_resend_buffer(); while ((ret != DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1)); } return dlt_unregister_app_util(true); } DltReturnValue dlt_unregister_context(DltContext *handle) { DltContextData log; DltReturnValue ret = DLT_RETURN_OK; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; log.handle = NULL; log.context_description = NULL; if (dlt_user_log_init(handle, &log) <= DLT_RETURN_ERROR) return DLT_RETURN_ERROR; DLT_SEM_LOCK(); handle->log_level_ptr = NULL; handle->trace_status_ptr = NULL; if (dlt_user.dlt_ll_ts != NULL) { /* Clear and free local stored context information */ dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, ""); dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL; dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS; if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description != NULL) free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description); if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr != NULL) { free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr); dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = NULL; } if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr != NULL) { free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr); dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = NULL; } dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = NULL; if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table != NULL) { free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table); dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = NULL; } dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0; dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_changed_callback = 0; } DLT_SEM_FREE(); /* Inform daemon to unregister context */ ret = dlt_user_log_send_unregister_context(&log); return ret; } DltReturnValue dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus) { uint32_t i; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) { dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel); return DLT_RETURN_WRONG_PARAMETER; } if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) { dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus); return DLT_RETURN_WRONG_PARAMETER; } if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } DLT_SEM_LOCK(); if (dlt_user.dlt_ll_ts == NULL) { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } /* Update local structures */ for (i = 0; i < dlt_user.dlt_ll_ts_num_entries; i++) { dlt_user.dlt_ll_ts[i].log_level = loglevel; dlt_user.dlt_ll_ts[i].trace_status = tracestatus; if (dlt_user.dlt_ll_ts[i].log_level_ptr) *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel; if (dlt_user.dlt_ll_ts[i].trace_status_ptr) *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus; } DLT_SEM_FREE(); /* Inform DLT server about update */ return dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus); } int dlt_get_log_state() { return dlt_user.log_state; } DltReturnValue dlt_set_log_mode(DltUserLogMode mode) { DLT_UNUSED(mode); /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) { dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode); return DLT_RETURN_WRONG_PARAMETER; } if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } return dlt_user_log_send_log_mode(mode); } int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds) { /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; if (DLT_USER_INITALIZED == 0) if (dlt_init() < 0) return -1; dlt_user.timeout_at_exit_handler = timeout_in_milliseconds * 10; return 0; } /* ********************************************************************************************* */ DltReturnValue dlt_user_log_write_start_init(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, bool is_verbose) { DLT_LOG_FATAL_RESET_TRAP(loglevel); /* initialize values */ if ((dlt_user_log_init(handle, log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL)) return DLT_RETURN_ERROR; log->args_num = 0; log->log_level = loglevel; log->size = 0; log->use_timestamp = DLT_AUTO_TIMESTAMP; log->verbose_mode = is_verbose; return DLT_RETURN_TRUE; } static DltReturnValue dlt_user_log_write_start_internal(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, uint32_t messageid, bool is_verbose); inline DltReturnValue dlt_user_log_write_start(DltContext *handle, DltContextData *log, DltLogLevelType loglevel) { return dlt_user_log_write_start_internal(handle, log, loglevel, DLT_USER_DEFAULT_MSGID, true); } DltReturnValue dlt_user_log_write_start_id(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, uint32_t messageid) { return dlt_user_log_write_start_internal(handle, log, loglevel, messageid, false); } DltReturnValue dlt_user_log_write_start_internal(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, uint32_t messageid, bool is_verbose) { int ret = DLT_RETURN_TRUE; /* check nullpointer */ if ((handle == NULL) || (log == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; /* check log levels */ ret = dlt_user_is_logLevel_enabled(handle, loglevel); if (ret == DLT_RETURN_WRONG_PARAMETER) { return DLT_RETURN_WRONG_PARAMETER; } else if (ret == DLT_RETURN_LOGGING_DISABLED) { log->handle = NULL; return DLT_RETURN_OK; } ret = dlt_user_log_write_start_init(handle, log, loglevel, is_verbose); if (ret == DLT_RETURN_TRUE) { /* initialize values */ if ((NULL != log->buffer)) { free(log->buffer); log->buffer = NULL; } else { log->buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); } if (log->buffer == NULL) { dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); return DLT_RETURN_ERROR; } else { /* In non-verbose mode, insert message id */ if (!is_verbose_mode(dlt_user.verbose_mode, log)) { if ((sizeof(uint32_t)) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; /* Write message id */ memcpy(log->buffer, &(messageid), sizeof(uint32_t)); log->size = sizeof(uint32_t); /* as the message id is part of each message in non-verbose mode, * it doesn't increment the argument counter in extended header (if used) */ } } } return ret; } DltReturnValue dlt_user_log_write_start_w_given_buffer(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, char *buffer, size_t size, int32_t args_num) { int ret = DLT_RETURN_TRUE; /* check nullpointer */ if ((handle == NULL) || (log == NULL) || (buffer == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* discard unexpected parameters */ if ((size <= 0) || (size > dlt_user.log_buf_len) || (args_num <= 0)) return DLT_RETURN_WRONG_PARAMETER; /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; /* discard non-verbose mode */ if (dlt_user.verbose_mode == 0) return DLT_RETURN_ERROR; ret = dlt_user_log_write_start_init(handle, log, loglevel, true); if (ret == DLT_RETURN_TRUE) { log->buffer = (unsigned char *)buffer; log->size = size; log->args_num = args_num; } return ret; } DltReturnValue dlt_user_log_write_finish(DltContextData *log) { int ret = DLT_RETURN_ERROR; if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; ret = dlt_user_log_send_log(log, DLT_TYPE_LOG); dlt_user_free_buffer(&(log->buffer)); return ret; } DltReturnValue dlt_user_log_write_finish_w_given_buffer(DltContextData *log) { int ret = DLT_RETURN_ERROR; if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; ret = dlt_user_log_send_log(log, DLT_TYPE_LOG); return ret; } static DltReturnValue dlt_user_log_write_raw_internal(DltContextData *log, const void *data, uint16_t length, DltFormatType type, const char *name, bool with_var_info) { /* check nullpointer */ if ((log == NULL) || ((data == NULL) && (length != 0))) return DLT_RETURN_WRONG_PARAMETER; /* Have to cast type to signed type because some compilers assume that DltFormatType is unsigned and issue a warning */ if (((int16_t)type < DLT_FORMAT_DEFAULT) || (type >= DLT_FORMAT_MAX)) { dlt_vlog(LOG_ERR, "Format type %u is outside valid range", type); return DLT_RETURN_WRONG_PARAMETER; } if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } const uint16_t name_size = (name != NULL) ? strlen(name)+1 : 0; size_t needed_size = length + sizeof(uint16_t); if ((log->size + needed_size) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; if (is_verbose_mode(dlt_user.verbose_mode, log)) { uint32_t type_info = DLT_TYPE_INFO_RAWD; needed_size += sizeof(uint32_t); // Type Info field if (with_var_info) { needed_size += sizeof(uint16_t); // length of name needed_size += name_size; // the name itself type_info |= DLT_TYPE_INFO_VARI; } if ((log->size + needed_size) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; // Genivi extension: put formatting hints into the unused (for RAWD) TYLE + SCOD fields. // The SCOD field holds the base (hex or bin); the TYLE field holds the column width (8bit..64bit). if ((type >= DLT_FORMAT_HEX8) && (type <= DLT_FORMAT_HEX64)) { type_info |= DLT_SCOD_HEX; type_info += type; } else if ((type >= DLT_FORMAT_BIN8) && (type <= DLT_FORMAT_BIN16)) { type_info |= DLT_SCOD_BIN; type_info += type - DLT_FORMAT_BIN8 + 1; } memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t)); log->size += sizeof(uint32_t); } memcpy(log->buffer + log->size, &length, sizeof(uint16_t)); log->size += sizeof(uint16_t); if (is_verbose_mode(dlt_user.verbose_mode, log)) { if (with_var_info) { // Write length of "name" attribute. // We assume that the protocol allows zero-sized strings here (which this code will create // when the input pointer is NULL). memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t)); log->size += sizeof(uint16_t); // Write name string itself. // Must not use NULL as source pointer for memcpy. This check assures that. if (name_size != 0) { memcpy(log->buffer + log->size, name, name_size); log->size += name_size; } } } memcpy(log->buffer + log->size, data, length); log->size += length; log->args_num++; return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_raw(DltContextData *log, void *data, uint16_t length) { return dlt_user_log_write_raw_internal(log, data, length, DLT_FORMAT_DEFAULT, NULL, false); } DltReturnValue dlt_user_log_write_raw_formatted(DltContextData *log, void *data, uint16_t length, DltFormatType type) { return dlt_user_log_write_raw_internal(log, data, length, type, NULL, false); } DltReturnValue dlt_user_log_write_raw_attr(DltContextData *log, const void *data, uint16_t length, const char *name) { return dlt_user_log_write_raw_internal(log, data, length, DLT_FORMAT_DEFAULT, name, true); } DltReturnValue dlt_user_log_write_raw_formatted_attr(DltContextData *log, const void *data, uint16_t length, DltFormatType type, const char *name) { return dlt_user_log_write_raw_internal(log, data, length, type, name, true); } // Generic implementation for all "simple" types, possibly with attributes static DltReturnValue dlt_user_log_write_generic_attr(DltContextData *log, const void *datap, size_t datalen, uint32_t type_info, const VarInfo *varinfo) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } size_t needed_size = datalen; if ((log->size + needed_size) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; if (is_verbose_mode(dlt_user.verbose_mode, log)) { bool with_var_info = (varinfo != NULL); uint16_t name_size; uint16_t unit_size; needed_size += sizeof(uint32_t); // Type Info field if (with_var_info) { name_size = (varinfo->name != NULL) ? strlen(varinfo->name)+1 : 0; unit_size = (varinfo->unit != NULL) ? strlen(varinfo->unit)+1 : 0; needed_size += sizeof(uint16_t); // length of name needed_size += name_size; // the name itself if (varinfo->with_unit) { needed_size += sizeof(uint16_t); // length of unit needed_size += unit_size; // the unit itself } type_info |= DLT_TYPE_INFO_VARI; } if ((log->size + needed_size) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t)); log->size += sizeof(uint32_t); if (with_var_info) { // Write lengths of name/unit strings // We assume here that the protocol allows zero-sized strings here (which occur // when the input pointers are NULL). memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t)); log->size += sizeof(uint16_t); if (varinfo->with_unit) { memcpy(log->buffer + log->size, &unit_size, sizeof(uint16_t)); log->size += sizeof(uint16_t); } // Write name/unit strings themselves // Must not use NULL as source pointer for memcpy. if (name_size != 0) { memcpy(log->buffer + log->size, varinfo->name, name_size); log->size += name_size; } if (unit_size != 0) { memcpy(log->buffer + log->size, varinfo->unit, unit_size); log->size += unit_size; } } } memcpy(log->buffer + log->size, datap, datalen); log->size += datalen; log->args_num++; return DLT_RETURN_OK; } // Generic implementation for all "simple" types static DltReturnValue dlt_user_log_write_generic_formatted(DltContextData *log, const void *datap, size_t datalen, uint32_t type_info, DltFormatType type) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; /* Have to cast type to signed type because some compilers assume that DltFormatType is unsigned and issue a warning */ if (((int16_t)type < DLT_FORMAT_DEFAULT) || (type >= DLT_FORMAT_MAX)) { dlt_vlog(LOG_ERR, "Format type %d is outside valid range", type); return DLT_RETURN_WRONG_PARAMETER; } if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } size_t needed_size = datalen; if ((log->size + needed_size) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; if (is_verbose_mode(dlt_user.verbose_mode, log)) { needed_size += sizeof(uint32_t); // Type Info field if ((log->size + needed_size) > dlt_user.log_buf_len) return DLT_RETURN_USER_BUFFER_FULL; // Genivi extension: put formatting hints into the unused (for SINT/UINT/FLOA) SCOD field. if ((type >= DLT_FORMAT_HEX8) && (type <= DLT_FORMAT_HEX64)) type_info |= DLT_SCOD_HEX; else if ((type >= DLT_FORMAT_BIN8) && (type <= DLT_FORMAT_BIN16)) type_info |= DLT_SCOD_BIN; memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t)); log->size += sizeof(uint32_t); } memcpy(log->buffer + log->size, datap, datalen); log->size += datalen; log->args_num++; return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_float32(DltContextData *log, float32_t data) { if (sizeof(float32_t) != 4) return DLT_RETURN_ERROR; uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(float32_t), type_info, NULL); } DltReturnValue dlt_user_log_write_float64(DltContextData *log, float64_t data) { if (sizeof(float64_t) != 8) return DLT_RETURN_ERROR; uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(float64_t), type_info, NULL); } DltReturnValue dlt_user_log_write_float32_attr(DltContextData *log, float32_t data, const char *name, const char *unit) { if (sizeof(float32_t) != 4) return DLT_RETURN_ERROR; uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(float32_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_float64_attr(DltContextData *log, float64_t data, const char *name, const char *unit) { if (sizeof(float64_t) != 8) return DLT_RETURN_ERROR; uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(float64_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_uint(DltContextData *log, unsigned int data) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } switch (sizeof(unsigned int)) { case 1: { return dlt_user_log_write_uint8(log, (uint8_t)data); break; } case 2: { return dlt_user_log_write_uint16(log, (uint16_t)data); break; } case 4: { return dlt_user_log_write_uint32(log, (uint32_t)data); break; } case 8: { return dlt_user_log_write_uint64(log, (uint64_t)data); break; } default: { return DLT_RETURN_ERROR; break; } } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_uint8(DltContextData *log, uint8_t data) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, NULL); } DltReturnValue dlt_user_log_write_uint16(DltContextData *log, uint16_t data) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint16_t), type_info, NULL); } DltReturnValue dlt_user_log_write_uint32(DltContextData *log, uint32_t data) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint32_t), type_info, NULL); } DltReturnValue dlt_user_log_write_uint64(DltContextData *log, uint64_t data) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint64_t), type_info, NULL); } DltReturnValue dlt_user_log_write_uint_attr(DltContextData *log, unsigned int data, const char *name, const char *unit) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); return DLT_RETURN_ERROR; } switch (sizeof(unsigned int)) { case 1: { return dlt_user_log_write_uint8_attr(log, (uint8_t)data, name, unit); break; } case 2: { return dlt_user_log_write_uint16_attr(log, (uint16_t)data, name, unit); break; } case 4: { return dlt_user_log_write_uint32_attr(log, (uint32_t)data, name, unit); break; } case 8: { return dlt_user_log_write_uint64_attr(log, (uint64_t)data, name, unit); break; } default: { return DLT_RETURN_ERROR; break; } } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_uint8_attr(DltContextData *log, uint8_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_uint16_attr(DltContextData *log, uint16_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint16_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_uint32_attr(DltContextData *log, uint32_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint32_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_uint64_attr(DltContextData *log, uint64_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint64_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_uint8_formatted(DltContextData *log, uint8_t data, DltFormatType type) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT; return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint8_t), type_info, type); } DltReturnValue dlt_user_log_write_uint16_formatted(DltContextData *log, uint16_t data, DltFormatType type) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT; return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint16_t), type_info, type); } DltReturnValue dlt_user_log_write_uint32_formatted(DltContextData *log, uint32_t data, DltFormatType type) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT; return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint32_t), type_info, type); } DltReturnValue dlt_user_log_write_uint64_formatted(DltContextData *log, uint64_t data, DltFormatType type) { uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT; return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint64_t), type_info, type); } DltReturnValue dlt_user_log_write_ptr(DltContextData *log, void *data) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s user_initialised false\n", __FUNCTION__); return DLT_RETURN_ERROR; } switch (sizeof(void *)) { case 4: return dlt_user_log_write_uint32_formatted(log, (uintptr_t) data, DLT_FORMAT_HEX32); break; case 8: return dlt_user_log_write_uint64_formatted(log, (uintptr_t) data, DLT_FORMAT_HEX64); break; default: ; /* skip */ } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_int(DltContextData *log, int data) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } switch (sizeof(int)) { case 1: { return dlt_user_log_write_int8(log, (int8_t)data); break; } case 2: { return dlt_user_log_write_int16(log, (int16_t)data); break; } case 4: { return dlt_user_log_write_int32(log, (int32_t)data); break; } case 8: { return dlt_user_log_write_int64(log, (int64_t)data); break; } default: { return DLT_RETURN_ERROR; break; } } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_int8(DltContextData *log, int8_t data) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(int8_t), type_info, NULL); } DltReturnValue dlt_user_log_write_int16(DltContextData *log, int16_t data) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(int16_t), type_info, NULL); } DltReturnValue dlt_user_log_write_int32(DltContextData *log, int32_t data) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(int32_t), type_info, NULL); } DltReturnValue dlt_user_log_write_int64(DltContextData *log, int64_t data) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(int64_t), type_info, NULL); } DltReturnValue dlt_user_log_write_int_attr(DltContextData *log, int data, const char *name, const char *unit) { if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); return DLT_RETURN_ERROR; } switch (sizeof(int)) { case 1: { return dlt_user_log_write_int8_attr(log, (int8_t)data, name, unit); break; } case 2: { return dlt_user_log_write_int16_attr(log, (int16_t)data, name, unit); break; } case 4: { return dlt_user_log_write_int32_attr(log, (int32_t)data, name, unit); break; } case 8: { return dlt_user_log_write_int64_attr(log, (int64_t)data, name, unit); break; } default: { return DLT_RETURN_ERROR; break; } } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_int8_attr(DltContextData *log, int8_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(int8_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_int16_attr(DltContextData *log, int16_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(int16_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_int32_attr(DltContextData *log, int32_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(int32_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_int64_attr(DltContextData *log, int64_t data, const char *name, const char *unit) { uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT; const VarInfo var_info = { name, unit, true }; return dlt_user_log_write_generic_attr(log, &data, sizeof(int64_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_bool(DltContextData *log, uint8_t data) { uint32_t type_info = DLT_TYPE_INFO_BOOL | DLT_TYLE_8BIT; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, NULL); } DltReturnValue dlt_user_log_write_bool_attr(DltContextData *log, uint8_t data, const char *name) { uint32_t type_info = DLT_TYPE_INFO_BOOL | DLT_TYLE_8BIT; const VarInfo var_info = { name, NULL, false }; return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, &var_info); } DltReturnValue dlt_user_log_write_string(DltContextData *log, const char *text) { return dlt_user_log_write_string_utils_attr(log, text, ASCII_STRING, NULL, false); } DltReturnValue dlt_user_log_write_string_attr(DltContextData *log, const char *text, const char *name) { return dlt_user_log_write_string_utils_attr(log, text, ASCII_STRING, name, true); } DltReturnValue dlt_user_log_write_sized_string(DltContextData *log, const char *text, uint16_t length) { return dlt_user_log_write_sized_string_utils_attr(log, text, length, ASCII_STRING, NULL, false); } DltReturnValue dlt_user_log_write_sized_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name) { return dlt_user_log_write_sized_string_utils_attr(log, text, length, ASCII_STRING, name, true); } DltReturnValue dlt_user_log_write_constant_string(DltContextData *log, const char *text) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_string(log, text) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_constant_string_attr(DltContextData *log, const char *text, const char *name) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_string_attr(log, text, name) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_sized_constant_string(DltContextData *log, const char *text, uint16_t length) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_string(log, text, length) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_sized_constant_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_string_attr(log, text, length, name) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_utf8_string(DltContextData *log, const char *text) { return dlt_user_log_write_string_utils_attr(log, text, UTF8_STRING, NULL, false); } DltReturnValue dlt_user_log_write_utf8_string_attr(DltContextData *log, const char *text, const char *name) { return dlt_user_log_write_string_utils_attr(log, text, UTF8_STRING, name, true); } DltReturnValue dlt_user_log_write_sized_utf8_string(DltContextData *log, const char *text, uint16_t length) { return dlt_user_log_write_sized_string_utils_attr(log, text, length, UTF8_STRING, NULL, false); } DltReturnValue dlt_user_log_write_sized_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name) { return dlt_user_log_write_sized_string_utils_attr(log, text, length, UTF8_STRING, name, true); } DltReturnValue dlt_user_log_write_constant_utf8_string(DltContextData *log, const char *text) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_utf8_string(log, text) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_constant_utf8_string_attr(DltContextData *log, const char *text, const char *name) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_utf8_string_attr(log, text, name) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_sized_constant_utf8_string(DltContextData *log, const char *text, uint16_t length) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_utf8_string(log, text, length) : DLT_RETURN_OK; } DltReturnValue dlt_user_log_write_sized_constant_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name) { /* Send parameter only in verbose mode */ return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_utf8_string_attr(log, text, length, name) : DLT_RETURN_OK; } static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, size_t length, const enum StringType type, const char *name, bool with_var_info) { if ((log == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } const uint16_t name_size = (name != NULL) ? strlen(name)+1 : 0; size_t arg_size = (size_t) (length + 1); size_t new_log_size = log->size + arg_size + sizeof(uint16_t); uint32_t type_info = 0; if (is_verbose_mode(dlt_user.verbose_mode, log)) { new_log_size += sizeof(uint32_t); if (with_var_info) { new_log_size += sizeof(uint16_t); // length of "name" attribute new_log_size += name_size; // the "name" attribute itself type_info |= DLT_TYPE_INFO_VARI; } } size_t str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; size_t max_payload_str_msg; DltReturnValue ret = DLT_RETURN_OK; /* Check log size condition */ if (new_log_size > dlt_user.log_buf_len) { ret = DLT_RETURN_USER_BUFFER_FULL; /* Re-calculate arg_size */ arg_size = (size_t) (dlt_user.log_buf_len - log->size - sizeof(uint16_t)); size_t min_payload_str_truncate_msg = log->size + str_truncate_message_length + sizeof(uint16_t); if (is_verbose_mode(dlt_user.verbose_mode, log)) { min_payload_str_truncate_msg += sizeof(uint32_t); arg_size -= (size_t) sizeof(uint32_t); if (with_var_info) { min_payload_str_truncate_msg += sizeof(uint16_t) + name_size; arg_size -= sizeof(uint16_t) + name_size; } } /* Return when dlt_user.log_buf_len does not have enough space for min_payload_str_truncate_msg */ if (min_payload_str_truncate_msg > dlt_user.log_buf_len) { dlt_vlog(LOG_WARNING, "%s not enough minimum space to store data\n", __FUNCTION__); return ret; } /* Calculate the maximum size of string will be copied after truncate */ max_payload_str_msg = dlt_user.log_buf_len - min_payload_str_truncate_msg; if (type == UTF8_STRING) { /** * Adjust the lengh to truncate one utf8 character corectly * refer: https://en.wikipedia.org/wiki/UTF-8 * one utf8 character will have maximum 4 bytes then maximum bytes will be truncate additional is 3 */ const char *tmp = (text + max_payload_str_msg - 3); uint16_t reduce_size = 0; if (tmp[2] & 0x80) { /* Is the last byte of truncated text is the first byte in multi-byte sequence (utf8 2 bytes) */ if (tmp[2] & 0x40) reduce_size = 1; /* Is the next to last byte of truncated text is the first byte in multi-byte sequence (utf8 3 bytes) */ else if ((tmp[1] & 0xe0) == 0xe0) reduce_size = 2; /* utf8 4 bytes */ else if ((tmp[0] & 0xf0) == 0xf0) reduce_size = 3; } max_payload_str_msg -= reduce_size; arg_size -= (size_t) reduce_size; } } if (is_verbose_mode(dlt_user.verbose_mode, log)) { switch (type) { case ASCII_STRING: type_info |= DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII; break; case UTF8_STRING: type_info |= DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8; break; default: /* Do nothing */ break; } memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t)); log->size += sizeof(uint32_t); } memcpy(log->buffer + log->size, &arg_size, sizeof(uint16_t)); log->size += sizeof(uint16_t); if (is_verbose_mode(dlt_user.verbose_mode, log)) { if (with_var_info) { // Write length of "name" attribute. // We assume that the protocol allows zero-sized strings here (which this code will create // when the input pointer is NULL). memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t)); log->size += sizeof(uint16_t); // Write name string itself. // Must not use NULL as source pointer for memcpy. This check assures that. if (name_size != 0) { memcpy(log->buffer + log->size, name, name_size); log->size += name_size; } } } switch (ret) { case DLT_RETURN_OK: { /* Whole string will be copied */ memcpy(log->buffer + log->size, text, length); /* The input string might not be null-terminated, so we're doing that by ourselves */ log->buffer[log->size + length] = '\0'; log->size += arg_size; break; } case DLT_RETURN_USER_BUFFER_FULL: { /* Only copy partial string */ memcpy(log->buffer + log->size, text, max_payload_str_msg); log->size += max_payload_str_msg; /* Append string truncate the input string */ memcpy(log->buffer + log->size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); log->size += str_truncate_message_length; break; } default: { /* Do nothing */ break; } } log->args_num++; return ret; } static DltReturnValue dlt_user_log_write_string_utils_attr(DltContextData *log, const char *text, const enum StringType type, const char *name, bool with_var_info) { if ((log == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; size_t length = strlen(text); return dlt_user_log_write_sized_string_utils_attr(log, text, length, type, name, with_var_info); } DltReturnValue dlt_register_injection_callback_with_id(DltContext *handle, uint32_t service_id, dlt_injection_callback_id dlt_injection_cbk, void *priv) { DltContextData log; uint32_t i, j, k; int found = 0; DltUserInjectionCallback *old; if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (service_id < DLT_USER_INJECTION_MIN) return DLT_RETURN_WRONG_PARAMETER; /* This function doesn't make sense storing to local file is choosen; * so terminate this function */ if (dlt_user.dlt_is_file) return DLT_RETURN_OK; DLT_SEM_LOCK(); if (dlt_user.dlt_ll_ts == NULL) { DLT_SEM_FREE(); return DLT_RETURN_OK; } /* Insert callback in corresponding table */ i = (uint32_t) handle->log_level_pos; /* Insert each service_id only once */ for (k = 0; k < dlt_user.dlt_ll_ts[i].nrcallbacks; k++) if ((dlt_user.dlt_ll_ts[i].injection_table) && (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id)) { found = 1; break; } if (found) { j = k; } else { j = dlt_user.dlt_ll_ts[i].nrcallbacks; /* Allocate or expand injection table */ if (dlt_user.dlt_ll_ts[i].injection_table == NULL) { dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback *)malloc(sizeof(DltUserInjectionCallback)); if (dlt_user.dlt_ll_ts[i].injection_table == NULL) { DLT_SEM_FREE(); return DLT_RETURN_ERROR; } } else { old = dlt_user.dlt_ll_ts[i].injection_table; dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback *)malloc( sizeof(DltUserInjectionCallback) * (j + 1)); if (dlt_user.dlt_ll_ts[i].injection_table == NULL) { dlt_user.dlt_ll_ts[i].injection_table = old; DLT_SEM_FREE(); return DLT_RETURN_ERROR; } memcpy(dlt_user.dlt_ll_ts[i].injection_table, old, sizeof(DltUserInjectionCallback) * j); free(old); } dlt_user.dlt_ll_ts[i].nrcallbacks++; } /* Store service_id and corresponding function pointer for callback function */ dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id; if (priv == NULL) { dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = (dlt_injection_callback)(void*)dlt_injection_cbk; dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback_with_id = NULL; dlt_user.dlt_ll_ts[i].injection_table[j].data = NULL; } else { dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = NULL; dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback_with_id = dlt_injection_cbk; dlt_user.dlt_ll_ts[i].injection_table[j].data = priv; } DLT_SEM_FREE(); return DLT_RETURN_OK; } DltReturnValue dlt_register_injection_callback(DltContext *handle, uint32_t service_id, int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length)) { return dlt_register_injection_callback_with_id(handle, service_id, (dlt_injection_callback_id)(void*)dlt_injection_callback, NULL); } DltReturnValue dlt_register_log_level_changed_callback(DltContext *handle, void (*dlt_log_level_changed_callback)( char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status)) { DltContextData log; uint32_t i; if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* This function doesn't make sense storing to local file is choosen; * so terminate this function */ if (dlt_user.dlt_is_file) return DLT_RETURN_OK; DLT_SEM_LOCK(); if (dlt_user.dlt_ll_ts == NULL) { DLT_SEM_FREE(); return DLT_RETURN_OK; } /* Insert callback in corresponding table */ i = (uint32_t) handle->log_level_pos; /* Store new callback function */ dlt_user.dlt_ll_ts[i].log_level_changed_callback = dlt_log_level_changed_callback; DLT_SEM_FREE(); return DLT_RETURN_OK; } /** * NW Trace related */ #ifdef DLT_NETWORK_TRACE_ENABLE int check_buffer(void) { int total_size, used_size; dlt_user_check_buffer(&total_size, &used_size); return (total_size - used_size < total_size / 2) ? -1 : 1; } /** * Send the start of a segment chain. * Returns DLT_RETURN_ERROR on failure */ DltReturnValue dlt_user_trace_network_segmented_start(uint32_t *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len) { DltContextData log = { 0 }; struct timeval tv; int ret = DLT_RETURN_ERROR; /* check null pointer */ if (id == NULL) return DLT_RETURN_WRONG_PARAMETER; if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) { dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type); return DLT_RETURN_WRONG_PARAMETER; } if (dlt_user.dlt_ll_ts == NULL) return DLT_RETURN_ERROR; if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) { /* initialize values */ if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (log.buffer == NULL) { log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); if (log.buffer == NULL) { dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); return DLT_RETURN_ERROR; } } log.args_num = 0; log.trace_status = nw_trace_type; log.size = 0; gettimeofday(&tv, NULL); *id = (uint32_t) tv.tv_usec; /* Write identifier */ if (dlt_user_log_write_string(&log, DLT_TRACE_NW_START) < 0) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write stream handle */ if (dlt_user_log_write_uint32(&log, *id) < 0) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write header */ if (dlt_user_log_write_raw(&log, header, header_len) < 0) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write size of payload */ if (dlt_user_log_write_uint32(&log, payload_len) < 0) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write expected segment count */ uint16_t segment_count = (uint16_t) (payload_len / DLT_MAX_TRACE_SEGMENT_SIZE + 1); /* If segments align perfectly with segment size, avoid sending empty segment */ if ((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0) segment_count--; if (dlt_user_log_write_uint16(&log, segment_count) < 0) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write length of one segment */ if (dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Send log */ ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE); dlt_user_free_buffer(&(log.buffer)); return ret; } return DLT_RETURN_OK; } DltReturnValue dlt_user_trace_network_segmented_segment(uint32_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload) { int ret = DLT_RETURN_ERROR; struct timespec ts; if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) { dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type); return DLT_RETURN_WRONG_PARAMETER; } while (check_buffer() < 0) { /* Wait 50ms */ ts.tv_sec = 0; ts.tv_nsec = 1000000 * 50; nanosleep(&ts, NULL); dlt_user_log_resend_buffer(); } if (dlt_user.dlt_ll_ts == NULL) return DLT_RETURN_ERROR; if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) { DltContextData log = { 0 }; if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* initialize values */ if (log.buffer == NULL) { log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); if (log.buffer == NULL) { dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); return DLT_RETURN_ERROR; } } log.args_num = 0; log.trace_status = nw_trace_type; log.size = 0; /* Write identifier */ if (dlt_user_log_write_string(&log, DLT_TRACE_NW_SEGMENT) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write stream handle */ if (dlt_user_log_write_uint32(&log, id) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write segment sequence number */ if (dlt_user_log_write_uint16(&log, (uint16_t) sequence) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write data */ if (dlt_user_log_write_raw(&log, payload, payload_len) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE); /* Send log */ dlt_user_free_buffer(&(log.buffer)); return ret; } /* Allow other threads to log between chunks */ sched_yield(); return DLT_RETURN_OK; } DltReturnValue dlt_user_trace_network_segmented_end(uint32_t id, DltContext *handle, DltNetworkTraceType nw_trace_type) { DltContextData log = { 0 }; int ret = DLT_RETURN_ERROR; if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) { dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type); return DLT_RETURN_WRONG_PARAMETER; } if (dlt_user.dlt_ll_ts == NULL) return DLT_RETURN_ERROR; if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) { /* initialize values */ if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* initialize values */ if (log.buffer == NULL) { log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); if (log.buffer == NULL) { dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); return DLT_RETURN_ERROR; } } log.args_num = 0; log.trace_status = nw_trace_type; log.size = 0; /* Write identifier */ if (dlt_user_log_write_string(&log, DLT_TRACE_NW_END) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write stream handle */ if (dlt_user_log_write_uint32(&log, id) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE); /* Send log */ dlt_user_free_buffer(&(log.buffer)); return ret; } return DLT_RETURN_OK; } void dlt_user_trace_network_segmented_thread(void *unused) { /* Unused on purpose. */ (void)unused; #ifdef DLT_USE_PTHREAD_SETNAME_NP if (pthread_setname_np(dlt_user.dlt_segmented_nwt_handle, "dlt_segmented")) dlt_log(LOG_WARNING, "Failed to rename segmented thread!\n"); #elif linux if (prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0) < 0) dlt_log(LOG_WARNING, "Failed to rename segmented thread!\n"); #endif pthread_cleanup_push(dlt_user_cleanup_handler, NULL); s_segmented_data *data; while (1) { /* Wait until message queue is initialized */ dlt_lock_mutex(&mq_mutex); while (dlt_user.dlt_segmented_queue_read_handle < 0) { pthread_cond_wait(&mq_init_condition, &mq_mutex); } dlt_unlock_mutex(&mq_mutex); ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data, sizeof(s_segmented_data *), NULL); if (read < 0) { if (errno != EINTR) { struct timespec req; long sec = (DLT_USER_MQ_ERROR_RETRY_INTERVAL / 1000000); dlt_vlog(LOG_WARNING, "NWTSegmented: Error while reading queue: %s\n", strerror(errno)); req.tv_sec = sec; req.tv_nsec = (DLT_USER_MQ_ERROR_RETRY_INTERVAL - sec * 1000000) * 1000; nanosleep(&req, NULL); } continue; } if (read != sizeof(s_segmented_data *)) { /* This case will not happen. */ /* When this thread is interrupted by signal, mq_receive() will not return */ /* partial read length and will return -1. And also no data is removed from mq. */ dlt_vlog(LOG_WARNING, "NWTSegmented: Could not read data fully from queue: %zd\n", read); continue; } dlt_user_trace_network_segmented_thread_segmenter(data); /* Send the end message */ DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type); if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) dlt_log(LOG_WARNING, "NWTSegmented: Could not send end segment.\n"); /* Free resources */ free(data->header); free(data->payload); free(data); } pthread_cleanup_pop(1); } void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data) { /* Segment the data and send the chunks */ void *ptr = NULL; uint32_t offset = 0; uint16_t sequence = 0; do { uint16_t len = 0; if (offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len) len = (uint16_t) (data->payload_len - offset); else len = DLT_MAX_TRACE_SEGMENT_SIZE; /* If payload size aligns perfectly with segment size, avoid sending empty segment */ if (len == 0) break; ptr = data->payload + offset; DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr); if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) { dlt_log(LOG_ERR, "NWTSegmented: Could not send segment. Aborting.\n"); break; /* loop */ } offset += len; } while (ptr < data->payload + data->payload_len); } DltReturnValue dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload) { /* forbid dlt usage in child after fork */ if (g_dlt_is_child) return DLT_RETURN_ERROR; /* Send as normal trace if possible */ if (header_len + payload_len + sizeof(uint16_t) < dlt_user.log_buf_len) return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload); /* Allocate Memory */ s_segmented_data *thread_data = malloc(sizeof(s_segmented_data)); if (thread_data == NULL) return DLT_RETURN_ERROR; thread_data->header = malloc(header_len); if (thread_data->header == NULL) { free(thread_data); return DLT_RETURN_ERROR; } thread_data->payload = malloc(payload_len); if (thread_data->payload == NULL) { free(thread_data->header); free(thread_data); return DLT_RETURN_ERROR; } /* Copy data */ thread_data->handle = handle; thread_data->nw_trace_type = nw_trace_type; thread_data->header_len = header_len; memcpy(thread_data->header, header, header_len); thread_data->payload_len = payload_len; memcpy(thread_data->payload, payload, payload_len); /* Send start message */ DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id), thread_data->handle, thread_data->nw_trace_type, (uint16_t) thread_data->header_len, thread_data->header, (uint16_t) thread_data->payload_len); if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) { dlt_log(LOG_ERR, "NWTSegmented: Could not send start segment. Aborting.\n"); free(thread_data->header); free(thread_data->payload); free(thread_data); return DLT_RETURN_ERROR; } /* Open queue if it is not open */ if (dlt_init_message_queue() < 0) { dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n"); free(thread_data->header); free(thread_data->payload); free(thread_data); return DLT_RETURN_ERROR; } /* Add to queue */ if (mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0) { if (errno == EAGAIN) dlt_log(LOG_WARNING, "NWTSegmented: Queue full. Message discarded.\n"); free(thread_data->header); free(thread_data->payload); free(thread_data); dlt_vnlog(LOG_WARNING, 256, "NWTSegmented: Could not write into queue: %s \n", strerror(errno)); return DLT_RETURN_ERROR; } /*thread_data will be freed by the receiver function */ /*coverity[leaked_storage] */ return DLT_RETURN_OK; } DltReturnValue dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload) { return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1); } DltReturnValue dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate) { int ret = DLT_RETURN_ERROR; DltContextData log = { 0 }; if ((payload == NULL) && (payload_len > 0)) return DLT_RETURN_WRONG_PARAMETER; if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) { dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type); return DLT_RETURN_WRONG_PARAMETER; } if (dlt_user.dlt_ll_ts == NULL) return DLT_RETURN_ERROR; if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) { if ((dlt_user_log_init(handle, &log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL)) return DLT_RETURN_ERROR; /* initialize values */ if (log.buffer == NULL) { log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); if (log.buffer == NULL) { dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); return DLT_RETURN_ERROR; } } log.args_num = 0; log.trace_status = nw_trace_type; log.size = 0; if (header == NULL) header_len = 0; /* If truncation is allowed, check if we must do it */ if ((allow_truncate > 0) && ((header_len + payload_len + sizeof(uint16_t)) > dlt_user.log_buf_len)) { /* Identify as truncated */ if (dlt_user_log_write_string(&log, DLT_TRACE_NW_TRUNCATED) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write header and its length */ if (dlt_user_log_write_raw(&log, header, header_len) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /* Write original size of payload */ if (dlt_user_log_write_uint32(&log, payload_len) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } /** * Calculate maximum available space in sending buffer after headers. */ uint16_t truncated_payload_len = (uint16_t) (dlt_user.log_buf_len - log.size - sizeof(uint16_t) - sizeof(uint32_t)); /* Write truncated payload */ if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } } else { /* Truncation not allowed or data short enough */ /* Write header and its length */ if (dlt_user_log_write_raw(&log, header, header_len) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } if (payload == NULL) payload_len = 0; /* Write payload and its length */ if (dlt_user_log_write_raw(&log, payload, payload_len) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return DLT_RETURN_ERROR; } } ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE); dlt_user_free_buffer(&(log.buffer)); /* Send log */ return ret; } return DLT_RETURN_OK; } #else /* DLT_NETWORK_TRACE_ENABLE not set */ DltReturnValue dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload) { /** * vsomeip uses the DLT_TRACE_NETWORK_SEGMENTED macro that calls this function. * It's not possible to rewrite this macro directly to a no-op, * because the macro is used on vsomeip side and there our defines are not set. * Add an empty function to the dlt-lib to avoid a broken build. */ (void)handle; (void)nw_trace_type; (void)header_len; (void)header; (void)payload_len; (void)payload; return DLT_RETURN_LOGGING_DISABLED; } DltReturnValue dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate) { /** * vsomeip uses the DLT_TRACE_NETWORK_TRUNCATED macro that calls this function. * It's not possible to rewrite this macro directly to a no-op, * because the macro is used on vsomeip side and there our defines are not set. * Add an empty function to the dlt-lib to avoid a broken build. */ (void)handle; (void)nw_trace_type; (void)header_len; (void)header; (void)payload_len; (void)payload; (void)allow_truncate; return DLT_RETURN_LOGGING_DISABLED; } #endif /* DLT_NETWORK_TRACE_ENABLE */ DltReturnValue dlt_log_string(DltContext *handle, DltLogLevelType loglevel, const char *text) { if (!is_verbose_mode(dlt_user.verbose_mode, NULL)) return DLT_RETURN_ERROR; if ((handle == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; DltReturnValue ret = DLT_RETURN_OK; DltContextData log; if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) { ret = dlt_user_log_write_string(&log, text); if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; } return ret; } DltReturnValue dlt_log_string_int(DltContext *handle, DltLogLevelType loglevel, const char *text, int data) { if (!is_verbose_mode(dlt_user.verbose_mode, NULL)) return DLT_RETURN_ERROR; if ((handle == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; DltReturnValue ret = DLT_RETURN_OK; DltContextData log; if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) { ret = dlt_user_log_write_string(&log, text); dlt_user_log_write_int(&log, data); if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; } return ret; } DltReturnValue dlt_log_string_uint(DltContext *handle, DltLogLevelType loglevel, const char *text, unsigned int data) { if (!is_verbose_mode(dlt_user.verbose_mode, NULL)) return DLT_RETURN_ERROR; if ((handle == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; DltReturnValue ret = DLT_RETURN_OK; DltContextData log; if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) { ret = dlt_user_log_write_string(&log, text); dlt_user_log_write_uint(&log, data); if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK) ret = DLT_RETURN_ERROR; } return ret; } DltReturnValue dlt_log_int(DltContext *handle, DltLogLevelType loglevel, int data) { if (!is_verbose_mode(dlt_user.verbose_mode, NULL)) return DLT_RETURN_ERROR; if (handle == NULL) return DLT_RETURN_ERROR; DltContextData log; if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) { dlt_user_log_write_int(&log, data); if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_log_uint(DltContext *handle, DltLogLevelType loglevel, unsigned int data) { if (!is_verbose_mode(dlt_user.verbose_mode, NULL)) return DLT_RETURN_ERROR; if (handle == NULL) return DLT_RETURN_WRONG_PARAMETER; DltContextData log; if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) { dlt_user_log_write_uint(&log, data); if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_log_raw(DltContext *handle, DltLogLevelType loglevel, void *data, uint16_t length) { if (!is_verbose_mode(dlt_user.verbose_mode, NULL)) return DLT_RETURN_ERROR; if (handle == NULL) return DLT_RETURN_WRONG_PARAMETER; DltContextData log; DltReturnValue ret = DLT_RETURN_OK; if (dlt_user_log_write_start(handle, &log, loglevel) > 0) { if ((ret = dlt_user_log_write_raw(&log, data, length)) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); return ret; } if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK) return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_log_marker() { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } return dlt_user_log_send_marker(); } DltReturnValue dlt_verbose_mode(void) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } /* Switch to verbose mode */ dlt_user.verbose_mode = 1; return DLT_RETURN_OK; } DltReturnValue dlt_nonverbose_mode(void) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } /* Switch to non-verbose mode */ dlt_user.verbose_mode = 0; return DLT_RETURN_OK; } DltReturnValue dlt_use_extended_header_for_non_verbose(int8_t use_extended_header_for_non_verbose) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } /* Set use_extended_header_for_non_verbose */ dlt_user.use_extended_header_for_non_verbose = use_extended_header_for_non_verbose; return DLT_RETURN_OK; } DltReturnValue dlt_with_session_id(int8_t with_session_id) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } /* Set use_extended_header_for_non_verbose */ dlt_user.with_session_id = with_session_id; return DLT_RETURN_OK; } DltReturnValue dlt_with_timestamp(int8_t with_timestamp) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } /* Set with_timestamp */ dlt_user.with_timestamp = with_timestamp; return DLT_RETURN_OK; } DltReturnValue dlt_with_ecu_id(int8_t with_ecu_id) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } /* Set with_timestamp */ dlt_user.with_ecu_id = with_ecu_id; return DLT_RETURN_OK; } DltReturnValue dlt_enable_local_print(void) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } dlt_user.enable_local_print = 1; return DLT_RETURN_OK; } DltReturnValue dlt_disable_local_print(void) { if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; } } dlt_user.enable_local_print = 0; return DLT_RETURN_OK; } /* Cleanup on thread cancellation, thread may hold lock release it here */ static void dlt_user_cleanup_handler(void *arg) { DLT_UNUSED(arg); /* Satisfy compiler */ #ifdef DLT_NETWORK_TRACE_ENABLE /* unlock the message queue */ dlt_unlock_mutex(&mq_mutex); #endif /* unlock DLT (dlt_mutex) */ DLT_SEM_FREE(); } void dlt_user_housekeeperthread_function(void *ptr) { struct timespec ts; bool in_loop = true; int signal_status = 0; atomic_bool* dlt_housekeeper_running = (atomic_bool*)ptr; #ifdef __ANDROID_API__ sigset_t set; sigset_t pset; /* * bionic is not supporting pthread_cancel so * use SIGUSR1 to kill thread properly. */ sigemptyset(&set); sigaddset(&set, SIGUSR1); if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { dlt_vlog(LOG_ERR, "Failed to block signal with error [%s]\n", strerror(errno)); in_loop = false; } #endif #ifdef DLT_USE_PTHREAD_SETNAME_NP if (pthread_setname_np(dlt_housekeeperthread_handle, "dlt_housekeeper")) dlt_log(LOG_WARNING, "Failed to rename housekeeper thread!\n"); #elif linux if (prctl(PR_SET_NAME, "dlt_housekeeper", 0, 0, 0) < 0) dlt_log(LOG_WARNING, "Failed to rename housekeeper thread!\n"); #endif pthread_cleanup_push(dlt_user_cleanup_handler, NULL); // signal dlt thread to be running *dlt_housekeeper_running = true; signal_status = pthread_cond_signal(&dlt_housekeeper_running_cond); if (signal_status != 0) { dlt_log(LOG_CRIT, "Housekeeper thread failed to signal running state\n"); } while (in_loop) { /* Check for new messages from DLT daemon */ if (!dlt_user.disable_injection_msg) if (dlt_user_log_check_user_message() < DLT_RETURN_OK) /* Critical error */ dlt_log(LOG_CRIT, "Housekeeper thread encountered error condition\n"); /* Reattach to daemon if neccesary */ dlt_user_log_reattach_to_daemon(); /* flush buffer to DLT daemon if possible */ if (dlt_user.dlt_log_handle != DLT_FD_INIT) dlt_user_log_resend_buffer(); #ifdef __ANDROID_API__ if (sigpending(&pset)) { dlt_vlog(LOG_ERR, "sigpending failed with error [%s]!\n", strerror(errno)); break; } if (sigismember(&pset, SIGUSR1)) { dlt_log(LOG_NOTICE, "Received SIGUSR1! Stop thread\n"); break; } #endif /* delay */ ts.tv_sec = 0; ts.tv_nsec = DLT_USER_RECEIVE_NDELAY; nanosleep(&ts, NULL); } pthread_cleanup_pop(1); } /* Private functions of user library */ DltReturnValue dlt_user_log_init(DltContext *handle, DltContextData *log) { int ret = DLT_RETURN_OK; if ((handle == NULL) || (log == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (!DLT_USER_INITALIZED) { ret = dlt_init(); if (ret < DLT_RETURN_OK) { if (ret != DLT_RETURN_LOGGING_DISABLED) dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return ret; } } log->handle = handle; log->buffer = NULL; return ret; } DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) { DltMessage msg; DltUserHeader userheader; int32_t len; DltReturnValue ret = DLT_RETURN_OK; if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } if ((log == NULL) || (log->handle == NULL) || (log->handle->contextID[0] == '\0') || (mtype < DLT_TYPE_LOG) || (mtype > DLT_TYPE_CONTROL) ) return DLT_RETURN_WRONG_PARAMETER; /* also for Trace messages */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; msg.storageheader = (DltStorageHeader *)msg.headerbuffer; if (dlt_set_storageheader(msg.storageheader, dlt_user.ecuID) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); msg.standardheader->htyp = DLT_HTYP_PROTOCOL_VERSION1; /* send ecu id */ if (dlt_user.with_ecu_id) msg.standardheader->htyp |= DLT_HTYP_WEID; /* send timestamp */ if (dlt_user.with_timestamp) msg.standardheader->htyp |= DLT_HTYP_WTMS; /* send session id */ if (dlt_user.with_session_id) { msg.standardheader->htyp |= DLT_HTYP_WSID; msg.headerextra.seid = (uint32_t) getpid(); } if (is_verbose_mode(dlt_user.verbose_mode, log)) /* In verbose mode, send extended header */ msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH); else /* In non-verbose, send extended header if desired */ if (dlt_user.use_extended_header_for_non_verbose) msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH); #if (BYTE_ORDER == BIG_ENDIAN) msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF); #endif msg.standardheader->mcnt = log->handle->mcnt++; /* Set header extra parameters */ dlt_set_id(msg.headerextra.ecu, dlt_user.ecuID); /*msg.headerextra.seid = 0; */ if (log->use_timestamp == DLT_AUTO_TIMESTAMP) { msg.headerextra.tmsp = dlt_uptime(); } else { msg.headerextra.tmsp = log->user_timestamp; } if (dlt_message_set_extraparameters(&msg, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; /* Fill out extended header, if extended header should be provided */ if (DLT_IS_HTYP_UEH(msg.standardheader->htyp)) { /* with extended header */ msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); switch (mtype) { case DLT_TYPE_LOG: { msg.extendedheader->msin = (uint8_t) (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN)); break; } case DLT_TYPE_NW_TRACE: { msg.extendedheader->msin = (uint8_t) (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN)); break; } default: { /* This case should not occur */ return DLT_RETURN_ERROR; break; } } /* If in verbose mode, set flag in header for verbose mode */ if (is_verbose_mode(dlt_user.verbose_mode, log)) msg.extendedheader->msin |= DLT_MSIN_VERB; msg.extendedheader->noar = (uint8_t) log->args_num; /* number of arguments */ dlt_set_id(msg.extendedheader->apid, dlt_user.appID); /* application id */ dlt_set_id(msg.extendedheader->ctid, log->handle->contextID); /* context id */ msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); } else { /* without extended header */ msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE( msg.standardheader->htyp)); } len = (int32_t) (msg.headersize - sizeof(DltStorageHeader) + log->size); if (len > UINT16_MAX) { dlt_log(LOG_WARNING, "Huge message discarded!\n"); return DLT_RETURN_ERROR; } msg.standardheader->len = DLT_HTOBE_16(len); /* print to std out, if enabled */ if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) && (dlt_user.local_print_mode != DLT_PM_AUTOMATIC)) { if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON)) if (dlt_user_print_msg(&msg, log) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } if (dlt_user.dlt_is_file) { if (dlt_user_file_reach_max) { return DLT_RETURN_FILESZERR; } else { /* Get file size */ struct stat st; fstat(dlt_user.dlt_log_handle, &st); dlt_vlog(LOG_DEBUG, "%s: Current file size=[%jd]\n", __func__, st.st_size); /* Check filesize */ /* Return error if the file size has reached to maximum */ unsigned int msg_size = st.st_size + (unsigned int) msg.headersize + (unsigned int) log->size; if (msg_size > dlt_user.filesize_max) { dlt_user_file_reach_max = true; dlt_vlog(LOG_ERR, "%s: File size (%jd bytes) reached to defined maximum size (%d bytes)\n", __func__, st.st_size, dlt_user.filesize_max); return DLT_RETURN_FILESZERR; } else { /* log to file */ ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size); return ret; } } } else { if (dlt_user.overflow_counter) { if (dlt_user_log_send_overflow() == DLT_RETURN_OK) { dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "%u messages discarded!\n", dlt_user.overflow_counter); dlt_user.overflow_counter = 0; } } /* try to resent old data first */ ret = DLT_RETURN_OK; if ((dlt_user.dlt_log_handle != -1) && (dlt_user.appID[0] != '\0')) ret = dlt_user_log_resend_buffer(); if ((ret == DLT_RETURN_OK) && (dlt_user.appID[0] != '\0')) { /* resend ok or nothing to resent */ #ifdef DLT_SHM_ENABLE if (dlt_user.dlt_log_handle != -1) dlt_shm_push(&dlt_user.dlt_shm, msg.headerbuffer + sizeof(DltStorageHeader), msg.headersize - sizeof(DltStorageHeader), log->buffer, log->size, 0, 0); ret = dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0, 0, 0); #else # ifdef DLT_TEST_ENABLE if (dlt_user.corrupt_user_header) { userheader.pattern[0] = (char) 0xff; userheader.pattern[1] = (char) 0xff; userheader.pattern[2] = (char) 0xff; userheader.pattern[3] = (char) 0xff; } if (dlt_user.corrupt_message_size) msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size); # endif ret = dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), msg.headerbuffer + sizeof(DltStorageHeader), msg.headersize - sizeof(DltStorageHeader), log->buffer, log->size); #endif } DltReturnValue process_error_ret = DLT_RETURN_OK; /* store message in ringbuffer, if an error has occured */ if ((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0')) process_error_ret = dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), msg.headerbuffer + sizeof(DltStorageHeader), msg.headersize - sizeof(DltStorageHeader), log->buffer, log->size); if (process_error_ret == DLT_RETURN_OK) return DLT_RETURN_OK; if (process_error_ret == DLT_RETURN_BUFFER_FULL) { /* Buffer full */ dlt_user.overflow_counter += 1; return DLT_RETURN_BUFFER_FULL; } /* handle return value of function dlt_user_log_out3() when process_error_ret < 0*/ switch (ret) { case DLT_RETURN_PIPE_FULL: { /* data could not be written */ return DLT_RETURN_PIPE_FULL; } case DLT_RETURN_PIPE_ERROR: { /* handle not open or pipe error */ close(dlt_user.dlt_log_handle); dlt_user.dlt_log_handle = -1; #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC dlt_user.connection_state = DLT_USER_RETRY_CONNECT; #endif #ifdef DLT_SHM_ENABLE /* free shared memory */ dlt_shm_free_client(&dlt_user.dlt_shm); #endif if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC) dlt_user_print_msg(&msg, log); return DLT_RETURN_PIPE_ERROR; } case DLT_RETURN_ERROR: { /* other error condition */ return DLT_RETURN_ERROR; } case DLT_RETURN_OK: { return DLT_RETURN_OK; } default: { /* This case should never occur. */ return DLT_RETURN_ERROR; } } } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_send_register_application(void) { DltUserHeader userheader; DltUserControlMsgRegisterApplication usercontext; DltReturnValue ret; if (dlt_user.appID[0] == '\0') return DLT_RETURN_ERROR; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set usercontext */ dlt_set_id(usercontext.apid, dlt_user.appID); /* application id */ usercontext.pid = getpid(); if (dlt_user.application_description != NULL) usercontext.description_length = (uint32_t) strlen(dlt_user.application_description); else usercontext.description_length = 0; if (dlt_user.dlt_is_file) return DLT_RETURN_OK; ret = dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication), dlt_user.application_description, usercontext.description_length); /* store message in ringbuffer, if an error has occured */ if (ret < DLT_RETURN_OK) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication), dlt_user.application_description, usercontext.description_length); return DLT_RETURN_OK; } DltReturnValue dlt_user_log_send_unregister_application(void) { DltUserHeader userheader; DltUserControlMsgUnregisterApplication usercontext; DltReturnValue ret = DLT_RETURN_OK; if (dlt_user.appID[0] == '\0') return DLT_RETURN_ERROR; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set usercontext */ dlt_set_id(usercontext.apid, dlt_user.appID); /* application id */ usercontext.pid = getpid(); if (dlt_user.dlt_is_file) return DLT_RETURN_OK; ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication)); /* store message in ringbuffer, if an error has occured */ if (ret < DLT_RETURN_OK) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication), NULL, 0); return DLT_RETURN_OK; } DltReturnValue dlt_user_log_send_register_context(DltContextData *log) { DltUserHeader userheader; DltUserControlMsgRegisterContext usercontext; DltReturnValue ret = DLT_RETURN_ERROR; if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (log->handle == NULL) return DLT_RETURN_ERROR; if (log->handle->contextID[0] == '\0') return DLT_RETURN_ERROR; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set usercontext */ dlt_set_id(usercontext.apid, dlt_user.appID); /* application id */ dlt_set_id(usercontext.ctid, log->handle->contextID); /* context id */ usercontext.log_level_pos = log->handle->log_level_pos; usercontext.pid = getpid(); usercontext.log_level = (int8_t) log->log_level; usercontext.trace_status = (int8_t) log->trace_status; if (log->context_description != NULL) usercontext.description_length = (uint32_t) strlen(log->context_description); else usercontext.description_length = 0; if (dlt_user.dlt_is_file) return DLT_RETURN_OK; if (dlt_user.appID[0] != '\0') ret = dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext), log->context_description, usercontext.description_length); /* store message in ringbuffer, if an error has occured */ if ((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0')) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext), log->context_description, usercontext.description_length); return DLT_RETURN_OK; } DltReturnValue dlt_user_log_send_unregister_context(DltContextData *log) { DltUserHeader userheader; DltUserControlMsgUnregisterContext usercontext; DltReturnValue ret; if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; if (log->handle == NULL) return DLT_RETURN_WRONG_PARAMETER; if (log->handle->contextID[0] == '\0') return DLT_RETURN_ERROR; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set usercontext */ dlt_set_id(usercontext.apid, dlt_user.appID); /* application id */ dlt_set_id(usercontext.ctid, log->handle->contextID); /* context id */ usercontext.pid = getpid(); if (dlt_user.dlt_is_file) return DLT_RETURN_OK; ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext)); /* store message in ringbuffer, if an error has occured */ if (ret < DLT_RETURN_OK) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext), NULL, 0); return DLT_RETURN_OK; } DltReturnValue dlt_send_app_ll_ts_limit(const char *apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus) { DltUserHeader userheader; DltUserControlMsgAppLogLevelTraceStatus usercontext; DltReturnValue ret; if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) { dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel); return DLT_RETURN_ERROR; } if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) { dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus); return DLT_RETURN_ERROR; } if ((apid == NULL) || (apid[0] == '\0')) return DLT_RETURN_ERROR; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set usercontext */ dlt_set_id(usercontext.apid, apid); /* application id */ usercontext.log_level = loglevel; usercontext.trace_status = tracestatus; if (dlt_user.dlt_is_file) return DLT_RETURN_OK; ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus)); /* store message in ringbuffer, if an error has occured */ if (ret < DLT_RETURN_OK) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus), NULL, 0); return DLT_RETURN_OK; } DltReturnValue dlt_user_log_send_log_mode(DltUserLogMode mode) { DltUserHeader userheader; DltUserControlMsgLogMode logmode; DltReturnValue ret; if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) { dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode); return DLT_RETURN_WRONG_PARAMETER; } /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set data */ logmode.log_mode = (unsigned char)mode; if (dlt_user.dlt_is_file) return DLT_RETURN_OK; ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode)); /* store message in ringbuffer, if an error has occured */ if (ret < DLT_RETURN_OK) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode), NULL, 0); return DLT_RETURN_OK; } DltReturnValue dlt_user_log_send_marker() { DltUserHeader userheader; DltReturnValue ret; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_MARKER) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (dlt_user.dlt_is_file) return DLT_RETURN_OK; /* log to FIFO */ ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0); /* store message in ringbuffer, if an error has occured */ if (ret < DLT_RETURN_OK) return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), NULL, 0, NULL, 0); return DLT_RETURN_OK; } DltReturnValue dlt_user_print_msg(DltMessage *msg, DltContextData *log) { uint8_t *databuffer_tmp; uint32_t datasize_tmp; uint32_t databuffersize_tmp; static char text[DLT_USER_TEXT_LENGTH]; if ((msg == NULL) || (log == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* Save variables before print */ databuffer_tmp = msg->databuffer; datasize_tmp = msg->datasize; databuffersize_tmp = msg->databuffersize; /* Act like a receiver, convert header back to host format */ msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len); dlt_message_get_extraparameters(msg, 0); msg->databuffer = log->buffer; msg->datasize = (uint32_t) log->size; msg->databuffersize = (uint32_t) log->size; /* Print message as ASCII */ if (dlt_message_print_ascii(msg, text, DLT_USER_TEXT_LENGTH, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; /* Restore variables and set len to BE*/ msg->databuffer = databuffer_tmp; msg->databuffersize = databuffersize_tmp; msg->datasize = datasize_tmp; msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len); return DLT_RETURN_OK; } DltReturnValue dlt_user_log_check_user_message(void) { int offset = 0; int leave_while = 0; int ret = 0; uint32_t i; int fd; struct pollfd nfd[1]; DltUserHeader *userheader; DltReceiver *receiver = &(dlt_user.receiver); DltUserControlMsgLogLevel *usercontextll; DltUserControlMsgInjection *usercontextinj; DltUserControlMsgLogState *userlogstate; unsigned char *userbuffer; /* For delayed calling of injection callback, to avoid deadlock */ DltUserInjectionCallback delayed_injection_callback; DltUserLogLevelChangedCallback delayed_log_level_changed_callback; unsigned char *delayed_inject_buffer = 0; uint32_t delayed_inject_data_length = 0; /* Ensure that callback is null before searching for it */ delayed_injection_callback.injection_callback = 0; delayed_injection_callback.injection_callback_with_id = 0; delayed_injection_callback.service_id = 0; delayed_log_level_changed_callback.log_level_changed_callback = 0; delayed_injection_callback.data = 0; #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC fd = dlt_user.dlt_log_handle; #else /* DLT_LIB_USE_FIFO_IPC */ fd = dlt_user.dlt_user_handle; #endif nfd[0].events = POLLIN; nfd[0].fd = fd; if (fd >= 0) { ret = poll(nfd, 1, DLT_USER_RECEIVE_MDELAY); if (ret) { if (nfd[0].revents & (POLLHUP | POLLNVAL | POLLERR)) { dlt_user.dlt_log_handle = DLT_FD_INIT; return DLT_RETURN_ERROR; } if (dlt_receiver_receive(receiver) <= 0) /* No new message available */ return DLT_RETURN_OK; /* look through buffer as long as data is in there */ while (1) { if (receiver->bytesRcvd < (int32_t) sizeof(DltUserHeader)) break; /* resync if necessary */ offset = 0; do { userheader = (DltUserHeader *)(receiver->buf + offset); /* Check for user header pattern */ if (dlt_user_check_userheader(userheader)) break; offset++; } while (((int32_t) (sizeof(DltUserHeader)) + offset) <= receiver->bytesRcvd); /* Check for user header pattern */ if ((dlt_user_check_userheader(userheader) < 0) || (dlt_user_check_userheader(userheader) == 0)) break; /* Set new start offset */ if (offset > 0) { receiver->buf += offset; receiver->bytesRcvd -= offset; } switch (userheader->message) { case DLT_USER_MESSAGE_LOG_LEVEL: { if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel))) { leave_while = 1; break; } usercontextll = (DltUserControlMsgLogLevel *)(receiver->buf + sizeof(DltUserHeader)); /* Update log level and trace status */ if (usercontextll != NULL) { DLT_SEM_LOCK(); if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries)) { if (dlt_user.dlt_ll_ts) { dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = (int8_t) usercontextll->log_level; dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = (int8_t) usercontextll->trace_status; if (dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = (int8_t) usercontextll->log_level; if (dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = (int8_t) usercontextll->trace_status; delayed_log_level_changed_callback.log_level_changed_callback = dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_changed_callback; memcpy(delayed_log_level_changed_callback.contextID, dlt_user.dlt_ll_ts[usercontextll->log_level_pos].contextID, DLT_ID_SIZE); delayed_log_level_changed_callback.log_level = (int8_t) usercontextll->log_level; delayed_log_level_changed_callback.trace_status = (int8_t) usercontextll->trace_status; } } DLT_SEM_FREE(); } /* call callback outside of semaphore */ if (delayed_log_level_changed_callback.log_level_changed_callback != 0) delayed_log_level_changed_callback.log_level_changed_callback( delayed_log_level_changed_callback.contextID, (uint8_t) delayed_log_level_changed_callback.log_level, (uint8_t) delayed_log_level_changed_callback.trace_status); /* keep not read data in buffer */ if (dlt_receiver_remove(receiver, sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel)) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } break; case DLT_USER_MESSAGE_INJECTION: { /* At least, user header, user context, and service id and data_length of injected message is available */ if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection))) { leave_while = 1; break; } usercontextinj = (DltUserControlMsgInjection *)(receiver->buf + sizeof(DltUserHeader)); userbuffer = (unsigned char *)(receiver->buf + sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection)); if (userbuffer != NULL) { if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection) + usercontextinj->data_length_inject)) { leave_while = 1; break; } DLT_SEM_LOCK(); if ((usercontextinj->data_length_inject > 0) && (dlt_user.dlt_ll_ts)) /* Check if injection callback is registered for this context */ for (i = 0; i < dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks; i++) if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) && (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id)) { /* Prepare delayed injection callback call */ if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i]. injection_callback != NULL) { delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i]. injection_callback; } else if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i]. injection_callback_with_id != NULL) { delayed_injection_callback.injection_callback_with_id = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i]. injection_callback_with_id; delayed_injection_callback.data = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].data; } delayed_injection_callback.service_id = usercontextinj->service_id; delayed_inject_data_length = usercontextinj->data_length_inject; delayed_inject_buffer = malloc(delayed_inject_data_length); if (delayed_inject_buffer != NULL) { memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length); } else { DLT_SEM_FREE(); dlt_log(LOG_WARNING, "malloc failed!\n"); return DLT_RETURN_ERROR; } break; } DLT_SEM_FREE(); /* Delayed injection callback call */ if ((delayed_inject_buffer != NULL) && (delayed_injection_callback.injection_callback != NULL)) { delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length); delayed_injection_callback.injection_callback = NULL; } else if ((delayed_inject_buffer != NULL) && (delayed_injection_callback.injection_callback_with_id != NULL)) { delayed_injection_callback.injection_callback_with_id(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length, delayed_injection_callback.data); delayed_injection_callback.injection_callback_with_id = NULL; } free(delayed_inject_buffer); delayed_inject_buffer = NULL; /* keep not read data in buffer */ if (dlt_receiver_remove(receiver, (int) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection) + usercontextinj->data_length_inject)) != DLT_RETURN_OK) return DLT_RETURN_ERROR; } } break; case DLT_USER_MESSAGE_LOG_STATE: { /* At least, user header, user context, and service id and data_length of injected message is available */ if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogState))) { leave_while = 1; break; } userlogstate = (DltUserControlMsgLogState *)(receiver->buf + sizeof(DltUserHeader)); dlt_user.log_state = userlogstate->log_state; /* keep not read data in buffer */ if (dlt_receiver_remove(receiver, (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogState))) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } break; default: { dlt_log(LOG_WARNING, "Invalid user message type received!\n"); /* Ignore result */ dlt_receiver_remove(receiver, sizeof(DltUserHeader)); /* In next invocation of while loop, a resync will be triggered if additional data was received */ } break; } /* switch() */ if (leave_while == 1) { leave_while = 0; break; } } /* while buffer*/ if (dlt_receiver_move_to_begin(receiver) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } /* while receive */ } /* if */ return DLT_RETURN_OK; } DltReturnValue dlt_user_log_resend_buffer(void) { int num, count; int size; DltReturnValue ret; DLT_SEM_LOCK(); if (dlt_user.appID[0] == '\0') { DLT_SEM_FREE(); return 0; } /* Send content of ringbuffer */ count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer)); DLT_SEM_FREE(); for (num = 0; num < count; num++) { DLT_SEM_LOCK(); size = dlt_buffer_copy(&(dlt_user.startup_buffer), dlt_user.resend_buffer, dlt_user.log_buf_len); if (size > 0) { DltUserHeader *userheader = (DltUserHeader *)(dlt_user.resend_buffer); /* Add application id to the messages of needed*/ if (dlt_user_check_userheader(userheader)) { switch (userheader->message) { case DLT_USER_MESSAGE_REGISTER_CONTEXT: { DltUserControlMsgRegisterContext *usercontext = (DltUserControlMsgRegisterContext *)(dlt_user.resend_buffer + sizeof(DltUserHeader)); if ((usercontext != 0) && (usercontext->apid[0] == '\0')) dlt_set_id(usercontext->apid, dlt_user.appID); break; } case DLT_USER_MESSAGE_LOG: { DltExtendedHeader *extendedHeader = (DltExtendedHeader *)(dlt_user.resend_buffer + sizeof(DltUserHeader) + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra)); if (((extendedHeader) != 0) && (extendedHeader->apid[0] == '\0')) /* if application id is empty, add it */ dlt_set_id(extendedHeader->apid, dlt_user.appID); break; } default: { break; } } } #ifdef DLT_SHM_ENABLE dlt_shm_push(&dlt_user.dlt_shm, dlt_user.resend_buffer + sizeof(DltUserHeader), size - sizeof(DltUserHeader), 0, 0, 0, 0); ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer, sizeof(DltUserHeader), 0, 0, 0, 0); #else ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer, (size_t) size, 0, 0, 0, 0); #endif /* in case of error, keep message in ringbuffer */ if (ret == DLT_RETURN_OK) { dlt_buffer_remove(&(dlt_user.startup_buffer)); } else { if (ret == DLT_RETURN_PIPE_ERROR) { /* handle not open or pipe error */ close(dlt_user.dlt_log_handle); dlt_user.dlt_log_handle = -1; } /* keep message in ringbuffer */ DLT_SEM_FREE(); return ret; } } DLT_SEM_FREE(); } return DLT_RETURN_OK; } void dlt_user_log_reattach_to_daemon(void) { uint32_t num; DltContext handle; DltContextData log_new; if (dlt_user.dlt_log_handle < 0) { dlt_user.dlt_log_handle = DLT_FD_INIT; #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC /* try to open connection to dlt daemon */ dlt_initialize_socket_connection(); if (dlt_user.connection_state != DLT_USER_CONNECTED) /* return if not connected */ return; #elif defined DLT_LIB_USE_VSOCK_IPC dlt_initialize_vsock_connection(); if (dlt_user.connection_state != DLT_USER_CONNECTED) return; #else /* DLT_LIB_USE_FIFO_IPC */ /* try to open pipe to dlt daemon */ int fd = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK); if (fd < 0) return; dlt_user.dlt_log_handle = fd; #endif if (dlt_user_log_init(&handle, &log_new) < DLT_RETURN_OK) return; #ifdef DLT_SHM_ENABLE /* init shared memory */ if (dlt_shm_init_client(&dlt_user.dlt_shm, dltShmName) < DLT_RETURN_OK) dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled," " Shared memory %s cannot be created!\n", dltShmName); #endif dlt_log(LOG_NOTICE, "Logging (re-)enabled!\n"); /* Re-register application */ if (dlt_user_log_send_register_application() < DLT_RETURN_ERROR) return; DLT_SEM_LOCK(); /* Re-register all stored contexts */ for (num = 0; num < dlt_user.dlt_ll_ts_num_entries; num++) /* Re-register stored context */ if ((dlt_user.appID[0] != '\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0] != '\0')) { /*dlt_set_id(log_new.appID, dlt_user.appID); */ dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID); handle.log_level_pos = (int32_t) num; log_new.context_description = dlt_user.dlt_ll_ts[num].context_description; /* Release the mutex for sending context registration: */ /* function dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock */ DLT_SEM_FREE(); log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET; log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET; if (dlt_user_log_send_register_context(&log_new) < DLT_RETURN_ERROR) return; /* Lock again the mutex */ /* it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section. */ DLT_SEM_LOCK(); } DLT_SEM_FREE(); } } DltReturnValue dlt_user_log_send_overflow(void) { DltUserHeader userheader; DltUserControlMsgBufferOverflow userpayload; /* set userheader */ if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (dlt_user.dlt_is_file) return DLT_RETURN_OK; /* set user message parameters */ userpayload.overflow_counter = dlt_user.overflow_counter; dlt_set_id(userpayload.apid, dlt_user.appID); return dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(userpayload), sizeof(DltUserControlMsgBufferOverflow)); } DltReturnValue dlt_user_check_buffer(int *total_size, int *used_size) { if ((total_size == NULL) || (used_size == NULL)) return DLT_RETURN_WRONG_PARAMETER; DLT_SEM_LOCK(); #ifdef DLT_SHM_ENABLE *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm)); *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm)); #else *total_size = (int) dlt_buffer_get_total_size(&(dlt_user.startup_buffer)); *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer)); #endif DLT_SEM_FREE(); return DLT_RETURN_OK; /* ok */ } #ifdef DLT_TEST_ENABLE void dlt_user_test_corrupt_user_header(int enable) { dlt_user.corrupt_user_header = enable; } void dlt_user_test_corrupt_message_size(int enable, int16_t size) { dlt_user.corrupt_message_size = enable; dlt_user.corrupt_message_size_size = size; } #endif int dlt_start_threads() { struct timespec time_to_wait, single_wait; struct timespec now; int signal_status = 1; atomic_bool dlt_housekeeper_running = false; /* * Configure the condition varibale to use CLOCK_MONOTONIC. * This makes sure we're protected against changes in the system clock */ pthread_condattr_t attr; pthread_condattr_init(&attr); pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); pthread_cond_init(&dlt_housekeeper_running_cond, &attr); if (pthread_create(&(dlt_housekeeperthread_handle), 0, (void *)&dlt_user_housekeeperthread_function, &dlt_housekeeper_running) != 0) { dlt_log(LOG_CRIT, "Can't create housekeeper thread!\n"); return -1; } clock_gettime(CLOCK_MONOTONIC, &now); /* wait at most 10s */ time_to_wait.tv_sec = now.tv_sec + 10; time_to_wait.tv_nsec = now.tv_nsec; /* * wait until the house keeper is up and running * Even though the condition variable and the while are * using the same time out the while loop is not a no op. * This is due to the fact that the pthread_cond_timedwait * can be woken before time is up and dlt_housekeeper_running is not true yet. * (spurious wakeup) * To protect against this, a while loop with a timeout is added * */ while (!dlt_housekeeper_running && now.tv_sec <= time_to_wait.tv_sec) { /* * wait 500ms at a time * this makes sure we don't block too long * even if we missed the signal */ clock_gettime(CLOCK_MONOTONIC, &now); single_wait.tv_sec = now.tv_sec; single_wait.tv_nsec = now.tv_nsec + 500000000; // pthread_cond_timedwait has to be called on a locked mutex pthread_mutex_lock(&dlt_housekeeper_running_mutex); signal_status = pthread_cond_timedwait( &dlt_housekeeper_running_cond, &dlt_housekeeper_running_mutex, &single_wait); pthread_mutex_unlock(&dlt_housekeeper_running_mutex); /* otherwise it might be a spurious wakeup, try again until the time is over */ if (signal_status == 0) { break; } } if (signal_status != 0 && !dlt_housekeeper_running) { dlt_log(LOG_CRIT, "Failed to wait for house keeper thread!\n"); dlt_stop_threads(); return -1; } #ifdef DLT_NETWORK_TRACE_ENABLE /* Start the segmented thread */ if (pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL, (void *)dlt_user_trace_network_segmented_thread, NULL)) { dlt_log(LOG_CRIT, "Can't start segmented thread!\n"); return -1; } #endif return 0; } void dlt_stop_threads() { int dlt_housekeeperthread_result = 0; int joined = 0; if (dlt_housekeeperthread_handle) { /* do not ignore return value */ #ifndef __ANDROID_API__ dlt_housekeeperthread_result = pthread_cancel(dlt_housekeeperthread_handle); #else #ifdef DLT_NETWORK_TRACE_ENABLE dlt_lock_mutex(&mq_mutex); #endif /* DLT_NETWORK_TRACE_ENABLE */ dlt_housekeeperthread_result = pthread_kill(dlt_housekeeperthread_handle, SIGUSR1); dlt_user_cleanup_handler(NULL); #endif if (dlt_housekeeperthread_result != 0) dlt_vlog(LOG_ERR, "ERROR %s(dlt_housekeeperthread_handle): %s\n", #ifndef __ANDROID_API__ "pthread_cancel", #else "pthread_kill", #endif strerror(dlt_housekeeperthread_result)); } #ifdef DLT_NETWORK_TRACE_ENABLE int dlt_segmented_nwt_result = 0; if (dlt_user.dlt_segmented_nwt_handle) { dlt_lock_mutex(&mq_mutex); pthread_cond_signal(&mq_init_condition); dlt_unlock_mutex(&mq_mutex); dlt_segmented_nwt_result = pthread_cancel(dlt_user.dlt_segmented_nwt_handle); if (dlt_segmented_nwt_result != 0) dlt_vlog(LOG_ERR, "ERROR pthread_cancel(dlt_user.dlt_segmented_nwt_handle): %s\n", strerror(dlt_segmented_nwt_result)); } #endif /* DLT_NETWORK_TRACE_ENABLE */ /* make sure that the threads really finished working */ if ((dlt_housekeeperthread_result == 0) && dlt_housekeeperthread_handle) { joined = pthread_join(dlt_housekeeperthread_handle, NULL); if (joined != 0) dlt_vlog(LOG_ERR, "ERROR pthread_join(dlt_housekeeperthread_handle, NULL): %s\n", strerror(joined)); dlt_housekeeperthread_handle = 0; /* set to invalid */ } #ifdef DLT_NETWORK_TRACE_ENABLE if ((dlt_segmented_nwt_result == 0) && dlt_user.dlt_segmented_nwt_handle) { joined = pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL); if (joined != 0) dlt_vlog(LOG_ERR, "ERROR pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL): %s\n", strerror(joined)); dlt_user.dlt_segmented_nwt_handle = 0; /* set to invalid */ } #endif /* DLT_NETWORK_TRACE_ENABLE */ } static void dlt_fork_child_fork_handler() { g_dlt_is_child = 1; dlt_user_init_state = INIT_UNITIALIZED; dlt_user.dlt_log_handle = -1; } DltReturnValue dlt_user_log_out_error_handling(void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3, size_t len3) { DltReturnValue ret = DLT_RETURN_ERROR; size_t msg_size = len1 + len2 + len3; DLT_SEM_LOCK(); ret = dlt_buffer_check_size(&(dlt_user.startup_buffer), (int)msg_size); DLT_SEM_FREE(); DLT_SEM_LOCK(); if (dlt_buffer_push3(&(dlt_user.startup_buffer), ptr1, (unsigned int)len1, ptr2, (unsigned int)len2, ptr3, (unsigned int)len3) == DLT_RETURN_ERROR) { if (dlt_user.overflow_counter == 0) dlt_log(LOG_WARNING, "Buffer full! Messages will be discarded.\n"); ret = DLT_RETURN_BUFFER_FULL; } DLT_SEM_FREE(); return ret; } dlt-daemon-2.18.10/src/lib/dlt_user_cfg.h000066400000000000000000000163121446635226000200700ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user_cfg.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_user_cfg.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_USER_CFG_H #define DLT_USER_CFG_H /*************/ /* Changable */ /*************/ /* Size of receive buffer */ #define DLT_USER_RCVBUF_MAX_SIZE 10024 /* Size of ring buffer */ #define DLT_USER_RINGBUFFER_MIN_SIZE 50000 #define DLT_USER_RINGBUFFER_MAX_SIZE 500000 #define DLT_USER_RINGBUFFER_STEP_SIZE 50000 /* Name of environment variable for ringbuffer configuration */ #define DLT_USER_ENV_BUFFER_MIN_SIZE "DLT_USER_BUFFER_MIN" #define DLT_USER_ENV_BUFFER_MAX_SIZE "DLT_USER_BUFFER_MAX" #define DLT_USER_ENV_BUFFER_STEP_SIZE "DLT_USER_BUFFER_STEP" /* Temporary buffer length */ #define DLT_USER_BUFFER_LENGTH 255 /* Number of context entries, which will be allocated, * if no more context entries are available */ #define DLT_USER_CONTEXT_ALLOC_SIZE 500 /* Maximu length of a filename string */ #define DLT_USER_MAX_FILENAME_LENGTH 255 /* Maximum length of a single version number */ #define DLT_USER_MAX_LIB_VERSION_LENGTH 3 /* Length of buffer for constructing text output */ #define DLT_USER_TEXT_LENGTH 10024 /* Stack size of receiver thread */ #define DLT_USER_RECEIVERTHREAD_STACKSIZE 100000 /* default value for storage to file, not used in daemon connection */ #define DLT_USER_DEFAULT_ECU_ID "ECU1" /* Initial log level */ #define DLT_USER_INITIAL_LOG_LEVEL DLT_LOG_INFO /* Initial trace status */ #define DLT_USER_INITIAL_TRACE_STATUS DLT_TRACE_STATUS_OFF /* send always session id: 0 - don't use, 1 - use */ #define DLT_USER_WITH_SESSION_ID 1 /* send always timestamp: 0 - don't use, 1 - use */ #define DLT_USER_WITH_TIMESTAMP 1 /* send always ecu id: 0 - don't use, 1 - use */ #define DLT_USER_WITH_ECU_ID 1 /* default message id for non-verbose mode, if no message id was provided */ #define DLT_USER_DEFAULT_MSGID 0xffff /* timeout for poll operations in milliseconds*/ #define DLT_USER_RECEIVE_MDELAY (500) /* delay for housekeeper thread (nsec) while receiving messages*/ #define DLT_USER_RECEIVE_NDELAY (DLT_USER_RECEIVE_MDELAY * 1000 * 1000) /* Name of environment variable for local print mode */ #define DLT_USER_ENV_LOCAL_PRINT_MODE "DLT_LOCAL_PRINT_MODE" /* Timeout offset for resending user buffer at exit in 10th milliseconds (10000 = 1s)*/ #define DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT 100000 /* Sleeps between resending user buffer at exit in nsec (1000000 nsec = 1ms)*/ #define DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP 100000000 /* Name of environment variable to disable extended header in non verbose mode */ #define DLT_USER_ENV_DISABLE_EXTENDED_HEADER_FOR_NONVERBOSE \ "DLT_DISABLE_EXTENDED_HEADER_FOR_NONVERBOSE" typedef enum { DLT_USER_NO_USE_EXTENDED_HEADER_FOR_NONVERBOSE = 0, DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE } DltExtHeaderNonVer; /* Retry interval for mq error in usec */ #define DLT_USER_MQ_ERROR_RETRY_INTERVAL 100000 /* Name of environment variable to change the dlt log message buffer size */ #define DLT_USER_ENV_LOG_MSG_BUF_LEN "DLT_LOG_MSG_BUF_LEN" /* Maximum msg size as per autosar standard */ #define DLT_LOG_MSG_BUF_MAX_SIZE 65535 /* Name of environment variable for disabling the injection message at libdlt */ #define DLT_USER_ENV_DISABLE_INJECTION_MSG "DLT_DISABLE_INJECTION_MSG_AT_USER" /************************/ /* Don't change please! */ /************************/ /* Minimum valid ID of an injection message */ #define DLT_USER_INJECTION_MIN 0xFFF /* Defines of the different local print modes */ #define DLT_PM_UNSET 0 #define DLT_PM_AUTOMATIC 1 #define DLT_PM_FORCE_ON 2 #define DLT_PM_FORCE_OFF 3 #endif /* DLT_USER_CFG_H */ dlt-daemon-2.18.10/src/offlinelogstorage/000077500000000000000000000000001446635226000202175ustar00rootroot00000000000000dlt-daemon-2.18.10/src/offlinelogstorage/dlt_offline_logstorage.c000066400000000000000000002201211446635226000250740ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality source file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * * \file: dlt_offline_logstorage.c * For further information see http://www.covesa.org/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dlt_offline_logstorage.h" #include "dlt_offline_logstorage_internal.h" #include "dlt_offline_logstorage_behavior.h" #include "dlt_config_file_parser.h" #define DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR 1 #define DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR 2 #define DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE 3 #define GENERAL_BASE_NAME "General" DLT_STATIC void dlt_logstorage_filter_config_free(DltLogStorageFilterConfig *data) { DltLogStorageFileList *n = NULL; DltLogStorageFileList *n1 = NULL; if (data->apids) { free(data->apids); data->apids = NULL; } if (data->ctids) { free(data->ctids); data->ctids = NULL; } if (data->file_name) { free(data->file_name); data->file_name = NULL; } if (data->working_file_name) { free(data->working_file_name); data->working_file_name = NULL; } if (data->ecuid != NULL) { free(data->ecuid); data->ecuid = NULL; } if (data->log != NULL) fclose(data->log); #ifdef DLT_LOGSTORAGE_USE_GZIP if (data->gzlog != NULL) gzclose(data->gzlog); #endif if (data->cache != NULL) { free(data->cache); data->cache = NULL; } n = data->records; while (n) { n1 = n; n = n->next; if (n1->name) { free(n1->name); n1->name = NULL; } free(n1); n1 = NULL; } } /** * dlt_logstorage_list_destroy * * Destroy Filter configurations list. * * @param list List of the filter configurations will be destroyed. * @param uconfig User configurations for log file * @param dev_path Path to the device * @param reason Reason for the destroying of Filter configurations list * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_list_destroy(DltLogStorageFilterList **list, DltLogStorageUserConfig *uconfig, char *dev_path, int reason) { DltLogStorageFilterList *tmp = NULL; while (*(list) != NULL) { tmp = *list; *list = (*list)->next; if (tmp->key_list != NULL) { free(tmp->key_list); tmp->key_list = NULL; } if (tmp->data != NULL) { /* sync data if necessary */ /* ignore return value */ tmp->data->dlt_logstorage_sync(tmp->data, uconfig, dev_path, reason); dlt_logstorage_filter_config_free(tmp->data); free(tmp->data); tmp->data = NULL; } free(tmp); tmp = NULL; } return 0; } DLT_STATIC int dlt_logstorage_list_add_config(DltLogStorageFilterConfig *data, DltLogStorageFilterConfig **listdata) { if (*(listdata) == NULL) return -1; /* copy the data to list */ memcpy(*listdata, data, sizeof(DltLogStorageFilterConfig)); if (data->apids != NULL) (*listdata)->apids = strdup(data->apids); if (data->ctids != NULL) (*listdata)->ctids = strdup(data->ctids); if (data->file_name != NULL) (*listdata)->file_name = strdup(data->file_name); if (data->ecuid != NULL) (*listdata)->ecuid = strdup(data->ecuid); return 0; } /** * dlt_logstorage_list_add * * Add Filter configurations to the list. * * @param keys Keys will be added to the list. * @param num_keys Number of keys * @param data Filter configurations data will be added to the list. * @param list List of the filter configurations * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_list_add(char *keys, int num_keys, DltLogStorageFilterConfig *data, DltLogStorageFilterList **list) { DltLogStorageFilterList *tmp = NULL; while (*(list) != NULL) { list = &(*list)->next; } tmp = calloc(1, sizeof(DltLogStorageFilterList)); if (tmp == NULL) return -1; tmp->key_list = (char *)calloc( (num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN), sizeof(char)); if (tmp->key_list == NULL) { free(tmp); tmp = NULL; return -1; } memcpy(tmp->key_list, keys, num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); tmp->num_keys = num_keys; tmp->next = NULL; tmp->data = calloc(1, sizeof(DltLogStorageFilterConfig)); if (tmp->data == NULL) { free(tmp->key_list); tmp->key_list = NULL; free(tmp); tmp = NULL; return -1; } if (dlt_logstorage_list_add_config(data, &(tmp->data)) != 0) { free(tmp->key_list); tmp->key_list = NULL; free(tmp->data); tmp->data = NULL; free(tmp); tmp = NULL; return -1; } *list = tmp; return 0; } /** * dlt_logstorage_list_find * * Find all Filter configurations corresponding with key provided. * * @param key Key to find the filter configurations * @param list List of the filter configurations * @param config Filter configurations corresponding with the key. * @return Number of the filter configuration found. */ DLT_STATIC int dlt_logstorage_list_find(char *key, DltLogStorageFilterList **list, DltLogStorageFilterConfig **config) { int i = 0; int num = 0; while (*(list) != NULL) { for (i = 0; i < (*list)->num_keys; i++) { if (strncmp(((*list)->key_list + (i * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), key, DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) == 0) { config[num] = (*list)->data; num++; break; } } list = &(*list)->next; } return num; } /* Configuration file parsing helper functions */ DLT_STATIC int dlt_logstorage_count_ids(const char *str) { if (str == NULL) return -1; /* delimiter is: "," */ const char *p = str; int i = 0; int num = 1; while (p[i] != 0) { if (p[i] == ',') num++; i++; } return num; } /** * dlt_logstorage_free * * Free all allocated memory used in log storage handle * * @param handle DLT Logstorage handle * @param reason Reason for freeing the device * */ void dlt_logstorage_free(DltLogStorage *handle, int reason) { if (handle == NULL) { dlt_vlog(LOG_ERR, "%s failed: handle is NULL\n", __func__); return; } dlt_logstorage_list_destroy(&(handle->config_list), &handle->uconfig, handle->device_mount_point, reason); } /** * dlt_logstorage_read_list_of_names * * Evaluate app and ctx names given in config file and create a list of names * acceptable by DLT Daemon. When using SET_APPLICATION_NAME and SET_CONTEXT_NAME * there is no constraint that these names have max 4 characters. Internally, * these names are cutted down to max 4 chars. To have create valid keys, the * internal representation of these names has to be considered. * Therefore, a given configuration of "AppLogName = App1,Application2,A3" will * be stored as "App1,Appl,A3". * * @param names to store the list of names * @param value string given in config file * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) { int i = 0; int y = 0; int len = 0; char *tok; int num = 1; if ((names == NULL) || (value == NULL)) return -1; /* free, alloce'd memory to store new apid/ctid */ if (*names != NULL) { free(*names); *names = NULL; } len = strlen(value); if (len == 0) return -1; /* count number of delimiters to get actual number off names */ num = dlt_logstorage_count_ids(value); /* need to alloc space for 5 chars, 4 for the name and "," and "\0" */ *names = (char *)calloc(num * 5, sizeof(char)); if (*names == NULL) return -1; tok = strtok(value, ","); i = 1; while (tok != NULL) { len = strlen(tok); len = DLT_OFFLINE_LOGSTORAGE_MIN(len, 4); strncpy((*names + y), tok, len); if ((num > 1) && (i < num)) strncpy((*names + y + len), ",", 2); y += len + 1; i++; tok = strtok(NULL, ","); } return 0; } /** * dlt_logstorage_read_number * * Evaluate file size and number of files given in config file and set file size * The file number is checked by converting a string to an unsigned integer * width 0 > result < UINT_MAX (excludes 0!) * Non-digit characters including spaces and out of boundary will lead to an * error -1. * * @param number Number to be read * @param value string given in config file * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_read_number(unsigned int *number, char *value) { int i = 0; int len = 0; unsigned long size = 0; if (value == NULL) return -1; *number = 0; len = strlen(value); /* check if string consists of digits only */ for (i = 0; i < len; i++) if (!isdigit(value[i])) { dlt_log(LOG_ERR, "Invalid, is not a number \n"); return -1; } size = strtoul(value, NULL, 10); if ((size == 0) || (size > UINT_MAX)) { dlt_log(LOG_ERR, "Invalid, is not a number \n"); return -1; } *number = (unsigned int)size; return 0; } /** * dlt_logstorage_read_bool * * Evaluate a boolean config value. Values such as '1', 'on' or 'true' will be * treated as true otherwise the config value will be interpreted as false. * * @param bool The boolean to populate * @param value The string from the config file * @returns 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_read_bool(unsigned int *boolean, char *value) { int len = 0; if (value == NULL) return -1; len = strnlen(value, 5); *boolean = 0; if (strncmp(value, "on", len) == 0) { *boolean = 1; } else if (strncmp(value, "true", len) == 0) { *boolean = 1; } else if (strncmp(value, "1", len) == 0) { *boolean = 1; } return 0; } /** * dlt_logstorage_get_keys_list * * Obtain key list and number of keys for id list passed * after splitting it between seperator (,) * * @param ids ID's * @param sep Seperator * @param list Prepared key list is stored here * @param numids Number of keys in the list is stored here * @return: 0 on success, error on failure* */ DLT_STATIC int dlt_logstorage_get_keys_list(char *ids, char *sep, char **list, int *numids) { char *token = NULL; char *tmp_token = NULL; char *ids_local = NULL; *numids = 0; /* Duplicate the ids passed for using in strtok_r() */ ids_local = strdup(ids); if (ids_local == NULL) return -1; token = strtok_r(ids_local, sep, &tmp_token); if (token == NULL) { free(ids_local); return -1; } *list = (char *)calloc(DLT_OFFLINE_LOGSTORAGE_MAXIDS * (DLT_ID_SIZE + 1), sizeof(char)); if (*(list) == NULL) { free(ids_local); return -1; } while (token != NULL) { /* If it reached the max then other ids are ignored */ if (*numids >= DLT_OFFLINE_LOGSTORAGE_MAXIDS) { free(ids_local); return 0; } strncpy(((*list) + ((*numids) * (DLT_ID_SIZE + 1))), token, DLT_ID_SIZE); *numids = *numids + 1; token = strtok_r(NULL, sep, &tmp_token); } free(ids_local); return 0; } /** * dlt_logstorage_create_keys_only_ctid * * Prepares keys with context ID alone, will use ecuid if provided * (ecuid\:\:ctid) or (\:\:ctid) * * @param ecuid ECU ID * @param ctid Context ID * @param key Prepared key stored here * @return None */ DLT_STATIC void dlt_logstorage_create_keys_only_ctid(char *ecuid, char *ctid, char *key) { char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; int curr_len = 0; if (ecuid != NULL) { strncpy(curr_str, ecuid, DLT_ID_SIZE); strncat(curr_str, "::", 2); } else { strncpy(curr_str, "::", 2); } curr_len = strlen(ctid); strncat(curr_str, ctid, curr_len); curr_len = strlen(curr_str); strncpy(key, curr_str, curr_len); } /** * dlt_logstorage_create_keys_only_apid * * Prepares keys with application ID alone, will use ecuid if provided * (ecuid:apid::) or (:apid::) * * @param ecuid ECU ID * @param apid Application ID * @param key Prepared key stored here * @return None */ DLT_STATIC void dlt_logstorage_create_keys_only_apid(char *ecuid, char *apid, char *key) { char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; int curr_len = 0; if (ecuid != NULL) { strncpy(curr_str, ecuid, DLT_ID_SIZE); strncat(curr_str, ":", 1); } else { strncpy(curr_str, ":", 1); } curr_len = strlen(apid); strncat(curr_str, apid, curr_len); strncat(curr_str, ":", 1); curr_len = strlen(curr_str); strncpy(key, curr_str, curr_len); } /** * dlt_logstorage_create_keys_multi * * Prepares keys with apid, ctid (ecuid:apid:ctid), will use ecuid if is provided * (ecuid:apid:ctid) or (:apid:ctid) * * @param ecuid ECU ID * @param apid Application ID * @param ctid Context ID * @param key Prepared key stored here * @return None */ DLT_STATIC void dlt_logstorage_create_keys_multi(char *ecuid, char *apid, char *ctid, char *key) { char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; int curr_len = 0; if (ecuid != NULL) { strncpy(curr_str, ecuid, DLT_ID_SIZE); strncat(curr_str, ":", 1); } else { strncpy(curr_str, ":", 1); } curr_len = strlen(apid); strncat(curr_str, apid, curr_len); strncat(curr_str, ":", 1); curr_len = strlen(ctid); strncat(curr_str, ctid, curr_len); curr_len = strlen(curr_str); strncpy(key, curr_str, curr_len); } /** * dlt_logstorage_create_keys_only_ecu * * Prepares keys with only ecuid (ecuid::) * * @param ecuid ECU ID * @param key Prepared key stored here * @return None */ DLT_STATIC void dlt_logstorage_create_keys_only_ecu(char *ecuid, char *key) { char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; strncpy(curr_str, ecuid, DLT_ID_SIZE); strncat(curr_str, "::", 2); strncpy(key, curr_str, strlen(curr_str)); } /** * dlt_logstorage_create_keys * * Create keys for hash table * * From each section [filter] in offline logstorage configuration file, we * receive application and context id strings. * Application and context id can consist of * - a 4char long name * - a comma separated list of ids * - a wildcard: .* * * If both application and context id are set to wildcard, this will be treated * in the same way of the case application and context id are not present: * - EcuID must be specified * * If lists given for application and/or context id, all possible combinations * are returned as keys in a form "[apid][ctid], e.g. "APP1\:CTX1". * If wildcards are used, the non-wildcard value becomes the key, e.g. "APP1\:" * or "\:CTX2". * * @param[in] apids string given from filter configuration * @param[in] ctids string given from filter configuration * @param[in] ecuid string given from filter configuration * @param[out] keys keys to fill into hash table * @param[out] num_keys number of keys * @return: 0 on success, error on failure* */ DLT_STATIC int dlt_logstorage_create_keys(char *apids, char *ctids, char *ecuid, char **keys, int *num_keys) { int i, j; int num_apids = 0; int num_ctids = 0; char *apid_list = NULL; char *ctid_list = NULL; char *curr_apid = NULL; char *curr_ctid = NULL; char curr_key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; int num_currkey = 0; /* Handle ecuid alone case here */ if (((apids == NULL) && (ctids == NULL) && (ecuid != NULL)) || ((apids != NULL) && (strncmp(apids, ".*", 2) == 0) && (ctids != NULL) && (strncmp(ctids, ".*", 2) == 0) && (ecuid != NULL)) ) { dlt_logstorage_create_keys_only_ecu(ecuid, curr_key); *(num_keys) = 1; *(keys) = (char *)calloc(*num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, sizeof(char)); if (*(keys) == NULL) return -1; strncpy(*keys, curr_key, strlen(curr_key)); return 0; } if ((apids == NULL) || (ctids == NULL)) { dlt_log(LOG_ERR, "Required inputs (apid and ctid) are NULL\n"); return -1; } /* obtain key list and number of keys for application ids */ if (dlt_logstorage_get_keys_list(apids, ",", &apid_list, &num_apids) != 0) { dlt_log(LOG_ERR, "Failed to obtain apid, check configuration file \n"); return -1; } /* obtain key list and number of keys for context ids */ if (dlt_logstorage_get_keys_list(ctids, ",", &ctid_list, &num_ctids) != 0) { dlt_log(LOG_ERR, "Failed to obtain ctid, check configuration file \n"); free(apid_list); return -1; } *(num_keys) = num_apids * num_ctids; /* allocate memory for needed number of keys */ *(keys) = (char *)calloc(*num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, sizeof(char)); if (*(keys) == NULL) { free(apid_list); free(ctid_list); return -1; } /* store all combinations of apid ctid in keys */ for (i = 0; i < num_apids; i++) { curr_apid = apid_list + (i * (DLT_ID_SIZE + 1)); for (j = 0; j < num_ctids; j++) { curr_ctid = ctid_list + (j * (DLT_ID_SIZE + 1)); if (strncmp(curr_apid, ".*", 2) == 0) /* only context id matters */ dlt_logstorage_create_keys_only_ctid(ecuid, curr_ctid, curr_key); else if (strncmp(curr_ctid, ".*", 2) == 0) /* only app id matters*/ dlt_logstorage_create_keys_only_apid(ecuid, curr_apid, curr_key); else /* key is combination of all */ dlt_logstorage_create_keys_multi(ecuid, curr_apid, curr_ctid, curr_key); strncpy((*keys + (num_currkey * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), curr_key, strlen(curr_key)); num_currkey += 1; memset(&curr_key[0], 0, sizeof(curr_key)); } } free(apid_list); free(ctid_list); return 0; } /** * dlt_logstorage_prepare_table * * Prepares hash table with keys and data * * @param handle DLT Logstorage handle * @param data Holds all other configuration values * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_prepare_table(DltLogStorage *handle, DltLogStorageFilterConfig *data) { int ret = 0; int num_keys = 0; int found = 0; char *keys = NULL; DltNewestFileName *tmp = NULL; DltNewestFileName *prev_tmp = NULL; DltNewestFileName *new_tmp = NULL; if ((handle == NULL) || (data == NULL)) { dlt_vlog(LOG_ERR, "Invalid parameters in %s\n", __func__); return -1; } ret = dlt_logstorage_create_keys(data->apids, data->ctids, data->ecuid, &keys, &num_keys); if (ret != 0) { dlt_log(LOG_ERR, "Not able to create keys for hash table\n"); return -1; } /* hash_add */ if (dlt_logstorage_list_add(keys, num_keys, data, &(handle->config_list)) != 0) { dlt_log(LOG_ERR, "Adding to hash table failed, returning failure\n"); dlt_logstorage_free(handle, DLT_LOGSTORAGE_SYNC_ON_ERROR); free(keys); keys = NULL; return -1; } if (data->file_name) { if (handle->newest_file_list != NULL) { tmp = handle->newest_file_list; while (tmp) { if (strcmp(tmp->file_name, data->file_name) == 0) { found = 1; break; } else { prev_tmp = tmp; tmp = tmp->next; } } } if (!found) { new_tmp = calloc(1, sizeof(DltNewestFileName)); if (new_tmp == NULL) { /* In this case, the existing list does not need to be freed.*/ dlt_vlog(LOG_ERR, "Failed to allocate memory for new file name [%s]\n", data->file_name); free(keys); keys = NULL; return -1; } new_tmp->file_name = strdup(data->file_name); new_tmp->newest_file = NULL; new_tmp->next = NULL; if (handle->newest_file_list == NULL) handle->newest_file_list = new_tmp; else prev_tmp->next = new_tmp; } } free(keys); keys = NULL; return 0; } /** * dlt_logstorage_validate_filter_name * * Validates if the provided filter name is as required [FILTER] * * @param name Filter name * @return 0 on success, -1 on error * */ DLT_STATIC int dlt_logstorage_validate_filter_name(char *name) { int len = 0; int idx = 0; int config_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION); int storage_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION); int control_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION); if (name == NULL) return -1; len = strlen(name); /* Check if section header is of format "FILTER" followed by a number */ if (strncmp(name, DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION, config_sec_len) == 0) { for (idx = config_sec_len; idx < len - 1; idx++) if (!isdigit(name[idx])) return -1; return 0; } /* Check if section header is of format "FILTER" followed by a number */ else if (strncmp(name, DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION, storage_sec_len) == 0) { for (idx = storage_sec_len; idx < len - 1; idx++) if (!isdigit(name[idx])) return -1; return 0; } /* Check if section header is of format "FILTER" followed by a number */ else if (strncmp(name, DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION, control_sec_len) == 0) { for (idx = control_sec_len; idx < len - 1; idx++) if (!isdigit(name[idx])) return -1; return 0; } else { return -1; } } DLT_STATIC void dlt_logstorage_filter_set_strategy(DltLogStorageFilterConfig *config, int strategy) { if (config == NULL) return; /* file based */ if ((strategy == DLT_LOGSTORAGE_SYNC_ON_MSG) || (strategy == DLT_LOGSTORAGE_SYNC_UNSET)) { config->dlt_logstorage_prepare = &dlt_logstorage_prepare_on_msg; config->dlt_logstorage_write = &dlt_logstorage_write_on_msg; config->dlt_logstorage_sync = &dlt_logstorage_sync_on_msg; } else { /* cache based */ config->dlt_logstorage_prepare = &dlt_logstorage_prepare_msg_cache; config->dlt_logstorage_write = &dlt_logstorage_write_msg_cache; config->dlt_logstorage_sync = &dlt_logstorage_sync_msg_cache; } } DLT_STATIC int dlt_logstorage_check_apids(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) { dlt_log(LOG_ERR, "Not able to create keys for hash table\n"); return -1; } return dlt_logstorage_read_list_of_names(&config->apids, value); } DLT_STATIC int dlt_logstorage_check_ctids(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; return dlt_logstorage_read_list_of_names(&config->ctids, value); } DLT_STATIC int dlt_logstorage_check_loglevel(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; if (value == NULL) { config->log_level = 0; return -1; } if (strcmp(value, "DLT_LOG_FATAL") == 0) { config->log_level = 1; } else if (strcmp(value, "DLT_LOG_ERROR") == 0) { config->log_level = 2; } else if (strcmp(value, "DLT_LOG_WARN") == 0) { config->log_level = 3; } else if (strcmp(value, "DLT_LOG_INFO") == 0) { config->log_level = 4; } else if (strcmp(value, "DLT_LOG_DEBUG") == 0) { config->log_level = 5; } else if (strcmp(value, "DLT_LOG_VERBOSE") == 0) { config->log_level = 6; } else { config->log_level = -1; dlt_log(LOG_ERR, "Invalid log level \n"); return -1; } return 0; } DLT_STATIC int dlt_logstorage_check_reset_loglevel(DltLogStorageFilterConfig *config, char *value) { if (config == NULL) return -1; if (value == NULL) { config->reset_log_level = 0; return -1; } if (strcmp(value, "DLT_LOG_OFF") == 0) { config->reset_log_level = DLT_LOG_OFF; } else if (strcmp(value, "DLT_LOG_FATAL") == 0) { config->reset_log_level = DLT_LOG_FATAL; } else if (strcmp(value, "DLT_LOG_ERROR") == 0) { config->reset_log_level = DLT_LOG_ERROR; } else if (strcmp(value, "DLT_LOG_WARN") == 0) { config->reset_log_level = DLT_LOG_WARN; } else if (strcmp(value, "DLT_LOG_INFO") == 0) { config->reset_log_level = DLT_LOG_INFO; } else if (strcmp(value, "DLT_LOG_DEBUG") == 0) { config->reset_log_level = DLT_LOG_DEBUG; } else if (strcmp(value, "DLT_LOG_VERBOSE") == 0) { config->reset_log_level = DLT_LOG_VERBOSE; } else { config->reset_log_level = -1; dlt_log(LOG_ERR, "Invalid log level \n"); return -1; } return 0; } DLT_STATIC int dlt_logstorage_check_filename(DltLogStorageFilterConfig *config, char *value) { int len; if ((value == NULL) || (strcmp(value, "") == 0)) return -1; if (config->file_name != NULL) { free(config->file_name); config->file_name = NULL; } len = strlen(value); /* do not allow the user to change directory by adding a relative path */ if (strstr(value, "..") == NULL) { config->file_name = calloc((len + 1), sizeof(char)); if (config->file_name == NULL) { dlt_log(LOG_ERR, "Cannot allocate memory for filename\n"); return -1; } strncpy(config->file_name, value, len); } else { dlt_log(LOG_ERR, "Invalid filename, paths not accepted due to security issues\n"); return -1; } return 0; } DLT_STATIC int dlt_logstorage_check_filesize(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; return dlt_logstorage_read_number(&config->file_size, value); } DLT_STATIC int dlt_logstorage_check_nofiles(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; return dlt_logstorage_read_number(&config->num_files, value); } DLT_STATIC int dlt_logstorage_check_gzip_compression(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; int result = dlt_logstorage_read_bool(&config->gzip_compression, value); #ifndef DLT_LOGSTORAGE_USE_GZIP dlt_log(LOG_WARNING, "dlt-daemon not compiled with logstorage gzip support\n"); config->gzip_compression = 0; #endif return result; } DLT_STATIC int dlt_logstorage_check_specificsize(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; return dlt_logstorage_read_number(&config->specific_size, value); } /** * dlt_logstorage_check_sync_strategy * * Evaluate sync strategy. The sync strategy is an optional filter * configuration parameter. * If the given value cannot be associated with a sync strategy, the default * sync strategy will be assigned. * * @param config DltLogStorageFilterConfig * @param value string given in config file * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_check_sync_strategy(DltLogStorageFilterConfig *config, char *value) { if ((config == NULL) || (value == NULL)) return -1; if (strcasestr(value, "ON_MSG") != NULL) { config->sync = DLT_LOGSTORAGE_SYNC_ON_MSG; dlt_log(LOG_DEBUG, "ON_MSG found, ignore other if added\n"); } else { /* ON_MSG not set, combination of cache based strategies possible */ if (strcasestr(value, "ON_DAEMON_EXIT") != NULL) config->sync |= DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT; if (strcasestr(value, "ON_DEMAND") != NULL) config->sync |= DLT_LOGSTORAGE_SYNC_ON_DEMAND; if (strcasestr(value, "ON_DEVICE_DISCONNECT") != NULL) config->sync |= DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT; if (strcasestr(value, "ON_SPECIFIC_SIZE") != NULL) config->sync |= DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE; if (strcasestr(value, "ON_FILE_SIZE") != NULL) config->sync |= DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE; if (config->sync == 0) { dlt_log(LOG_WARNING, "Unknown sync strategies. Set default ON_MSG\n"); config->sync = DLT_LOGSTORAGE_SYNC_ON_MSG; return 1; } } return 0; } /** * dlt_logstorage_check_ecuid * * Evaluate if ECU idenfifier given in config file * * @param config DltLogStorageFilterConfig * @param value string given in config file * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_check_ecuid(DltLogStorageFilterConfig *config, char *value) { int len; if ((config == NULL) || (value == NULL) || (value[0] == '\0')) return -1; if (config->ecuid != NULL) { free(config->ecuid); config->ecuid = NULL; } len = strlen(value); config->ecuid = calloc((len + 1), sizeof(char)); if (config->ecuid == NULL) return -1; strncpy(config->ecuid, value, len); return 0; } DLT_STATIC DltLogstorageFilterConf filter_cfg_entries[DLT_LOGSTORAGE_FILTER_CONF_COUNT] = { [DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME] = { .key = "LogAppName", .func = dlt_logstorage_check_apids, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME] = { .key = "ContextName", .func = dlt_logstorage_check_ctids, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL] = { .key = "LogLevel", .func = dlt_logstorage_check_loglevel, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL] = { .key = NULL, .func = dlt_logstorage_check_reset_loglevel, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_FILE] = { .key = "File", .func = dlt_logstorage_check_filename, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_FILESIZE] = { .key = "FileSize", .func = dlt_logstorage_check_filesize, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_NOFILES] = { .key = "NOFiles", .func = dlt_logstorage_check_nofiles, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR] = { .key = "SyncBehavior", .func = dlt_logstorage_check_sync_strategy, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { .key = "EcuID", .func = dlt_logstorage_check_ecuid, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE] = { .key = "SpecificSize", .func = dlt_logstorage_check_specificsize, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_GZIP_COMPRESSION] = { .key = "GzipCompression", .func = dlt_logstorage_check_gzip_compression, .is_opt = 1 } }; /* */ DLT_STATIC DltLogstorageFilterConf filter_nonverbose_storage_entries[DLT_LOGSTORAGE_FILTER_CONF_COUNT] = { [DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME] = { .key = NULL, .func = dlt_logstorage_check_apids, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME] = { .key = NULL, .func = dlt_logstorage_check_ctids, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL] = { .key = NULL, .func = dlt_logstorage_check_loglevel, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL] = { .key = NULL, .func = NULL, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_FILE] = { .key = "File", .func = dlt_logstorage_check_filename, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_FILESIZE] = { .key = "FileSize", .func = dlt_logstorage_check_filesize, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_NOFILES] = { .key = "NOFiles", .func = dlt_logstorage_check_nofiles, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR] = { .key = NULL, .func = dlt_logstorage_check_sync_strategy, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { .key = "EcuID", .func = dlt_logstorage_check_ecuid, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE] = { .key = NULL, .func = dlt_logstorage_check_specificsize, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_GZIP_COMPRESSION] = { .key = "GzipCompression", .func = dlt_logstorage_check_gzip_compression, .is_opt = 1 } }; DLT_STATIC DltLogstorageFilterConf filter_nonverbose_control_entries[DLT_LOGSTORAGE_FILTER_CONF_COUNT] = { [DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME] = { .key = "LogAppName", .func = dlt_logstorage_check_apids, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME] = { .key = "ContextName", .func = dlt_logstorage_check_ctids, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL] = { .key = "LogLevel", .func = dlt_logstorage_check_loglevel, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL] = { .key = "ResetLogLevel", .func = dlt_logstorage_check_reset_loglevel, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_FILE] = { .key = NULL, .func = dlt_logstorage_check_filename, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_FILESIZE] = { .key = NULL, .func = dlt_logstorage_check_filesize, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_NOFILES] = { .key = NULL, .func = dlt_logstorage_check_nofiles, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR] = { .key = NULL, .func = dlt_logstorage_check_sync_strategy, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { .key = "EcuID", .func = dlt_logstorage_check_ecuid, .is_opt = 0 }, [DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE] = { .key = NULL, .func = dlt_logstorage_check_specificsize, .is_opt = 1 }, [DLT_LOGSTORAGE_FILTER_CONF_GZIP_COMPRESSION] = { .key = "GzipCompression", .func = dlt_logstorage_check_gzip_compression, .is_opt = 1 } }; /** * Check filter configuration parameter is valid. * * @param config DltLogStorageFilterConfig * @param ctype DltLogstorageFilterConfType * @param value specified property value from configuration file * @return 0 on success, -1 otherwise */ DLT_STATIC int dlt_logstorage_check_param(DltLogStorageFilterConfig *config, DltLogstorageFilterConfType ctype, char *value) { if ((config == NULL) || (value == NULL)) return -1; if (ctype < DLT_LOGSTORAGE_FILTER_CONF_COUNT) return filter_cfg_entries[ctype].func(config, value); return -1; } DLT_STATIC int dlt_logstorage_get_filter_section_value(DltConfigFile *config_file, char *sec_name, DltLogstorageFilterConf entry, char *value) { int ret = 0; if ((config_file == NULL) || (sec_name == NULL)) return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; if (entry.key != NULL) { ret = dlt_config_file_get_value(config_file, sec_name, entry.key, value); if ((ret != 0) && (entry.is_opt == 0)) { dlt_vlog(LOG_WARNING, "Invalid configuration in section: %s -> %s : %s\n", sec_name, entry.key, value); return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } if ((ret != 0) && (entry.is_opt == 1)) { dlt_vlog(LOG_DEBUG, "Optional parameter %s not specified\n", entry.key); return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; } } else { return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; } return 0; } DLT_STATIC int dlt_logstorage_get_filter_value(DltConfigFile *config_file, char *sec_name, int index, char *value) { int ret = 0; int config_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION); int storage_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION); int control_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION); if ((config_file == NULL) || (sec_name == NULL)) return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; /* Branch based on section name, no complete string compare needed */ if (strncmp(sec_name, DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION, config_sec_len) == 0) { ret = dlt_logstorage_get_filter_section_value(config_file, sec_name, filter_cfg_entries[index], value); } else if (strncmp(sec_name, DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION, storage_sec_len) == 0) { ret = dlt_logstorage_get_filter_section_value(config_file, sec_name, filter_nonverbose_storage_entries[index], value); } else if ((strncmp(sec_name, DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION, control_sec_len) == 0)) { ret = dlt_logstorage_get_filter_section_value(config_file, sec_name, filter_nonverbose_control_entries[index], value); } else { dlt_log(LOG_ERR, "Error: Section name not valid \n"); ret = DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } return ret; } DLT_STATIC int dlt_logstorage_setup_table(DltLogStorage *handle, DltLogStorageFilterConfig *tmp_data) { int ret = 0; /* depending on the specified strategy set function pointers for * prepare, write and sync */ dlt_logstorage_filter_set_strategy(tmp_data, tmp_data->sync); ret = dlt_logstorage_prepare_table(handle, tmp_data); if (ret != 0) { dlt_vlog(LOG_ERR, "%s Error: Storing filter values failed\n", __func__); ret = DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; } return ret; } /*Return : * DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR - On filter properties or value is not valid * DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR - On error while storing in hash table */ DLT_STATIC int dlt_daemon_offline_setup_filter_properties(DltLogStorage *handle, DltConfigFile *config_file, char *sec_name) { DltLogStorageFilterConfig tmp_data; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN + 1] = { '\0' }; int i = 0; int ret = 0; if ((handle == NULL) || (config_file == NULL) || (sec_name == NULL)) return DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; memset(&tmp_data, 0, sizeof(DltLogStorageFilterConfig)); tmp_data.log_level = DLT_LOG_VERBOSE; tmp_data.reset_log_level = DLT_LOG_OFF; for (i = 0; i < DLT_LOGSTORAGE_FILTER_CONF_COUNT; i++) { ret = dlt_logstorage_get_filter_value(config_file, sec_name, i, value); if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR) return ret; if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE) continue; /* check value and store temporary */ ret = dlt_logstorage_check_param(&tmp_data, i, value); if (ret != 0) { if (tmp_data.apids != NULL) { free(tmp_data.apids); tmp_data.apids = NULL; } if (tmp_data.ctids != NULL) { free(tmp_data.ctids); tmp_data.ctids = NULL; } if (tmp_data.file_name != NULL) { free(tmp_data.file_name); tmp_data.file_name = NULL; } if (tmp_data.working_file_name != NULL) { free(tmp_data.working_file_name); tmp_data.working_file_name = NULL; } if (tmp_data.ecuid != NULL) { free(tmp_data.ecuid); tmp_data.ecuid = NULL; } return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } } /* filter configuration is valid */ ret = dlt_logstorage_setup_table(handle, &tmp_data); if (ret != 0) { dlt_vlog(LOG_ERR, "%s Error: Storing filter values failed\n", __func__); ret = DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; } else { /* move to next free filter configuration, if no error occurred */ handle->num_configs += 1; } /* free tmp_data */ dlt_logstorage_filter_config_free(&tmp_data); return ret; } /** * dlt_logstorage_check_maintain_logstorage_loglevel * * Evaluate to maintain the logstorage loglevel setting. This is an optional * configuration parameter * If the given value cannot be associated with an overwrite, the default value * will be assigned. * * @param config DltLogStorage * @param value string given in config file * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_check_maintain_logstorage_loglevel(DltLogStorage *handle, char *value) { if ((handle == NULL) || (value == NULL)) { return -1; } if ((strncmp(value, "OFF", 3) == 0) || (strncmp(value, "0", 1) == 0)) { handle->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_OFF; } else if ((strncmp(value, "ON", 2) == 0) || (strncmp(value, "1", 1) == 0)) { handle->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_ON; } else { dlt_vlog(LOG_ERR, "Wrong value for Maintain logstorage loglevel section name: %s\n", value); handle->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_ON; return -1; } return 0; } DLT_STATIC DltLogstorageGeneralConf general_cfg_entries[DLT_LOGSTORAGE_GENERAL_CONF_COUNT] = { [DLT_LOGSTORAGE_GENERAL_CONF_MAINTAIN_LOGSTORAGE_LOGLEVEL] = { .key = "MaintainLogstorageLogLevel", .func = dlt_logstorage_check_maintain_logstorage_loglevel, .is_opt = 1 } }; /** * Check if DltLogstorage General configuration parameter is valid. * * @param handle pointer to DltLogstorage structure * @param ctype Logstorage general configuration type * @param value specified property value from configuration file * @return 0 on success, -1 otherwise */ DLT_STATIC int dlt_logstorage_check_general_param(DltLogStorage *handle, DltLogstorageGeneralConfType ctype, char *value) { if ((handle == NULL) || (value == NULL)) { return -1; } if (ctype < DLT_LOGSTORAGE_GENERAL_CONF_COUNT) { return general_cfg_entries[ctype].func(handle, value); } return -1; } DLT_STATIC int dlt_daemon_setup_general_properties(DltLogStorage *handle, DltConfigFile *config_file, char *sec_name) { DltLogstorageGeneralConfType type = DLT_LOGSTORAGE_GENERAL_CONF_MAINTAIN_LOGSTORAGE_LOGLEVEL; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = {0}; if ((handle == NULL) || (config_file == NULL) || (sec_name == NULL)) { return -1; } for ( ; type < DLT_LOGSTORAGE_GENERAL_CONF_COUNT ; type++) { if (dlt_config_file_get_value(config_file, sec_name, general_cfg_entries[type].key, value) == 0) { if (dlt_logstorage_check_general_param(handle, type, value) != 0) { dlt_vlog(LOG_WARNING, "General parameter %s [%s] is invalid\n", general_cfg_entries[type].key, value); } } else { if (general_cfg_entries[type].is_opt == 1) { dlt_vlog(LOG_DEBUG, "Optional General parameter %s not given\n", general_cfg_entries[type].key); } else { dlt_vlog(LOG_ERR, "General parameter %s not given\n", general_cfg_entries[type].key); return -1; } } } return 0; } /** * dlt_logstorage_store_filters * * This function reads the filter keys and values * and stores them into the hash map * * @param handle DLT Logstorage handle * @param config_file_name Configuration file name * @return 0 on success, -1 on error, 1 on warning * */ DLT_STATIC int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name) { DltConfigFile *config = NULL; int sec = 0; int num_sec = 0; int ret = 0; /* we have to make sure that this function returns success if atleast one * filter configuration is valid and stored */ int valid = -1; if (config_file_name == NULL) { dlt_vlog(LOG_ERR, "%s unexpected parameter received\n", __func__); return -1; } config = dlt_config_file_init(config_file_name); if (config == NULL) { dlt_log(LOG_CRIT, "Failed to open filter configuration file\n"); return -1; } handle->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_UNDEF; dlt_config_file_get_num_sections(config, &num_sec); for (sec = 0; sec < num_sec; sec++) { char sec_name[DLT_CONFIG_FILE_ENTRY_MAX_LEN + 1]; if (dlt_config_file_get_section_name(config, sec, sec_name) == -1) { dlt_log(LOG_CRIT, "Failed to read section name\n"); dlt_config_file_release(config); return -1; } if (strstr(sec_name, GENERAL_BASE_NAME) != NULL) { if (dlt_daemon_setup_general_properties(handle, config, sec_name) == -1) { dlt_log(LOG_CRIT, "General configuration is invalid\n"); continue; } } else if (dlt_logstorage_validate_filter_name(sec_name) == 0) { ret = dlt_daemon_offline_setup_filter_properties(handle, config, sec_name); if (ret == DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR) { break; } else if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR) { valid = 1; dlt_vlog(LOG_WARNING, "%s filter configuration is invalid \n", sec_name); /* Continue reading next filter section */ continue; } else /* Filter properties read and stored successfuly */ if (valid != 1) valid = 0; } else { /* unknown section */ dlt_vlog(LOG_WARNING, "Unknown section: %s", sec_name); } } dlt_config_file_release(config); return valid; } /** * dlt_logstorage_load_config * * Read dlt_logstorage.conf file and setup filters in hash table * Hash table key consists of "APID:CTID", e.g "APP1:CTX1". If * wildcards used for application id or context id, the hash table * key consists of none wildcard value, e.g. apid=.*, cxid=CTX1 * results in "CTX1". * * Combination of two wildcards is not allowed if ECUID is not specified. * * @param handle DLT Logstorage handle * @return 0 on success, -1 on error, 1 on warning */ DLT_STATIC int dlt_logstorage_load_config(DltLogStorage *handle) { char config_file_name[PATH_MAX] = {0}; int ret = 0; /* Check if handle is NULL or already initialized or already configured */ if ((handle == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED)) return -1; /* Check if this device config was already setup */ if (handle->config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { dlt_vlog(LOG_ERR, "%s: Device already configured. Send disconnect first.\n", __func__); return -1; } if (snprintf(config_file_name, PATH_MAX, "%s/%s", handle->device_mount_point, DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME) < 0) { dlt_log(LOG_ERR, "Creating configuration file path string failed\n"); return -1; } config_file_name[PATH_MAX - 1] = 0; ret = dlt_logstorage_store_filters(handle, config_file_name); if (ret == 1) { handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; return 1; } else if (ret != 0) { dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Storing filters failed\n"); return -1; } handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; return 0; } /** * dlt_logstorage_device_connected * * Initializes DLT Offline Logstorage with respect to device status * * @param handle DLT Logstorage handle * @param mount_point Device mount path * @return 0 on success, -1 on error, 1 on warning */ int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point) { if ((handle == NULL) || (mount_point == NULL)) { dlt_log(LOG_ERR, "Handle error \n"); return -1; } if (handle->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { dlt_log(LOG_WARNING, "Device already connected. Send disconnect, connect request\n"); dlt_logstorage_device_disconnected( handle, DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); } strncpy(handle->device_mount_point, mount_point, DLT_MOUNT_PATH_MAX); handle->device_mount_point[DLT_MOUNT_PATH_MAX] = 0; handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle->config_status = 0; handle->write_errors = 0; handle->num_configs = 0; handle->newest_file_list = NULL; /* Setup logstorage with config file settings */ return dlt_logstorage_load_config(handle); } /** * dlt_logstorage_device_disconnected * * De-Initializes DLT Offline Logstorage with respect to device status * * @param handle DLT Logstorage handle * @param reason Reason for disconnect * @return 0 on success, -1 on error * */ int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason) { DltNewestFileName *tmp = NULL; if (handle == NULL) return -1; /* If configuration loading was done, free it */ if (handle->config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) dlt_logstorage_free(handle, reason); /* Reset all device status */ memset(handle->device_mount_point, 0, sizeof(char) * (DLT_MOUNT_PATH_MAX + 1)); handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED; handle->config_status = 0; handle->write_errors = 0; handle->num_configs = 0; while (handle->newest_file_list) { tmp = handle->newest_file_list; handle->newest_file_list = tmp->next; if (tmp->file_name) { free(tmp->file_name); tmp->file_name = NULL; } if (tmp->newest_file) { free(tmp->newest_file); tmp->newest_file = NULL; } free(tmp); tmp = NULL; } return 0; } /** * dlt_logstorage_get_loglevel_by_key * * Obtain the log level for the provided key * This function can be used to obtain log level when the actual * key stored in the Hash map is availble with the caller * * @param handle DltLogstorage handle * @param key key to search for in Hash MAP * @return log level on success:, -1 on error */ int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key) { DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; int num_configs = 0; int i = 0; int log_level = 0; /* Check if handle is NULL,already initialized or already configured */ if ((handle == NULL) || (key == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) return -1; num_configs = dlt_logstorage_list_find(key, &(handle->config_list), config); if (num_configs == 0) { dlt_vlog(LOG_WARNING, "Configuration for key [%s] not found!\n", key); return -1; } else if (num_configs == 1) { if (config[0] != NULL) { log_level = config[0]->log_level; } } else { /** * Multiple configurations found, raise a warning to the user and go * for the more verbose one. */ dlt_vlog(LOG_WARNING, "Multiple configuration for key [%s] found," " return the highest log level!\n", key); for (i = 0; i < num_configs; i++) { if ((config[i] != NULL) && (config[i]->log_level > log_level)) { log_level = config[i]->log_level; } } } return log_level; } /** * dlt_logstorage_get_config * * Obtain the configuration data of all filters for provided apid and ctid * * @param handle DltLogStorage handle * @param config [out] Pointer to array of filter configurations * @param apid application id * @param ctid context id * @param ecuid ecu id * @return number of configurations found */ int dlt_logstorage_get_config(DltLogStorage *handle, DltLogStorageFilterConfig **config, char *apid, char *ctid, char *ecuid) { DltLogStorageFilterConfig **cur_config_ptr = NULL; char key[DLT_CONFIG_FILE_SECTIONS_MAX][DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN] = { { '\0' }, { '\0' }, { '\0' } }; int i = 0; int apid_len = 0; int ctid_len = 0; int ecuid_len = 0; int num_configs = 0; int num = 0; /* Check if handle is NULL,already initialized or already configured */ if ((handle == NULL) || (config == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) || (ecuid == NULL)) return 0; /* Prepare possible keys with * Possible combinations are * ecu:: * ecu:apid:ctid * :apid:ctid * ecu::ctid * ecu:apid: * ::ctid * :apid: */ ecuid_len = strlen(ecuid); if (ecuid_len > DLT_ID_SIZE) ecuid_len = DLT_ID_SIZE; if ((apid == NULL) && (ctid == NULL)) { /* ecu:: */ strncpy(key[0], ecuid, ecuid_len); strncat(key[0], ":", 1); strncat(key[0], ":", 1); num_configs = dlt_logstorage_list_find(key[0], &(handle->config_list), config); return num_configs; } apid_len = strlen(apid); if (apid_len > DLT_ID_SIZE) apid_len = DLT_ID_SIZE; ctid_len = strlen(ctid); if (ctid_len > DLT_ID_SIZE) ctid_len = DLT_ID_SIZE; /* :apid: */ strncpy(key[0], ":", 1); strncat(key[0], apid, apid_len); strncat(key[0], ":", 1); /* ::ctid */ strncpy(key[1], ":", 1); strncat(key[1], ":", 1); strncat(key[1], ctid, ctid_len); /* :apid:ctid */ strncpy(key[2], ":", 1); strncat(key[2], apid, apid_len); strncat(key[2], ":", 1); strncat(key[2], ctid, ctid_len); /* ecu:apid:ctid */ strncpy(key[3], ecuid, ecuid_len); strncat(key[3], ":", 1); strncat(key[3], apid, apid_len); strncat(key[3], ":", 1); strncat(key[3], ctid, ctid_len); /* ecu:apid: */ strncpy(key[4], ecuid, ecuid_len); strncat(key[4], ":", 1); strncat(key[4], apid, apid_len); strncat(key[4], ":", 1); /* ecu::ctid */ strncpy(key[5], ecuid, ecuid_len); strncat(key[5], ":", 1); strncat(key[5], ":", 1); strncat(key[5], ctid, ctid_len); /* ecu:: */ strncpy(key[6], ecuid, ecuid_len); strncat(key[6], ":", 1); strncat(key[6], ":", 1); /* Search the list three times with keys as -apid: , :ctid and apid:ctid */ for (i = 0; i < DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_KEYS; i++) { cur_config_ptr = &config[num_configs]; num = dlt_logstorage_list_find(key[i], &(handle->config_list), cur_config_ptr); num_configs += num; /* If all filter configurations matched, stop and return */ if (num_configs == handle->num_configs) { break; } } return num_configs; } /** * dlt_logstorage_filter * * Check if log message need to be stored in a certain device based on filter * config * - get all DltLogStorageFilterConfig from hash table possible by given * apid/ctid (apid:, :ctid, apid:ctid * - for each found structure, compare message log level with configured one * * @param handle DltLogStorage handle * @param config Pointer to array of filter configurations * @param apid application id * @param ctid context id * @param log_level Log level of message * @param ecuid EcuID given in the message * @return number of found configurations */ DLT_STATIC int dlt_logstorage_filter(DltLogStorage *handle, DltLogStorageFilterConfig **config, char *apid, char *ctid, char *ecuid, int log_level) { int i = 0; int num = 0; if ((handle == NULL) || (config == NULL) || (ecuid == NULL)) return -1; /* filter on names: find DltLogStorageFilterConfig structures */ num = dlt_logstorage_get_config(handle, config, apid, ctid, ecuid); if (num == 0) { dlt_log(LOG_DEBUG, "No valid filter configuration found\n"); return 0; } for (i = 0 ; i < num ; i++) { if (config[i] == NULL) continue; /* filter on log level */ if (log_level > config[i]->log_level) { config[i] = NULL; continue; } /* filter on ECU id only if EcuID is set */ if (config[i]->ecuid != NULL) { if (strncmp(ecuid, config[i]->ecuid, DLT_ID_SIZE) != 0) config[i] = NULL; } } return num; } /** * dlt_logstorage_write * * Write a message to one or more configured log files, based on filter * configuration. * * @param handle DltLogStorage handle * @param uconfig User configurations for log file * @param data1 Data buffer of message header * @param size1 Size of message header buffer * @param data2 Data buffer of extended message body * @param size2 Size of extended message body * @param data3 Data buffer of message body * @param size3 Size of message body * @return 0 on success or write errors < max write errors, -1 on error */ int dlt_logstorage_write(DltLogStorage *handle, DltLogStorageUserConfig *uconfig, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3) { DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; int i = 0; int ret = 0; int num = 0; int err = 0; /* data2 contains DltStandardHeader, DltStandardHeaderExtra and * DltExtendedHeader. We are interested in ecuid, apid, ctid and loglevel */ DltExtendedHeader *extendedHeader = NULL; DltStandardHeaderExtra *extraHeader = NULL; DltStandardHeader *standardHeader = NULL; unsigned int standardHeaderExtraLen = sizeof(DltStandardHeaderExtra); unsigned int header_len = 0; DltNewestFileName *tmp = NULL; int found = 0; int log_level = -1; if ((handle == NULL) || (uconfig == NULL) || (data1 == NULL) || (data2 == NULL) || (data3 == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) return 0; /* Calculate real length of DltStandardHeaderExtra */ standardHeader = (DltStandardHeader *)data2; if (!DLT_IS_HTYP_WEID(standardHeader->htyp)) standardHeaderExtraLen -= DLT_ID_SIZE; if (!DLT_IS_HTYP_WSID(standardHeader->htyp)) standardHeaderExtraLen -= DLT_SIZE_WSID; if (!DLT_IS_HTYP_WTMS(standardHeader->htyp)) standardHeaderExtraLen -= DLT_SIZE_WTMS; extraHeader = (DltStandardHeaderExtra *)(data2 + sizeof(DltStandardHeader)); if (DLT_IS_HTYP_UEH(standardHeader->htyp)) { header_len = sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + standardHeaderExtraLen; /* check if size2 is big enough to contain expected DLT message header */ if ((unsigned int)size2 < header_len) { dlt_log(LOG_ERR, "DLT message header is too small\n"); return 0; } extendedHeader = (DltExtendedHeader *)(data2 + sizeof(DltStandardHeader) + standardHeaderExtraLen); log_level = DLT_GET_MSIN_MTIN(extendedHeader->msin); /* check if log message need to be stored in a certain device based on * filter configuration */ num = dlt_logstorage_filter(handle, config, extendedHeader->apid, extendedHeader->ctid, extraHeader->ecu, log_level); if ((num == 0) || (num == -1)) { dlt_log(LOG_DEBUG, "No valid filter configuration found!\n"); return 0; } } else { header_len = sizeof(DltStandardHeader) + standardHeaderExtraLen; /* check if size2 is big enough to contain expected DLT message header */ if ((unsigned int)size2 < header_len) { dlt_log(LOG_ERR, "DLT message header is too small (without extended header)\n"); return 0; } log_level = DLT_LOG_VERBOSE; /* check if log message need to be stored in a certain device based on * filter configuration */ num = dlt_logstorage_filter(handle, config, NULL, NULL, extraHeader->ecu, log_level); if ((num == 0) || (num == -1)) { dlt_log(LOG_DEBUG, "No valid filter configuration found!\n"); return 0; } } /* store log message in every found filter */ for (i = 0; i < num; i++) { if (config[i] == NULL) continue; /* If file name is not present, the filter is non verbose control filter * hence skip storing */ if (config[i]->file_name == NULL) continue; tmp = handle->newest_file_list; while (tmp) { if (strcmp(tmp->file_name, config[i]->file_name) == 0) { found = 1; break; } else { tmp = tmp->next; } } if (!found) { dlt_vlog(LOG_ERR, "Cannot find out record for filename [%s]\n", config[i]->file_name); return -1; } /* prepare log file (create and/or open)*/ if (config[i]->ecuid == NULL) dlt_vlog(LOG_DEBUG, "%s: ApId-CtId-EcuId [%s]-[%s]-[]\n", __func__, config[i]->apids, config[i]->ctids); else dlt_vlog(LOG_DEBUG, "%s: ApId-CtId-EcuId [%s]-[%s]-[%s]\n", __func__, config[i]->apids, config[i]->ctids, config[i]->ecuid); ret = config[i]->dlt_logstorage_prepare(config[i], uconfig, handle->device_mount_point, size1 + size2 + size3, tmp); if (config[i]->sync == DLT_LOGSTORAGE_SYNC_UNSET || config[i]->sync == DLT_LOGSTORAGE_SYNC_ON_MSG) { /* It is abnormal if working file is still NULL after preparation. */ if (!config[i]->working_file_name) { dlt_vlog(LOG_ERR, "Failed to prepare working file for %s\n", config[i]->file_name); return -1; } else { /* After preparation phase, update newest file info * it means there is new file created, newest file info must be updated. */ if (tmp->newest_file) { free(tmp->newest_file); tmp->newest_file = NULL; } tmp->newest_file = strdup(config[i]->working_file_name); tmp->wrap_id = config[i]->wrap_id; } } if (ret == 0) { /* log data (write) */ ret = config[i]->dlt_logstorage_write(config[i], uconfig, handle->device_mount_point, data1, size1, data2, size2, data3, size3); if (ret == 0) { /* In case of behavior CACHED_BASED, the newest file info * must be updated right after writing phase. * That is because in writing phase, it could also perform * sync to file which actions could impact to the log file info. * If both working file name and newest file name are unavailable, * it means the sync to file is not performed yet, wait for next times. */ if (config[i]->sync != DLT_LOGSTORAGE_SYNC_ON_MSG && config[i]->sync != DLT_LOGSTORAGE_SYNC_UNSET) { if (config[i]->working_file_name) { if (tmp->newest_file) { free(tmp->newest_file); tmp->newest_file = NULL; } tmp->newest_file = strdup(config[i]->working_file_name); tmp->wrap_id = config[i]->wrap_id; } } /* flush to be sure log is stored on device */ ret = config[i]->dlt_logstorage_sync(config[i], uconfig, handle->device_mount_point, DLT_LOGSTORAGE_SYNC_ON_MSG); if (ret != 0) dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to sync.\n"); } else { handle->write_errors += 1; if (handle->write_errors >= DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS) err = -1; dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to write.\n"); } } else { dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to prepare.\n"); } } return err; } /** * dlt_logstorage_sync_caches * * Write Cache data to file * * @param handle DltLogStorage handle * @return 0 on success, -1 on error */ int dlt_logstorage_sync_caches(DltLogStorage *handle) { DltLogStorageFilterList **tmp = NULL; if (handle == NULL) return -1; tmp = &(handle->config_list); while (*(tmp) != NULL) { if ((*tmp)->data != NULL) { if ((*tmp)->data->dlt_logstorage_sync((*tmp)->data, &handle->uconfig, handle->device_mount_point, DLT_LOGSTORAGE_SYNC_ON_DEMAND) != 0) dlt_vlog(LOG_ERR, "%s: Sync failed. Continue with next cache.\n", __func__); } tmp = &(*tmp)->next; } return 0; } dlt-daemon-2.18.10/src/offlinelogstorage/dlt_offline_logstorage.h000066400000000000000000000400501446635226000251020ustar00rootroot00000000000000/** * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Syed Hameed ADIT 2013 - 2015 * \author Christoph Lipka ADIT 2015 * * \file: dlt_offline_logstorage.h * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_offline_logstorage.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Syed Hameed shameed@jp.adit-jv.com ** ** Christoph Lipka clipka@jp.adit-jv.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** sh Syed Hameed ADIT ** ** cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef DLT_OFFLINE_LOGSTORAGE_H #define DLT_OFFLINE_LOGSTORAGE_H #include #include #include #include "dlt_common.h" #include "dlt-daemon_cfg.h" #include "dlt_config_file_parser.h" #define DLT_OFFLINE_LOGSTORAGE_MAXIDS 100 /* Maximum entries for each apids and ctids */ #define DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_KEYS 7 /* Max number of possible keys when searching for */ #define DLT_OFFLINE_LOGSTORAGE_INIT_DONE 1 /* For device configuration status */ #define DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED 1 #define DLT_OFFLINE_LOGSTORAGE_FREE 0 #define DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED 0 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE 1 #define DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES 2 /* sync logstorage caches */ #define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN 15 /* Maximum size for key */ #define DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN 50 /* Maximum file name length of the log file */ #define DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN 4 #define DLT_OFFLINE_LOGSTORAGE_GZ_FILE_EXTENSION_LEN 7 #define DLT_OFFLINE_LOGSTORAGE_INDEX_LEN 3 #define DLT_OFFLINE_LOGSTORAGE_MAX_INDEX 999 #define DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN 16 #define DLT_OFFLINE_LOGSTORAGE_INDEX_OFFSET (DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + \ DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + \ DLT_OFFLINE_LOGSTORAGE_INDEX_LEN) #define DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN (DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + \ DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + \ DLT_OFFLINE_LOGSTORAGE_INDEX_LEN + \ DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + 1) #define DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN 50 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME "dlt_logstorage.conf" /* +3 because of device number and \0 */ #define DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN (DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + \ DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 3) #define DLT_OFFLINE_LOGSTORAGE_MAX(A, B) ((A) > (B) ? (A) : (B)) #define DLT_OFFLINE_LOGSTORAGE_MIN(A, B) ((A) < (B) ? (A) : (B)) #define DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS 5 #define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_NUM 8 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION "FILTER" #define DLT_OFFLINE_LOGSTORAGE_GENERAL_CONFIG_SECTION "GENERAL" #define DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION "NON-VERBOSE-STORAGE-FILTER" #define DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION "NON-VERBOSE-LOGLEVEL-CTRL" /* Offline Logstorage sync strategies */ #define DLT_LOGSTORAGE_SYNC_ON_ERROR -1 /* error case */ #define DLT_LOGSTORAGE_SYNC_UNSET 0 /* strategy not set */ #define DLT_LOGSTORAGE_SYNC_ON_MSG 1 /* default, on message sync */ #define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT (1 << 1) /* sync on daemon exit */ #define DLT_LOGSTORAGE_SYNC_ON_DEMAND (1 << 2) /* sync on demand */ #define DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT (1 << 3) /* sync on device disconnect*/ #define DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE (1 << 4) /* sync on after specific size */ #define DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE (1 << 5) /* sync on file size reached */ #define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s) ((S)&(s)) /* logstorage max cache */ extern unsigned int g_logstorage_cache_max; /* current logstorage cache size */ extern unsigned int g_logstorage_cache_size; typedef struct { unsigned int offset; /* current write offset */ unsigned int wrap_around_cnt; /* wrap around counter */ unsigned int last_sync_offset; /* last sync position */ unsigned int end_sync_offset; /* end position of previous round */ } DltLogStorageCacheFooter; typedef struct { /* File name user configurations */ int logfile_timestamp; /* Timestamp set/reset */ char logfile_delimiter; /* Choice of delimiter */ unsigned int logfile_maxcounter; /* Maximum file index counter */ unsigned int logfile_counteridxlen; /* File index counter length */ } DltLogStorageUserConfig; typedef struct DltLogStorageFileList { /* List for filenames */ char *name; /* Filename */ unsigned int idx; /* File index */ struct DltLogStorageFileList *next; /* Pointer to next */ } DltLogStorageFileList; typedef struct DltNewestFileName DltNewestFileName; struct DltNewestFileName { char *file_name; /* The unique name of file in whole a dlt_logstorage.conf */ char *newest_file; /* The real newest name of file which is associated with filename.*/ unsigned int wrap_id; /* Identifier of wrap around happened for this file_name */ DltNewestFileName *next; /* Pointer to next */ }; typedef struct DltLogStorageFilterConfig DltLogStorageFilterConfig; struct DltLogStorageFilterConfig { /* filter section */ char *apids; /* Application IDs configured for filter */ char *ctids; /* Context IDs configured for filter */ int log_level; /* Log level number configured for filter */ int reset_log_level; /* reset Log level to be sent on disconnect */ char *file_name; /* File name for log storage configured for filter */ char *working_file_name; /* Current open log file name */ unsigned int wrap_id; /* Identifier of wrap around happened for this filter */ unsigned int file_size; /* MAX File size of storage file configured for filter */ unsigned int num_files; /* MAX number of storage files configured for filters */ int sync; /* Sync strategy */ char *ecuid; /* ECU identifier */ unsigned int gzip_compression; /* Toggle if log files should be gzip compressed */ /* callback function for filter configurations */ int (*dlt_logstorage_prepare)(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size, DltNewestFileName *newest_file_info); int (*dlt_logstorage_write)(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3); /* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback * is called on message received */ int (*dlt_logstorage_sync)(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *uconfig, char *dev_path, int status); FILE *log; /* current open log file */ int fd; /* The file descriptor for the active log file */ #ifdef DLT_LOGSTORAGE_USE_GZIP gzFile gzlog; /* current open gz log file */ #endif void *cache; /* log data cache */ unsigned int specific_size; /* cache size used for specific_size sync strategy */ unsigned int current_write_file_offset; /* file offset for specific_size sync strategy */ DltLogStorageFileList *records; /* File name list */ }; typedef struct DltLogStorageFilterList DltLogStorageFilterList; struct DltLogStorageFilterList { char *key_list; /* List of key */ int num_keys; /* Number of keys */ DltLogStorageFilterConfig *data; /* Filter data */ DltLogStorageFilterList *next; /* Pointer to next */ }; typedef struct { DltLogStorageFilterList *config_list; /* List of all filters */ DltLogStorageUserConfig uconfig; /* User configurations for file name*/ int num_configs; /* Number of configs */ char device_mount_point[DLT_MOUNT_PATH_MAX + 1]; /* Device mount path */ unsigned int connection_type; /* Type of connection */ unsigned int config_status; /* Status of configuration */ int write_errors; /* number of write errors */ DltNewestFileName *newest_file_list; /* List of newest file name */ int maintain_logstorage_loglevel; /* Permission to maintain the logstorage loglevel*/ } DltLogStorage; typedef struct { char *key; /* The configuration key */ int (*func)(DltLogStorage *handle, char *value); /* conf handler */ int is_opt; /* If configuration is optional or not */ } DltLogstorageGeneralConf; typedef enum { DLT_LOGSTORAGE_GENERAL_CONF_MAINTAIN_LOGSTORAGE_LOGLEVEL = 1, DLT_LOGSTORAGE_GENERAL_CONF_COUNT } DltLogstorageGeneralConfType; typedef struct { char *key; /* Configuration key */ int (*func)(DltLogStorageFilterConfig *config, char *value); /* conf handler */ int is_opt; /* If configuration is optional or not */ } DltLogstorageFilterConf; typedef enum { DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME = 0, DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME, DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL, DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL, DLT_LOGSTORAGE_FILTER_CONF_FILE, DLT_LOGSTORAGE_FILTER_CONF_FILESIZE, DLT_LOGSTORAGE_FILTER_CONF_NOFILES, DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR, DLT_LOGSTORAGE_FILTER_CONF_ECUID, DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE, DLT_LOGSTORAGE_FILTER_CONF_GZIP_COMPRESSION, DLT_LOGSTORAGE_FILTER_CONF_COUNT } DltLogstorageFilterConfType; /** * dlt_logstorage_device_connected * * Initializes DLT Offline Logstorage with respect to device status * * * @param handle DLT Logstorage handle * @param mount_point Device mount path * @return 0 on success, -1 on error */ int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point); /** * dlt_logstorage_device_disconnected * De-Initializes DLT Offline Logstorage with respect to device status * * @param handle DLT Logstorage handle * @param reason Reason for device disconnection * @return 0 on success, -1 on error */ int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason); /** * dlt_logstorage_get_config * * Obtain the configuration data of all filters for provided apid and ctid * For a given apid and ctid, there can be 3 possiblities of configuration * data available in the Hash map, this function will return the address * of configuration data for all these 3 combinations * * @param handle DltLogStorage handle * @param config Pointer to array of filter configurations * @param apid application id * @param ctid context id * @param ecuid ecu id * @return number of found configurations */ int dlt_logstorage_get_config(DltLogStorage *handle, DltLogStorageFilterConfig **config, char *apid, char *ctid, char *ecuid); /** * dlt_logstorage_get_loglevel_by_key * * Obtain the log level for the provided key * This function can be used to obtain log level when the actual * key stored in the Hash map is available with the caller * * @param handle DltLogstorage handle * @param key key to search for in Hash MAP * @return log level on success:, -1 on error */ int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); /** * dlt_logstorage_write * * Write a message to one or more configured log files, based on filter * configuration. * * @param handle DltLogStorage handle * @param uconfig User configurations for log file * @param data1 Data buffer of message header * @param size1 Size of message header buffer * @param data2 Data buffer of extended message body * @param size2 Size of extended message body * @param data3 Data buffer of message body * @param size3 Size of message body * @return 0 on success or write errors < max write errors, -1 on error */ int dlt_logstorage_write(DltLogStorage *handle, DltLogStorageUserConfig *uconfig, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3); /** * dlt_logstorage_sync_caches * * Sync all caches inside the specified logstorage device. * * @param handle DltLogStorage handle * @return 0 on success, -1 otherwise */ int dlt_logstorage_sync_caches(DltLogStorage *handle); #endif /* DLT_OFFLINE_LOGSTORAGE_H */ dlt-daemon-2.18.10/src/offlinelogstorage/dlt_offline_logstorage_behavior.c000066400000000000000000001404261446635226000267640ustar00rootroot00000000000000/** * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality source file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka ADIT 2015 * \author Syed Hameed ADIT 2015 * * \file: dlt_offline_logstorage_behavior.c * For further information see http://www.covesa.org/. */ #include #include #include #include #include #include #include #include #include #include "dlt_common.h" #include "dlt_offline_logstorage.h" #include "dlt_offline_logstorage_behavior.h" #include "dlt_offline_logstorage_behavior_internal.h" unsigned int g_logstorage_cache_size; /** * dlt_logstorage_concat * * Concatenates two strings but keeps the size of the result less then dst_size. * * @param dst The destination string * @param src The source string to concat */ DLT_STATIC void dlt_logstorage_concat_logfile_name(char *log_file_name, const char *append) { size_t dst_len = strnlen(log_file_name, DLT_MOUNT_PATH_MAX); size_t src_len = strlen(append); if (dst_len < DLT_MOUNT_PATH_MAX) { size_t rem_len = DLT_MOUNT_PATH_MAX - dst_len - 1; strncat(log_file_name, append, rem_len); } else { dlt_vlog(LOG_ERR, "Log file name reached max len: %s [%d]\n", log_file_name, DLT_MOUNT_PATH_MAX); } if (src_len + dst_len >= DLT_MOUNT_PATH_MAX) { dlt_vlog(LOG_ERR, "Log file path too long. Truncated: %s", log_file_name); } } /** * dlt_logstorage_log_file_name * * Create log file name in the form configured by the user * \\\\\.dlt * * filename: given in configuration file * delimiter: Punctuation characters (configured in dlt.conf) * timestamp: yyyy-mm-dd-hh-mm-ss (enabled/disabled in dlt.conf) * index: Index len depends on wrap around value in dlt.conf * ex: wrap around = 99, index will 01..99 * * @param log_file_name contains complete logfile name * @param file_config User configurations for log file * @param name file name given in configuration file * @param idx continous index of log files * @ return None */ void dlt_logstorage_log_file_name(char *log_file_name, DltLogStorageUserConfig *file_config, DltLogStorageFilterConfig *filter_config, int idx) { if ((log_file_name == NULL) || (file_config == NULL) || (filter_config == NULL)) return; char file_index[10] = { '\0' }; /* create log file name */ memset(log_file_name, '\0', DLT_MOUNT_PATH_MAX * sizeof(char)); dlt_logstorage_concat_logfile_name(log_file_name, filter_config->file_name); dlt_logstorage_concat_logfile_name(log_file_name, &file_config->logfile_delimiter); snprintf(file_index, 10, "%d", idx); if (file_config->logfile_maxcounter != UINT_MAX) { /* Setup 0's to be appended in file index until max index len*/ unsigned int digit_idx = 0; unsigned int i = 0; snprintf(file_index, 10, "%d", idx); digit_idx = strlen(file_index); if (file_config->logfile_counteridxlen > digit_idx) { for (i = 0 ; i < (file_config->logfile_counteridxlen - digit_idx) ; i++) dlt_logstorage_concat_logfile_name(log_file_name, "0"); } } dlt_logstorage_concat_logfile_name(log_file_name, file_index); /* Add time stamp if user has configured */ if (file_config->logfile_timestamp) { char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = { 0 }; time_t t = time(NULL); struct tm tm_info; ssize_t n = 0; tzset(); localtime_r(&t, &tm_info); n = snprintf(stamp, DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1, "%c%04d%02d%02d-%02d%02d%02d", file_config->logfile_delimiter, 1900 + tm_info.tm_year, 1 + tm_info.tm_mon, tm_info.tm_mday, tm_info.tm_hour, tm_info.tm_min, tm_info.tm_sec); if (n < 0 || (size_t)n > (DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1)) { dlt_vlog(LOG_WARNING, "%s: snprintf truncation %s\n", __func__, stamp); } dlt_logstorage_concat_logfile_name(log_file_name, stamp); } dlt_logstorage_concat_logfile_name(log_file_name, ".dlt"); if (filter_config->gzip_compression) { dlt_logstorage_concat_logfile_name(log_file_name, ".gz"); } } /** * dlt_logstorage_sort_file_name * * Sort the filenames with index based ascending order (bubble sort) * * @param head Log filename list * @ return The last (biggest) index */ unsigned int dlt_logstorage_sort_file_name(DltLogStorageFileList **head) { int done = 0; unsigned int max_idx = 0; if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL)) return 0; while (!done) { /* "source" of the pointer to the current node in the list struct */ DltLogStorageFileList **pv = head; DltLogStorageFileList *nd = *head; /* local iterator pointer */ DltLogStorageFileList *nx = (*head)->next; /* local next pointer */ done = 1; while (nx) { max_idx = nx->idx; if (nd->idx > nx->idx) { max_idx = nd->idx; nd->next = nx->next; nx->next = nd; *pv = nx; done = 0; } pv = &nd->next; nd = nx; nx = nx->next; } } return max_idx; } /** * dlt_logstorage_rearrange_file_name * * Rearrange the filenames in the order of latest and oldest * * @param head Log filename list * @ return None */ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) { DltLogStorageFileList *n_prev = NULL; DltLogStorageFileList *tail = NULL; DltLogStorageFileList *wrap_pre = NULL; DltLogStorageFileList *wrap_post = NULL; DltLogStorageFileList *n = NULL; if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL)) return; if ((*head)->idx != 1) { /* Do not sort */ return; } for (n = *head; n != NULL; n = n->next) { /* Compare the diff between n->idx and n_prev->idx only if * wrap_post and wrap_pre are not set yet. Otherwise continue the loop * until the tail */ if (n && n_prev && !wrap_post && !wrap_pre) { if ((n->idx - n_prev->idx) != 1) { wrap_post = n; wrap_pre = n_prev; } } n_prev = n; } tail = n_prev; if (wrap_post && wrap_pre) { wrap_pre->next = NULL; tail->next = *head; *head = wrap_post; } } /** * dlt_logstorage_get_idx_of_log_file * * Extract index of log file name passed as input argument * * @param file_config User configurations for log file * @param config Filter configurations for log file * @param file file name to extract the index from * @return index on success, -1 if no index is found */ unsigned int dlt_logstorage_get_idx_of_log_file(DltLogStorageUserConfig *file_config, DltLogStorageFilterConfig *config, char *file) { if (file_config == NULL || config == NULL || file == NULL) return -1; int idx = 0; int basename_len; char *sptr, *eptr; /* Find the next delimiter after the first one: * Eg. base-log-name__.dlt * ^ ^ * | | * From here --+ +--- To this position */ basename_len = strlen(config->file_name); sptr = file + basename_len + 1; eptr = strchr(file + basename_len + 1, file_config->logfile_delimiter); idx = strtol(sptr, &eptr, 10); if (idx == 0) dlt_log(LOG_ERR, "Unable to calculate index from log file name. Reset to 001.\n"); return idx; } /** * dlt_logstorage_storage_dir_info * * Read file names of storage directory. * Update the file list, arrange it in order of latest and oldest * * @param file_config User configurations for log file * @param path Path to storage directory * @param config DltLogStorageFilterConfig * @return 0 on success, -1 on error */ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, char *path, DltLogStorageFilterConfig *config) { int check = 0; int i = 0; int cnt = 0; int ret = 0; unsigned int max_idx = 0; struct dirent **files = { 0 }; unsigned int current_idx = 0; DltLogStorageFileList *n = NULL; DltLogStorageFileList *n1 = NULL; if ((config == NULL) || (file_config == NULL) || (path == NULL) || (config->file_name == NULL)) return -1; cnt = scandir(path, &files, 0, alphasort); if (cnt < 0) { dlt_vlog(LOG_ERR, "%s: Failed to scan directory\n", __func__); return -1; } dlt_vlog(LOG_DEBUG, "%s: Scanned [%d] files from %s\n", __func__, cnt, path); /* In order to have a latest status of file list, * the existing records must be deleted before updating */ n = config->records; if (config->records) { while (n) { n1 = n; n = n->next; free(n1->name); n1->name = NULL; free(n1); n1 = NULL; } config->records = NULL; } char suffix[10]; int suffix_len; memset(suffix, 0, 10); if (config->gzip_compression) { suffix_len = DLT_OFFLINE_LOGSTORAGE_GZ_FILE_EXTENSION_LEN; strncpy(suffix, ".dlt.gz", suffix_len); } else { suffix_len = DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN; strncpy(suffix, ".dlt", suffix_len); } for (i = 0; i < cnt; i++) { int len = 0; int fname_len = 0; len = strlen(config->file_name); fname_len = strlen(files[i]->d_name); if ((strncmp(files[i]->d_name, config->file_name, len) == 0) && (files[i]->d_name[len] == file_config->logfile_delimiter) && (fname_len > suffix_len && strncmp(&files[i]->d_name[fname_len - suffix_len], suffix, suffix_len) == 0)) { DltLogStorageFileList **tmp = NULL; current_idx = dlt_logstorage_get_idx_of_log_file(file_config, config, files[i]->d_name); if (config->records == NULL) { config->records = malloc(sizeof(DltLogStorageFileList)); if (config->records == NULL) { ret = -1; dlt_log(LOG_ERR, "Memory allocation failed\n"); break; } tmp = &config->records; } else { tmp = &config->records; while (*(tmp) != NULL) tmp = &(*tmp)->next; *tmp = malloc(sizeof(DltLogStorageFileList)); if (*tmp == NULL) { ret = -1; dlt_log(LOG_ERR, "Memory allocation failed\n"); break; } } (*tmp)->name = strdup(files[i]->d_name); (*tmp)->idx = current_idx; (*tmp)->next = NULL; check++; } } dlt_vlog(LOG_DEBUG, "%s: After dir scan: [%d] files of [%s]\n", __func__, check, config->file_name); if (ret == 0) { max_idx = dlt_logstorage_sort_file_name(&config->records); /* Fault tolerance: * In case there are some log files are removed but * the index is still not reaching maxcounter, no need * to perform rearrangement of filename. * This would help the log keeps growing until maxcounter is reached and * the maximum number of log files could be obtained. */ if (max_idx == file_config->logfile_maxcounter) dlt_logstorage_rearrange_file_name(&config->records); } /* free scandir result */ for (i = 0; i < cnt; i++) free(files[i]); free(files); return ret; } /** * dlt_logstorage_open_log_file * * Open a handle to the logfile * * @param config A pointer to the current DltLogStorageFilterConfig * @param fpath The file path * @param mode The mode to open the file with */ DLT_STATIC void dlt_logstorage_open_log_output_file(DltLogStorageFilterConfig *config, const char *fpath, const char *mode) { FILE *file = fopen(fpath, mode); config->fd = fileno(file); if (config->gzip_compression) { #ifdef DLT_LOGSTORAGE_USE_GZIP dlt_vlog(LOG_DEBUG, "%s: Opening GZIP log file\n", __func__); config->gzlog = gzdopen(config->fd, mode); #endif } else { dlt_vlog(LOG_DEBUG, "%s: Opening log file\n", __func__); config->log = file; } } /** * dlt_logstorage_open_log_file * * Open a log file. Check storage directory for already created files and open * the oldest if there is enough space to store at least msg_size. * Otherwise create a new file, but take configured max number of files into * account and remove the oldest file if needed. * * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param msg_size Size of incoming message * @param is_update_required The file list needs to be updated * @return 0 on succes, -1 on error */ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int msg_size, bool is_update_required) { int ret = 0; char absolute_file_path[DLT_MOUNT_PATH_MAX + DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 1] = { '\0' }; char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 1] = { '\0' }; unsigned int num_log_files = 0; struct stat s; DltLogStorageFileList **tmp = NULL; DltLogStorageFileList **newest = NULL; char file_name[DLT_MOUNT_PATH_MAX + 1] = { '\0' }; if (config == NULL) return -1; if (strlen(dev_path) > DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN) { dlt_vlog(LOG_ERR, "device path '%s' is too long to store\n", dev_path); return -1; } snprintf(storage_path, DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN, "%s/", dev_path); /* check if there are already files stored */ if (config->records == NULL || is_update_required) { if (dlt_logstorage_storage_dir_info(file_config, storage_path, config) != 0) return -1; } /* obtain locations of newest, current file names, file count */ tmp = &config->records; while (*(tmp) != NULL) { num_log_files += 1; if ((*tmp)->next == NULL) newest = tmp; tmp = &(*tmp)->next; } /* need new file*/ if (num_log_files == 0) { dlt_logstorage_log_file_name(file_name, file_config, config, 1); /* concatenate path and file and open absolute path */ strcat(absolute_file_path, storage_path); strcat(absolute_file_path, file_name); config->working_file_name = strdup(file_name); dlt_logstorage_open_log_output_file(config, absolute_file_path, "a"); /* Add file to file list */ *tmp = malloc(sizeof(DltLogStorageFileList)); if (*tmp == NULL) { dlt_log(LOG_ERR, "Memory allocation for file name failed\n"); return -1; } (*tmp)->name = strdup(file_name); (*tmp)->idx = 1; (*tmp)->next = NULL; } else { strcat(absolute_file_path, storage_path); /* newest file available * Since the working file is already updated from newest file info * So if there is already wrap-up, the newest file will be the working file */ if ((config->wrap_id == 0) || (config->working_file_name == NULL)) { if (config->working_file_name != NULL) { free(config->working_file_name); config->working_file_name = NULL; } config->working_file_name = strdup((*newest)->name); } strcat(absolute_file_path, config->working_file_name); dlt_vlog(LOG_DEBUG, "%s: Number of log files-newest file-wrap_id [%u]-[%s]-[%u]\n", __func__, num_log_files, config->working_file_name, config->wrap_id); ret = stat(absolute_file_path, &s); /* if size is enough, open it */ if ((ret == 0) && (s.st_size + msg_size <= (int)config->file_size)) { dlt_logstorage_open_log_output_file(config, absolute_file_path, "a"); config->current_write_file_offset = s.st_size; } else { /* no space in file or file stats cannot be read */ unsigned int idx = 0; /* get index of newest log file */ idx = dlt_logstorage_get_idx_of_log_file(file_config, config, config->working_file_name); idx += 1; /* wrap around if max index is reached or an error occurred * while calculating index from file name */ if ((idx > file_config->logfile_maxcounter) || (idx == 0)) { idx = 1; config->wrap_id += 1; } dlt_logstorage_log_file_name(file_name, file_config, config, idx); /* concatenate path and file and open absolute path */ memset(absolute_file_path, 0, sizeof(absolute_file_path) / sizeof(char)); strcat(absolute_file_path, storage_path); strcat(absolute_file_path, file_name); if(config->working_file_name) { free(config->working_file_name); config->working_file_name = strdup(file_name); } /* If there is already wrap-up, check the existence of file * remove it and reopen it. * In this case number of log file won't be increased*/ if (config->wrap_id && stat(absolute_file_path, &s) == 0) { remove(absolute_file_path); num_log_files -= 1; dlt_vlog(LOG_DEBUG, "%s: Remove '%s' (num_log_files: %u, config->num_files:%u)\n", __func__, absolute_file_path, num_log_files, config->num_files); } dlt_logstorage_open_log_output_file(config, absolute_file_path, "a"); dlt_vlog(LOG_DEBUG, "%s: Filename and Index after updating [%s]-[%u]\n", __func__, file_name, idx); /* Add file to file list */ *tmp = malloc(sizeof(DltLogStorageFileList)); if (*tmp == NULL) { dlt_log(LOG_ERR, "Memory allocation for file name failed\n"); return -1; } (*tmp)->name = strdup(file_name); (*tmp)->idx = idx; (*tmp)->next = NULL; num_log_files += 1; /* check if number of log files exceeds configured max value */ if (num_log_files > config->num_files) { /* delete oldest */ DltLogStorageFileList **head = &config->records; DltLogStorageFileList *n = *head; memset(absolute_file_path, 0, sizeof(absolute_file_path) / sizeof(char)); strcat(absolute_file_path, storage_path); strcat(absolute_file_path, (*head)->name); dlt_vlog(LOG_DEBUG, "%s: Remove '%s' (num_log_files: %u, config->num_files:%u)\n", __func__, absolute_file_path, num_log_files, config->num_files); remove(absolute_file_path); free((*head)->name); (*head)->name = NULL; *head = n->next; n->next = NULL; free(n); } } } #ifdef DLT_LOGSTORAGE_USE_GZIP if (config->gzlog == NULL && config->log == NULL) { #else if (config->log == NULL) { #endif if (*tmp != NULL) { if ((*tmp)->name != NULL) { free((*tmp)->name); (*tmp)->name = NULL; } free(*tmp); *tmp = NULL; } if (config->working_file_name != NULL) { free(config->working_file_name); config->working_file_name = NULL; } dlt_vlog(LOG_ERR, "%s: Unable to open log file.\n", __func__); return -1; } return ret; } /** * dlt_logstorage_find_dlt_header * * search for dlt header in cache * * @param ptr cache starting position * @param offset offset * @param cnt count * @return index on success, -1 on error */ DLT_STATIC int dlt_logstorage_find_dlt_header(void *ptr, unsigned int offset, unsigned int cnt) { const char magic[] = { 'D', 'L', 'T', 0x01 }; const char *cache = (char*)ptr + offset; unsigned int i; for (i = 0; i < cnt; i++) { if ((cache[i] == 'D') && (strncmp(&cache[i], magic, 4) == 0)) return i; } return -1; } /** * dlt_logstorage_find_last_dlt_header * * search for last dlt header in cache * * @param ptr cache starting position * @param offset offset * @param cnt count * @return index on success, -1 on error */ DLT_STATIC int dlt_logstorage_find_last_dlt_header(void *ptr, unsigned int offset, unsigned int cnt) { const char magic[] = {'D', 'L', 'T', 0x01}; const char *cache = (char*)ptr + offset; unsigned int i; for (i = cnt; i > 0; i--) { if ((cache[i] == 'D') && (strncmp(&cache[i], magic, 4) == 0)) return i; } return -1; } /** * dlt_logstorage_write_to_log * * Write logdata to log storage file * * @param ptr A pointer to the data to write * @param size The size of the data blocks * @param nmemb The number of blocks to write * @param config A pointer to DltLogStorageFilterConfig */ DLT_STATIC int dlt_logstorage_write_to_log(void *ptr, size_t size, size_t nmemb, DltLogStorageFilterConfig *config) { #ifdef DLT_LOGSTORAGE_USE_GZIP if (config->gzip_compression) { return gzfwrite(ptr, size, nmemb, config->gzlog); } else { return fwrite(ptr, size, nmemb, config->log); } #else return fwrite(ptr, size, nmemb, config->log); #endif } /** * dlt_logstorage_check_write_ret * * check the return value of fwrite/gzfwrite * * @param config DltLogStorageFilterConfig * @param ret return value of fwrite/gzfwrite call */ DLT_STATIC void dlt_logstorage_check_write_ret(DltLogStorageFilterConfig *config, int ret) { if (config == NULL) dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); if (ret <= 0) { if (config->gzip_compression) { #ifdef DLT_LOGSTORAGE_USE_GZIP const char *msg = gzerror(config->gzlog, &ret); if (msg != NULL) { dlt_vlog(LOG_ERR, "%s: failed to write cache into log file: %s\n", __func__, msg); } #endif } else { if (ferror(config->log) != 0) dlt_vlog(LOG_ERR, "%s: failed to write cache into log file\n", __func__); } } else { /* force sync */ if (config->gzip_compression) { #ifdef DLT_LOGSTORAGE_USE_GZIP if (gzflush(config->gzlog, Z_SYNC_FLUSH) != 0) dlt_vlog(LOG_ERR, "%s: failed to gzflush log file\n", __func__); #endif } else { if (fflush(config->log) != 0) dlt_vlog(LOG_ERR, "%s: failed to flush log file\n", __func__); } if (fsync(config->fd) != 0) { /* some filesystem doesn't support fsync() */ if (errno != ENOSYS) { dlt_vlog(LOG_ERR, "%s: failed to sync log file\n", __func__); } } } } /** * dlt_logstorage_close_file * * Close open file handles if any exist in the provided * DltLogStorageFilterConfig * * @param config The DltLogStorageFilterConfig to operate on */ DLT_STATIC void dlt_logstorage_close_file(DltLogStorageFilterConfig *config) { #ifdef DLT_LOGSTORAGE_USE_GZIP if (config->gzlog) { gzclose(config->gzlog); config->gzlog = NULL; } #endif if (config->log) { fclose(config->log); config->log = NULL; } } /** * dlt_logstorage_sync_to_file * * Write the log message to log file * * @param config DltLogStorageFilterConfig * @param file_config DltLogStorageUserConfig * @param dev_path Storage device mount point path * @param footer DltLogStorageCacheFooter * @param start_offset Start offset of the cache * @param end_offset End offset of the cache * @return 0 on success, -1 on error */ DLT_STATIC int dlt_logstorage_sync_to_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, DltLogStorageCacheFooter *footer, unsigned int start_offset, unsigned int end_offset) { int ret = 0; int start_index = 0; int end_index = 0; int count = 0; int remain_file_size = 0; if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (footer == NULL)) { dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); return -1; } count = end_offset - start_offset; /* In case of cached-based strategy, the newest file information * must be updated everytime of synchronization. */ dlt_logstorage_close_file(config); config->current_write_file_offset = 0; if (dlt_logstorage_open_log_file(config, file_config, dev_path, count, true) != 0) { dlt_vlog(LOG_ERR, "%s: failed to open log file\n", __func__); return -1; } remain_file_size = config->file_size - config->current_write_file_offset; if (count > remain_file_size) { /* Check if more than one message can fit into the remaining file */ start_index = dlt_logstorage_find_dlt_header(config->cache, start_offset, remain_file_size); end_index = dlt_logstorage_find_last_dlt_header(config->cache, start_offset + start_index, remain_file_size - start_index); count = end_index - start_index; if ((start_index >= 0) && (end_index > start_index) && (count > 0) && (count <= remain_file_size)) { dlt_logstorage_write_to_log((uint8_t*)config->cache + start_offset + start_index, count, 1, config); dlt_logstorage_check_write_ret(config, ret); /* Close log file */ dlt_logstorage_close_file(config); config->current_write_file_offset = 0; footer->last_sync_offset = start_offset + count; start_offset = footer->last_sync_offset; } else { /* Close log file */ dlt_logstorage_close_file(config); config->current_write_file_offset = 0; } } start_index = dlt_logstorage_find_dlt_header(config->cache, start_offset, count); count = end_offset - start_offset - start_index; if ((start_index >= 0) && (count > 0)) { /* Prepare log file */ if (config->log == NULL) { if (dlt_logstorage_prepare_on_msg(config, file_config, dev_path, count, NULL) != 0) { dlt_vlog(LOG_ERR, "%s: failed to prepare log file\n", __func__); return -1; } } ret = dlt_logstorage_write_to_log((uint8_t *)config->cache + start_offset + start_index, count, 1, config); dlt_logstorage_check_write_ret(config, ret); config->current_write_file_offset += count; footer->last_sync_offset = end_offset; } footer->wrap_around_cnt = 0; return 0; } /** * dlt_logstorage_prepare_on_msg * * Prepare the log file for a certain filer. If log file not open or log * files max size reached, open a new file. * * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param log_msg_size Size of log message * @param newest_file_info Info of newest file for corresponding filename * @return 0 on success, -1 on error */ int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size, DltNewestFileName *newest_file_info) { int ret = 0; struct stat s; if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (newest_file_info == NULL)) { dlt_vlog(LOG_DEBUG, "Wrong paratemters\n"); return -1; } /* This is for ON_MSG/UNSET strategy */ #ifdef DLT_LOGSTORAGE_USE_GZIP if (config->log == NULL && config->gzlog == NULL) { #else if (config->log == NULL) { #endif /* Sync the wrap id and working file name before opening log file */ if (config->wrap_id < newest_file_info->wrap_id) { config->wrap_id = newest_file_info->wrap_id; if (config->working_file_name) { free(config->working_file_name); config->working_file_name = NULL; } config->working_file_name = strdup(newest_file_info->newest_file); } /* open a new log file */ ret = dlt_logstorage_open_log_file(config, file_config, dev_path, log_msg_size, true); } else { /* already open, check size and create a new file if needed */ ret = fstat(config->fd, &s); if (ret == 0) { /* Check if adding new data do not exceed max file size * * This is inaccurate for gz compressed files but as long as log * messages aren't gigantic it should be negligeble * * Also check if wrap id needs to be updated */ if ((s.st_size + log_msg_size > (int)config->file_size) || (strcmp(config->working_file_name, newest_file_info->newest_file) != 0) || (config->wrap_id < newest_file_info->wrap_id)) { dlt_logstorage_close_file(config); /* Sync the wrap id and working file name before opening log file */ if (config->wrap_id <= newest_file_info->wrap_id) { config->wrap_id = newest_file_info->wrap_id; if (config->working_file_name) { free(config->working_file_name); config->working_file_name = NULL; } config->working_file_name = strdup(newest_file_info->newest_file); } ret = dlt_logstorage_open_log_file(config, file_config, dev_path, log_msg_size, true); } else { /*everything is prepared */ ret = 0; } } else { dlt_log(LOG_ERR, "dlt_logstorage_prepare_log_file: stat() failed.\n"); ret = -1; } } return ret; } /** * dlt_logstorage_write_on_msg * * Write the log message. * * @param config DltLogStorageFilterConfig * @param file_config DltLogStorageUserConfig * @param dev_path Path to device * @param data1 header * @param size1 header size * @param data2 storage header * @param size2 storage header size * @param data3 payload * @param size3 payload size * @return 0 on success, -1 on error */ int dlt_logstorage_write_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3) { int ret; if ((config == NULL) || (data1 == NULL) || (data2 == NULL) || (data3 == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } ret = dlt_logstorage_write_to_log(data1, 1, size1, config); if (ret != size1) dlt_log(LOG_WARNING, "Wrote less data than specified\n"); ret = dlt_logstorage_write_to_log(data2, 1, size2, config); if (ret != size2) dlt_log(LOG_WARNING, "Wrote less data than specified\n"); ret = dlt_logstorage_write_to_log(data3, 1, size3, config); if (ret != size3) dlt_log(LOG_WARNING, "Wrote less data than specified\n"); #ifdef DLT_LOGSTORAGE_USE_GZIP if (config->gzip_compression) { gzerror(config->gzlog, &ret); return ret; } else { return ferror(config->log); } #else return ferror(config->log); #endif } /** * dlt_logstorage_sync_on_msg * * sync data to disk. * * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param status Strategy flag * @return 0 on success, -1 on error */ int dlt_logstorage_sync_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int status) { (void)file_config; /* satisfy compiler */ (void)dev_path; if (config == NULL) return -1; if (status == DLT_LOGSTORAGE_SYNC_ON_MSG) { /* sync on every message */ if (config->gzip_compression) { #ifdef DLT_LOGSTORAGE_USE_GZIP if (gzflush(config->gzlog, Z_SYNC_FLUSH) != 0) dlt_vlog(LOG_ERR, "%s: failed to gzflush log file\n", __func__); #endif } else { if (fflush(config->log) != 0) dlt_vlog(LOG_ERR, "%s: failed to flush log file\n", __func__); } } return 0; } /** * dlt_logstorage_prepare_msg_cache * * Prepare the log file for a certain filer. If log file not open or log * files max size reached, open a new file. * Create a memory area to cache data. * * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param log_msg_size Size of log message * @param newest_file_info Info of newest files for corresponding filename * @return 0 on success, -1 on error */ int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size, DltNewestFileName *newest_file_info ) { if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (newest_file_info == NULL)) return -1; /* check if newest file info is available * + working file name is NULL => update directly to newest file * + working file name is not NULL: check if * ++ wrap_ids are different from each other or * ++ newest file name <> working file name */ if (newest_file_info->newest_file) { if (config->working_file_name && ((config->wrap_id != newest_file_info->wrap_id) || (strcmp(newest_file_info->newest_file, config->working_file_name) != 0))) { free(config->working_file_name); config->working_file_name = NULL; } if (config->working_file_name == NULL) { config->working_file_name = strdup(newest_file_info->newest_file); config->wrap_id = newest_file_info->wrap_id; } } /* Combinations allowed: on Daemon_Exit with on Demand,File_Size with Daemon_Exit * File_Size with on Demand, Specific_Size with Daemon_Exit,Specific_Size with on Demand * Combination not allowed : File_Size with Specific_Size */ /* check for combinations of specific_size and file_size strategy */ if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) && ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE)) > 0)) { dlt_log(LOG_WARNING, "wrong combination of sync strategies \n"); return -1; } (void)log_msg_size; /* satisfy compiler */ /* check specific size is smaller than file size */ if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) && (config->specific_size > config->file_size)) { dlt_log(LOG_ERR, "Cache size is larger than file size. " "Cannot prepare log file for ON_SPECIFIC_SIZE sync\n"); return -1; } if (config->cache == NULL) { unsigned int cache_size = 0; /* check for sync_specific_size strategy */ if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { cache_size = config->specific_size; } else /* other cache strategies */ { cache_size = config->file_size; } /* check total logstorage cache size */ if ((g_logstorage_cache_size + cache_size + sizeof(DltLogStorageCacheFooter)) > g_logstorage_cache_max) { dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); return -1; } /* create cache */ config->cache = calloc(1, cache_size + sizeof(DltLogStorageCacheFooter)); if (config->cache == NULL) { dlt_log(LOG_CRIT, "Cannot allocate memory for filter ring buffer\n"); } else { /* update current used cache size */ g_logstorage_cache_size = cache_size + sizeof(DltLogStorageCacheFooter); } } return 0; } /** * dlt_logstorage_write_msg_cache * * Write the log message. * * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param data1 header * @param size1 header size * @param data2 storage header * @param size2 storage header size * @param data3 payload * @param size3 payload size * @return 0 on success, -1 on error */ int dlt_logstorage_write_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3) { DltLogStorageCacheFooter *footer = NULL; int msg_size; int remain_cache_size; uint8_t *curr_write_addr = NULL; int ret = 0; unsigned int cache_size; if ((config == NULL) || (data1 == NULL) || (size1 < 0) || (data2 == NULL) || (size2 < 0) || (data3 == NULL) || (size3 < 0) || (config->cache == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { cache_size = config->specific_size; } else { cache_size = config->file_size; } footer = (DltLogStorageCacheFooter *)((uint8_t*)config->cache + cache_size); if (footer == NULL) { dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n"); return -1; } msg_size = size1 + size2 + size3; remain_cache_size = cache_size - footer->offset; if (msg_size <= remain_cache_size) /* add at current position */ { curr_write_addr = (uint8_t*)config->cache + footer->offset; footer->offset += msg_size; if (footer->wrap_around_cnt < 1) { footer->end_sync_offset = footer->offset; } /* write data to cache */ memcpy(curr_write_addr, data1, size1); curr_write_addr += size1; memcpy(curr_write_addr, data2, size2); curr_write_addr += size2; memcpy(curr_write_addr, data3, size3); } /* * In case the msg_size is equal to remaining cache size, * the message is still written in cache. * Then whole cache data is synchronized to file. */ if (msg_size >= remain_cache_size) { /*check for message size exceeds cache size for specific_size strategy */ if ((unsigned int) msg_size > cache_size) { dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n"); return -1; } /*sync to file for specific_size or file_size */ if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) > 0) { ret = config->dlt_logstorage_sync(config, file_config, dev_path, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE); if (ret != 0) { dlt_log(LOG_ERR,"dlt_logstorage_sync: Unable to sync.\n"); return -1; } } else if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { ret = config->dlt_logstorage_sync(config, file_config, dev_path, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE); if (ret != 0) { dlt_log(LOG_ERR,"dlt_logstorage_sync: Unable to sync.\n"); return -1; } } else if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_DEMAND) > 0) || (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) > 0)) { footer->wrap_around_cnt += 1; } if (msg_size > remain_cache_size) { /* start writing from beginning */ footer->end_sync_offset = footer->offset; curr_write_addr = config->cache; footer->offset = msg_size; /* write data to cache */ memcpy(curr_write_addr, data1, size1); curr_write_addr += size1; memcpy(curr_write_addr, data2, size2); curr_write_addr += size2; memcpy(curr_write_addr, data3, size3); } } return 0; } /** * dlt_logstorage_sync_msg_cache * * sync data to disk. * * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param status Strategy flag * @return 0 on success, -1 on error */ int dlt_logstorage_sync_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int status) { unsigned int cache_size; DltLogStorageCacheFooter *footer = NULL; if ((config == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } /* sync only, if given strategy is set */ if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, status) > 0) { if (config->cache == NULL) { dlt_log(LOG_ERR, "Cannot copy cache to file. Cache is NULL\n"); return -1; } if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { cache_size = config->specific_size; } else { cache_size = config->file_size; } footer = (DltLogStorageCacheFooter *)((uint8_t*)config->cache + cache_size); if (footer == NULL) { dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); return -1; } /* sync cache data to file */ if (footer->wrap_around_cnt < 1) { /* Sync whole cache */ dlt_logstorage_sync_to_file(config, file_config, dev_path, footer, footer->last_sync_offset, footer->offset); } else if ((footer->wrap_around_cnt == 1) && (footer->offset < footer->last_sync_offset)) { /* sync (1) footer->last_sync_offset to footer->end_sync_offset, * and (2) footer->last_sync_offset (= 0) to footer->offset */ dlt_logstorage_sync_to_file(config, file_config, dev_path, footer, footer->last_sync_offset, footer->end_sync_offset); footer->last_sync_offset = 0; dlt_logstorage_sync_to_file(config, file_config, dev_path, footer, footer->last_sync_offset, footer->offset); } else { /* sync (1) footer->offset + index to footer->end_sync_offset, * and (2) footer->last_sync_offset (= 0) to footer->offset */ dlt_logstorage_sync_to_file(config, file_config, dev_path, footer, footer->offset, footer->end_sync_offset); footer->last_sync_offset = 0; dlt_logstorage_sync_to_file(config, file_config, dev_path, footer, footer->last_sync_offset, footer->offset); } /* Initialize cache if needed */ if ((status == DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) || (status == DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE)) { /* clean ring buffer and reset footer information */ memset(config->cache, 0, cache_size + sizeof(DltLogStorageCacheFooter)); } if (status == DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) { /* Close log file */ dlt_logstorage_close_file(config); config->current_write_file_offset = 0; } } return 0; } dlt-daemon-2.18.10/src/offlinelogstorage/dlt_offline_logstorage_behavior.h000066400000000000000000000123051446635226000267630ustar00rootroot00000000000000/** * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Christoph Lipka ADIT 2015 * * \file: dlt_offline_logstorage_behavior.h * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_offline_logstorage_behavior.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ #define DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ /* ON_MSG behavior */ int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size, DltNewestFileName *newest_file_info); int dlt_logstorage_write_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3); /* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback * is called on message received */ int dlt_logstorage_sync_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int status); /* Logstorage cache functionality */ int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size, DltNewestFileName *newest_file_info); int dlt_logstorage_write_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3); int dlt_logstorage_sync_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int status); #endif /* DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ */ dlt-daemon-2.18.10/src/offlinelogstorage/dlt_offline_logstorage_behavior_internal.h000066400000000000000000000115331446635226000306610ustar00rootroot00000000000000/** * Copyright (C) 2018 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality internal header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Aditya Paluri ADIT 2018 * * \file: dlt_offline_logstorage_behavior_internal.h * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_offline_logstorage_behavior_internal.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Aditya Paluri venkataaditya.paluri@in.bosch.com ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** ap Aditya Paluri ADIT ** *******************************************************************************/ #ifndef DLT_OFFLINELOGSTORAGE_BEHAVIOR_INTERNAL_H_ #define DLT_OFFLINELOGSTORAGE_BEHAVIOR_INTERNAL_H_ void dlt_logstorage_log_file_name(char *log_file_name, DltLogStorageUserConfig *file_config, DltLogStorageFilterConfig *filter_config, int idx); unsigned int dlt_logstorage_sort_file_name(DltLogStorageFileList **head); void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head); unsigned int dlt_logstorage_get_idx_of_log_file(DltLogStorageUserConfig *file_config, DltLogStorageFilterConfig *config, char *file); int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, char *path, DltLogStorageFilterConfig *config); int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int msg_size, bool is_update_required); DLT_STATIC int dlt_logstorage_sync_to_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, DltLogStorageCacheFooter *footer, unsigned int start_offset, unsigned int end_offset); DLT_STATIC int dlt_logstorage_find_dlt_header(void *ptr, unsigned int offset, unsigned int cnt); DLT_STATIC int dlt_logstorage_find_last_dlt_header(void *ptr, unsigned int offset, unsigned int cnt); #endif /* DLT_OFFLINELOGSTORAGE_BEHAVIOR_INTERNAL_H_ */ dlt-daemon-2.18.10/src/offlinelogstorage/dlt_offline_logstorage_internal.h000066400000000000000000000144051446635226000270030ustar00rootroot00000000000000/** * Copyright (C) 2017 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * DLT offline log storage functionality internal header file. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \author Aditya Paluri ADIT 2017 * * \file: dlt_offline_logstorage_internal.h * For further information see http://www.covesa.org/. */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_offline_logstorage_internal.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Aditya Paluri venkataaditya.paluri@in.bosch.com ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** ap Aditya Paluri ADIT ** *******************************************************************************/ #ifndef DLT_OFFLINE_LOGSTORAGE_INTERNAL_H #define DLT_OFFLINE_LOGSTORAGE_INTERNAL_H DLT_STATIC int dlt_logstorage_list_destroy(DltLogStorageFilterList **list, DltLogStorageUserConfig *uconfig, char *dev_path, int reason); DLT_STATIC int dlt_logstorage_list_add_config(DltLogStorageFilterConfig *data, DltLogStorageFilterConfig **listdata); DLT_STATIC int dlt_logstorage_list_add(char *key, int num_keys, DltLogStorageFilterConfig *data, DltLogStorageFilterList **list); DLT_STATIC int dlt_logstorage_list_find(char *key, DltLogStorageFilterList **list, DltLogStorageFilterConfig **config); DLT_STATIC int dlt_logstorage_count_ids(const char *str); DLT_STATIC int dlt_logstorage_read_number(unsigned int *number, char *value); DLT_STATIC int dlt_logstorage_read_bool(unsigned int *boolean, char *value); DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value); DLT_STATIC int dlt_logstorage_check_apids(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_ctids(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_loglevel(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_gzip_compression(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_filename(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_filesize(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_nofiles(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_sync_strategy(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_ecuid(DltLogStorageFilterConfig *config, char *value); DLT_STATIC int dlt_logstorage_check_param(DltLogStorageFilterConfig *config, DltLogstorageFilterConfType ctype, char *value); DLT_STATIC int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name); void dlt_logstorage_free(DltLogStorage *handle, int reason); DLT_STATIC int dlt_logstorage_create_keys(char *apids, char *ctids, char *ecuid, char **keys, int *num_keys); DLT_STATIC int dlt_logstorage_prepare_table(DltLogStorage *handle, DltLogStorageFilterConfig *data); DLT_STATIC int dlt_logstorage_validate_filter_name(char *name); DLT_STATIC void dlt_logstorage_filter_set_strategy(DltLogStorageFilterConfig *config, int strategy); DLT_STATIC int dlt_logstorage_load_config(DltLogStorage *handle); DLT_STATIC int dlt_logstorage_filter(DltLogStorage *handle, DltLogStorageFilterConfig **config, char *apid, char *ctid, char *ecuid, int log_level); #endif /* DLT_OFFLINE_LOGSTORAGE_INTERNAL_H */ dlt-daemon-2.18.10/src/shared/000077500000000000000000000000001446635226000157545ustar00rootroot00000000000000dlt-daemon-2.18.10/src/shared/dlt_common.c000066400000000000000000004152071446635226000202640ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_common.c */ #include #include /* for malloc(), free() */ #include /* for strlen(), memcmp(), memmove() */ #include /* for localtime_r(), strftime() */ #include /* for NAME_MAX */ #include /* for PRI formatting macro */ #include /* dirname */ #include #include #include #include /* for mkdir() */ #include #include "dlt_user_shared.h" #include "dlt_common.h" #include "dlt_common_cfg.h" #include "dlt_multiple_files.h" #include "dlt_version.h" #if defined (__WIN32__) || defined (_MSC_VER) # include /* for socket(), connect(), send(), and recv() */ #else # include /* for socket(), connect(), send(), and recv() */ # include # include /* for clock_gettime() */ #endif #if defined (_MSC_VER) # include #else # include /* for read(), close() */ # include # include /* for gettimeofday() */ #endif #if defined (__MSDOS__) || defined (_MSC_VER) # pragma warning(disable : 4996) /* Switch off C4996 warnings */ # include # include #endif const char dltSerialHeader[DLT_ID_SIZE] = { 'D', 'L', 'S', 1 }; char dltSerialHeaderChar[DLT_ID_SIZE] = { 'D', 'L', 'S', 1 }; #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC char dltFifoBaseDir[DLT_PATH_MAX] = "/tmp"; #endif #ifdef DLT_SHM_ENABLE char dltShmName[NAME_MAX + 1] = "/dlt-shm"; #endif /* internal logging parameters */ static int logging_level = LOG_INFO; static char logging_filename[NAME_MAX + 1] = ""; static bool print_with_attributes = false; int logging_mode = DLT_LOG_TO_STDERR; FILE *logging_handle = NULL; //use ohandle as an indicator that multiple files logging is active MultipleFilesRingBuffer multiple_files_ring_buffer = { .directory={0}, .filename={0}, .fileSize=0, .maxSize=0, .filenameTimestampBased=false, .filenameBase={0}, .filenameExt={0}, .ohandle=-1}; char *message_type[] = { "log", "app_trace", "nw_trace", "control", "", "", "", "" }; char *log_info[] = { "", "fatal", "error", "warn", "info", "debug", "verbose", "", "", "", "", "", "", "", "", "" }; char *trace_type[] = { "", "variable", "func_in", "func_out", "state", "vfb", "", "", "", "", "", "", "", "", "", "" }; char *nw_trace_type[] = { "", "ipc", "can", "flexray", "most", "vfb", "", "", "", "", "", "", "", "", "", "" }; char *control_type[] = { "", "request", "response", "time", "", "", "", "", "", "", "", "", "", "", "", "" }; static char *service_id_name[] = { "", "set_log_level", "set_trace_status", "get_log_info", "get_default_log_level", "store_config", "reset_to_factory_default", "set_com_interface_status", "set_com_interface_max_bandwidth", "set_verbose_mode", "set_message_filtering", "set_timing_packets", "get_local_time", "use_ecu_id", "use_session_id", "use_timestamp", "use_extended_header", "set_default_log_level", "set_default_trace_status", "get_software_version", "message_buffer_overflow" }; static char *return_type[] = { "ok", "not_supported", "error", "perm_denied", "warning", "", "", "", "no_matching_context_id" }; /* internal function definitions */ int dlt_buffer_get(DltBuffer *buf, unsigned char *data, int max_size, int delete); int dlt_buffer_reset(DltBuffer *buf); int dlt_buffer_increase_size(DltBuffer *buf); int dlt_buffer_minimize_size(DltBuffer *buf); void dlt_buffer_write_block(DltBuffer *buf, int *write, const unsigned char *data, unsigned int size); void dlt_buffer_read_block(DltBuffer *buf, int *read, unsigned char *data, unsigned int size); void dlt_print_hex(uint8_t *ptr, int size) { int num; if (ptr == NULL) return; for (num = 0; num < size; num++) { if (num > 0) dlt_user_printf(" "); dlt_user_printf("%.2x", ((uint8_t *)ptr)[num]); } } static DltReturnValue dlt_print_hex_string_delim(char *text, int textlength, uint8_t *ptr, int size, char delim) { int num; if ((ptr == NULL) || (text == NULL) || (textlength <= 0) || (size < 0) || (delim == '\0')) return DLT_RETURN_WRONG_PARAMETER; /* Length 3: AB_ , A is first digit of hex number, B is second digit of hex number, _ is space */ if (textlength < (size * 3)) { dlt_vlog(LOG_WARNING, "String does not fit hex data (available=%d, required=%d) !\n", textlength, size * 3); return DLT_RETURN_ERROR; } for (num = 0; num < size; num++) { if (num > 0) { snprintf(text, 2, "%c", delim); text++; } snprintf(text, 3, "%.2x", ((uint8_t *)ptr)[num]); text += 2; /* 2 chars */ } return DLT_RETURN_OK; } DltReturnValue dlt_print_hex_string(char *text, int textlength, uint8_t *ptr, int size) { return dlt_print_hex_string_delim(text, textlength, ptr, size, ' '); } DltReturnValue dlt_print_mixed_string(char *text, int textlength, uint8_t *ptr, int size, int html) { int required_size = 0; int lines, rest, i; if ((ptr == NULL) || (text == NULL) || (textlength <= 0) || (size < 0)) return DLT_RETURN_WRONG_PARAMETER; /* Check maximum required size and do a length check */ if (html == 0) required_size = (DLT_COMMON_HEX_LINELEN + (2 * DLT_COMMON_HEX_CHARS + (DLT_COMMON_HEX_CHARS - 1)) + DLT_COMMON_CHARLEN + DLT_COMMON_HEX_CHARS + DLT_COMMON_CHARLEN) * ((size / DLT_COMMON_HEX_CHARS) + 1); /* Example: (8 chars line number + (2*16 chars + 15 spaces) + space + 16 ascii chars + CR) * * ((size/16) lines + extra line for the rest) */ else required_size = (DLT_COMMON_HEX_LINELEN + (2 * DLT_COMMON_HEX_CHARS + (DLT_COMMON_HEX_CHARS - 1)) + DLT_COMMON_CHARLEN + DLT_COMMON_HEX_CHARS + 4 * DLT_COMMON_CHARLEN) * ((size / DLT_COMMON_HEX_CHARS) + 1); /* Example: (8 chars line number + (2*16 chars + 15 spaces) + space + 16 ascii chars + 4 [HTML CR:
]) * * ((size/16) lines + extra line for the rest) */ if (textlength < required_size) { dlt_vlog(LOG_WARNING, "String does not fit mixed data (available=%d, required=%d) !\n", textlength, required_size); return DLT_RETURN_ERROR; } /* print full lines */ for (lines = 0; lines < (size / DLT_COMMON_HEX_CHARS); lines++) { int ret = 0; /* Line number */ ret = snprintf(text, DLT_COMMON_HEX_LINELEN + 1, "%.6x: ", (uint32_t)lines * DLT_COMMON_HEX_CHARS); if ((ret < 0) || (ret >= (DLT_COMMON_HEX_LINELEN + 1))) dlt_log(LOG_WARNING, "line was truncated\n"); text += DLT_COMMON_HEX_LINELEN; /* 'XXXXXX: ' */ /* Hex-Output */ /* It is not required to decrement textlength, as it was already checked, that * there is enough space for the complete output */ if (dlt_print_hex_string(text, textlength, (uint8_t *)(ptr + (lines * DLT_COMMON_HEX_CHARS)), DLT_COMMON_HEX_CHARS) < DLT_RETURN_OK) return DLT_RETURN_ERROR; text += ((2 * DLT_COMMON_HEX_CHARS) + (DLT_COMMON_HEX_CHARS - 1)); /* 32 characters + 15 spaces */ snprintf(text, 2, " "); text += DLT_COMMON_CHARLEN; /* Char-Output */ /* It is not required to decrement textlength, as it was already checked, that * there is enough space for the complete output */ if (dlt_print_char_string(&text, textlength, (uint8_t *)(ptr + (lines * DLT_COMMON_HEX_CHARS)), DLT_COMMON_HEX_CHARS) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (html == 0) { snprintf(text, 2, "\n"); text += DLT_COMMON_CHARLEN; } else { snprintf(text, 5, "
"); text += (4 * DLT_COMMON_CHARLEN); } } /* print partial line */ rest = size % DLT_COMMON_HEX_CHARS; if (rest > 0) { /* Line number */ int ret = 0; ret = snprintf(text, 9, "%.6x: ", (uint32_t)(size / DLT_COMMON_HEX_CHARS) * DLT_COMMON_HEX_CHARS); if ((ret < 0) || (ret >= 9)) dlt_log(LOG_WARNING, "line number was truncated"); text += DLT_COMMON_HEX_LINELEN; /* 'XXXXXX: ' */ /* Hex-Output */ /* It is not required to decrement textlength, as it was already checked, that * there is enough space for the complete output */ if (dlt_print_hex_string(text, textlength, (uint8_t *)(ptr + ((size / DLT_COMMON_HEX_CHARS) * DLT_COMMON_HEX_CHARS)), rest) < DLT_RETURN_OK) return DLT_RETURN_ERROR; text += 2 * rest + (rest - 1); for (i = 0; i < (DLT_COMMON_HEX_CHARS - rest); i++) { snprintf(text, 4, " xx"); text += (3 * DLT_COMMON_CHARLEN); } snprintf(text, 2, " "); text += DLT_COMMON_CHARLEN; /* Char-Output */ /* It is not required to decrement textlength, as it was already checked, that * there is enough space for the complete output */ if (dlt_print_char_string(&text, textlength, (uint8_t *)(ptr + ((size / DLT_COMMON_HEX_CHARS) * DLT_COMMON_HEX_CHARS)), rest) < DLT_RETURN_OK) return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_print_char_string(char **text, int textlength, uint8_t *ptr, int size) { int num; if ((text == NULL) || (ptr == NULL) || (*text == NULL) || (textlength <= 0) || (size < 0)) return DLT_RETURN_WRONG_PARAMETER; if (textlength < size) { dlt_vlog(LOG_WARNING, "String does not fit character data (available=%d, required=%d) !\n", textlength, size); return DLT_RETURN_WRONG_PARAMETER; } for (num = 0; num < size; num++) { if ((((char *)ptr)[num] < DLT_COMMON_ASCII_CHAR_SPACE) || (((char *)ptr)[num] > DLT_COMMON_ASCII_CHAR_TILDE)) { snprintf(*text, 2, "."); } else { /* replace < with . */ if (((char *)ptr)[num] != DLT_COMMON_ASCII_CHAR_LT) snprintf(*text, 2, "%c", ((char *)ptr)[num]); else snprintf(*text, 2, "."); } (*text)++; } return DLT_RETURN_OK; } size_t dlt_strnlen_s(const char* str, size_t maxsize) { if (str == NULL) return 0; for (size_t i = 0; i < maxsize; ++i) { if (str[i] == '\0') return i; } return maxsize; } void dlt_print_id(char *text, const char *id) { /* check nullpointer */ if ((text == NULL) || (id == NULL)) return; /* Initialize text */ memset(text, '-', DLT_ID_SIZE); text[DLT_ID_SIZE] = 0; size_t len = dlt_strnlen_s(id, DLT_ID_SIZE); memcpy(text, id, len); } void dlt_set_id(char *id, const char *text) { /* check nullpointer */ if ((id == NULL) || (text == NULL)) return; id[0] = 0; id[1] = 0; id[2] = 0; id[3] = 0; if (text[0] != 0) id[0] = text[0]; else return; if (text[1] != 0) id[1] = text[1]; else return; if (text[2] != 0) id[2] = text[2]; else return; if (text[3] != 0) id[3] = text[3]; else return; } void dlt_clean_string(char *text, int length) { int num; if (text == NULL) return; for (num = 0; num < length; num++) if ((text[num] == '\r') || (text[num] == '\n')) text[num] = ' '; } DltReturnValue dlt_filter_init(DltFilter *filter, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (filter == NULL) return DLT_RETURN_WRONG_PARAMETER; filter->counter = 0; return DLT_RETURN_OK; } DltReturnValue dlt_filter_free(DltFilter *filter, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (filter == NULL) return DLT_RETURN_WRONG_PARAMETER; return DLT_RETURN_OK; } DltReturnValue dlt_filter_load(DltFilter *filter, const char *filename, int verbose) { if ((filter == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; FILE *handle; char str1[DLT_COMMON_BUFFER_LENGTH + 1]; char apid[DLT_ID_SIZE], ctid[DLT_ID_SIZE]; PRINT_FUNCTION_VERBOSE(verbose); handle = fopen(filename, "r"); if (handle == NULL) { dlt_vlog(LOG_WARNING, "Filter file %s cannot be opened!\n", filename); return DLT_RETURN_ERROR; } #define FORMAT_STRING_(x) "%" #x "s" #define FORMAT_STRING(x) FORMAT_STRING_(x) /* Reset filters */ filter->counter = 0; while (!feof(handle)) { str1[0] = 0; if (fscanf(handle, FORMAT_STRING(DLT_COMMON_BUFFER_LENGTH), str1) != 1) break; if (str1[0] == 0) break; printf(" %s", str1); if (strcmp(str1, "----") == 0) dlt_set_id(apid, ""); else dlt_set_id(apid, str1); str1[0] = 0; if (fscanf(handle, FORMAT_STRING(DLT_COMMON_BUFFER_LENGTH), str1) != 1) break; if (str1[0] == 0) break; printf(" %s\r\n", str1); if (strcmp(str1, "----") == 0) dlt_set_id(ctid, ""); else dlt_set_id(ctid, str1); if (filter->counter < DLT_FILTER_MAX) dlt_filter_add(filter, apid, ctid, 0, 0, INT32_MAX, verbose); else dlt_vlog(LOG_WARNING, "Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n", DLT_FILTER_MAX); } fclose(handle); return DLT_RETURN_OK; } DltReturnValue dlt_filter_save(DltFilter *filter, const char *filename, int verbose) { if ((filter == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; FILE *handle; int num; char buf[DLT_COMMON_BUFFER_LENGTH]; PRINT_FUNCTION_VERBOSE(verbose); handle = fopen(filename, "w"); if (handle == NULL) { dlt_vlog(LOG_WARNING, "Filter file %s cannot be opened!\n", filename); return DLT_RETURN_ERROR; } for (num = 0; num < filter->counter; num++) { if (filter->apid[num][0] == 0) { fprintf(handle, "---- "); } else { dlt_print_id(buf, filter->apid[num]); fprintf(handle, "%s ", buf); } if (filter->ctid[num][0] == 0) { fprintf(handle, "---- "); } else { dlt_print_id(buf, filter->ctid[num]); fprintf(handle, "%s ", buf); } } fclose(handle); return DLT_RETURN_OK; } int dlt_filter_find(DltFilter *filter, const char *apid, const char *ctid, const int log_level, const int32_t payload_min, const int32_t payload_max, int verbose) { int num; PRINT_FUNCTION_VERBOSE(verbose); if ((filter == NULL) || (apid == NULL)) return -1; for (num = 0; num < filter->counter; num++) if (memcmp(filter->apid[num], apid, DLT_ID_SIZE) == 0) { /* apid matches, now check for ctid */ if (ctid == NULL) { /* check if empty ctid matches */ /*if (memcmp(filter->ctid[num],"",DLT_ID_SIZE)==0)//coverity complains here about Out-of-bounds access. */ char empty_ctid[DLT_ID_SIZE] = ""; if (memcmp(filter->ctid[num], empty_ctid, DLT_ID_SIZE) == 0) if ((filter->log_level[num] == log_level) || (filter->log_level[num] == 0)) if (filter->payload_min[num] <= payload_min) if (filter->payload_max[num] >= payload_max) return num; } else if (memcmp(filter->ctid[num], ctid, DLT_ID_SIZE) == 0) { if ((filter->log_level[num] == log_level) || (filter->log_level[num] == 0)) if (filter->payload_min[num] <= payload_min) if (filter->payload_max[num] >= payload_max) return num; } } return -1; /* Not found */ } DltReturnValue dlt_filter_add(DltFilter *filter, const char *apid, const char *ctid, const int log_level, const int32_t payload_min, const int32_t payload_max, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((filter == NULL) || (apid == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (filter->counter >= DLT_FILTER_MAX) { dlt_vlog(LOG_WARNING, "Maximum number (%d) of allowed filters reached, ignoring filter!\n", DLT_FILTER_MAX); return DLT_RETURN_ERROR; } /* add each filter (apid, ctid, log_level, payload_min, payload_max) only once to filter array */ if (dlt_filter_find(filter, apid, ctid, log_level, payload_min, payload_max, verbose) < 0) { /* filter not found, so add it to filter array */ dlt_set_id(filter->apid[filter->counter], apid); dlt_set_id(filter->ctid[filter->counter], (ctid ? ctid : "")); filter->log_level[filter->counter] = log_level; filter->payload_min[filter->counter] = payload_min; filter->payload_max[filter->counter] = payload_max; filter->counter++; return DLT_RETURN_OK; } return DLT_RETURN_ERROR; } DltReturnValue dlt_filter_delete(DltFilter *filter, const char *apid, const char *ctid, const int log_level, const int32_t payload_min, const int32_t payload_max, int verbose) { int j, k; int found = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((filter == NULL) || (apid == NULL) || (ctid == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (filter->counter > 0) { /* Get first occurence of apid and ctid in filter array */ for (j = 0; j < filter->counter; j++) if ((memcmp(filter->apid[j], apid, DLT_ID_SIZE) == 0) && (memcmp(filter->ctid[j], ctid, DLT_ID_SIZE) == 0) && ((filter->log_level[j] == log_level) || (filter->log_level[j] == 0)) && (filter->payload_min[j] == payload_min) && (filter->payload_max[j] == payload_max) ) { found = 1; break; } if (found) { /* j is index */ /* Copy from j+1 til end to j til end-1 */ dlt_set_id(filter->apid[j], ""); dlt_set_id(filter->ctid[j], ""); filter->log_level[j] = 0; filter->payload_min[j] = 0; filter->payload_max[j] = INT32_MAX; for (k = j; k < (filter->counter - 1); k++) { dlt_set_id(filter->apid[k], filter->apid[k + 1]); dlt_set_id(filter->ctid[k], filter->ctid[k + 1]); filter->log_level[k] = filter->log_level[k + 1]; filter->payload_min[k] = filter->payload_min[k + 1]; filter->payload_max[k] = filter->payload_max[k + 1]; } filter->counter--; return DLT_RETURN_OK; } } return DLT_RETURN_ERROR; } DltReturnValue dlt_message_init(DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (msg == NULL) return DLT_RETURN_WRONG_PARAMETER; /* initalise structure parameters */ msg->headersize = 0; msg->datasize = 0; msg->databuffer = NULL; msg->databuffersize = 0; msg->storageheader = NULL; msg->standardheader = NULL; msg->extendedheader = NULL; msg->found_serialheader = 0; return DLT_RETURN_OK; } DltReturnValue dlt_message_free(DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (msg == NULL) return DLT_RETURN_WRONG_PARAMETER; /* delete databuffer if exists */ if (msg->databuffer) { free(msg->databuffer); msg->databuffer = NULL; msg->databuffersize = 0; } return DLT_RETURN_OK; } DltReturnValue dlt_message_header(DltMessage *msg, char *text, size_t textlength, int verbose) { return dlt_message_header_flags(msg, text, textlength, DLT_HEADER_SHOW_ALL, verbose); } DltReturnValue dlt_message_header_flags(DltMessage *msg, char *text, size_t textlength, int flags, int verbose) { struct tm timeinfo; char buffer [DLT_COMMON_BUFFER_LENGTH]; PRINT_FUNCTION_VERBOSE(verbose); if ((msg == NULL) || (text == NULL) || (textlength <= 0)) return DLT_RETURN_WRONG_PARAMETER; if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && (msg->extendedheader == NULL)) return DLT_RETURN_WRONG_PARAMETER; if ((flags < DLT_HEADER_SHOW_NONE) || (flags > DLT_HEADER_SHOW_ALL)) return DLT_RETURN_WRONG_PARAMETER; text[0] = 0; if ((flags & DLT_HEADER_SHOW_TIME) == DLT_HEADER_SHOW_TIME) { /* print received time */ time_t tt = msg->storageheader->seconds; tzset(); localtime_r(&tt, &timeinfo); strftime (buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", &timeinfo); snprintf(text, textlength, "%s.%.6d ", buffer, msg->storageheader->microseconds); } if ((flags & DLT_HEADER_SHOW_TMSTP) == DLT_HEADER_SHOW_TMSTP) { /* print timestamp if available */ if (DLT_IS_HTYP_WTMS(msg->standardheader->htyp)) snprintf(text + strlen(text), textlength - strlen(text), "%10u ", msg->headerextra.tmsp); else snprintf(text + strlen(text), textlength - strlen(text), "---------- "); } if ((flags & DLT_HEADER_SHOW_MSGCNT) == DLT_HEADER_SHOW_MSGCNT) /* print message counter */ snprintf(text + strlen(text), textlength - strlen(text), "%.3d ", msg->standardheader->mcnt); if ((flags & DLT_HEADER_SHOW_ECUID) == DLT_HEADER_SHOW_ECUID) { /* print ecu id, use header extra if available, else storage header value */ if (DLT_IS_HTYP_WEID(msg->standardheader->htyp)) dlt_print_id(text + strlen(text), msg->headerextra.ecu); else dlt_print_id(text + strlen(text), msg->storageheader->ecu); } /* print app id and context id if extended header available, else '----' */ # if ((flags & DLT_HEADER_SHOW_APID) == DLT_HEADER_SHOW_APID) { snprintf(text + strlen(text), textlength - strlen(text), " "); if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && (msg->extendedheader->apid[0] != 0)) dlt_print_id(text + strlen(text), msg->extendedheader->apid); else snprintf(text + strlen(text), textlength - strlen(text), "----"); snprintf(text + strlen(text), textlength - strlen(text), " "); } if ((flags & DLT_HEADER_SHOW_CTID) == DLT_HEADER_SHOW_CTID) { if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && (msg->extendedheader->ctid[0] != 0)) dlt_print_id(text + strlen(text), msg->extendedheader->ctid); else snprintf(text + strlen(text), textlength - strlen(text), "----"); snprintf(text + strlen(text), textlength - strlen(text), " "); } /* print info about message type and length */ if (DLT_IS_HTYP_UEH(msg->standardheader->htyp)) { if ((flags & DLT_HEADER_SHOW_MSGTYPE) == DLT_HEADER_SHOW_MSGTYPE) { snprintf(text + strlen(text), textlength - strlen(text), "%s", message_type[DLT_GET_MSIN_MSTP(msg->extendedheader->msin)]); snprintf(text + strlen(text), textlength - strlen(text), " "); } if ((flags & DLT_HEADER_SHOW_MSGSUBTYPE) == DLT_HEADER_SHOW_MSGSUBTYPE) { if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_LOG) snprintf(text + strlen(text), textlength - strlen(text), "%s", log_info[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]); if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_APP_TRACE) snprintf(text + strlen(text), textlength - strlen(text), "%s", trace_type[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]); if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_NW_TRACE) snprintf(text + strlen(text), textlength - strlen(text), "%s", nw_trace_type[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]); if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_CONTROL) snprintf(text + strlen(text), textlength - strlen(text), "%s", control_type[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]); snprintf(text + strlen(text), textlength - strlen(text), " "); } if ((flags & DLT_HEADER_SHOW_VNVSTATUS) == DLT_HEADER_SHOW_VNVSTATUS) { /* print verbose status pf message */ if (DLT_IS_MSIN_VERB(msg->extendedheader->msin)) snprintf(text + strlen(text), textlength - strlen(text), "V"); else snprintf(text + strlen(text), textlength - strlen(text), "N"); snprintf(text + strlen(text), textlength - strlen(text), " "); } if ((flags & DLT_HEADER_SHOW_NOARG) == DLT_HEADER_SHOW_NOARG) /* print number of arguments */ snprintf(text + strlen(text), textlength - strlen(text), "%d", msg->extendedheader->noar); } else { if ((flags & DLT_HEADER_SHOW_MSGTYPE) == DLT_HEADER_SHOW_MSGTYPE) snprintf(text + strlen(text), textlength - strlen(text), "--- "); if ((flags & DLT_HEADER_SHOW_MSGSUBTYPE) == DLT_HEADER_SHOW_MSGSUBTYPE) snprintf(text + strlen(text), textlength - strlen(text), "--- "); if ((flags & DLT_HEADER_SHOW_VNVSTATUS) == DLT_HEADER_SHOW_VNVSTATUS) snprintf(text + strlen(text), textlength - strlen(text), "N "); if ((flags & DLT_HEADER_SHOW_NOARG) == DLT_HEADER_SHOW_NOARG) snprintf(text + strlen(text), textlength - strlen(text), "-"); } return DLT_RETURN_OK; } DltReturnValue dlt_message_payload(DltMessage *msg, char *text, size_t textlength, int type, int verbose) { uint32_t id = 0, id_tmp = 0; uint8_t retval = 0; uint8_t *ptr; int32_t datalength; /* Pointer to ptr and datalength */ uint8_t **pptr; int32_t *pdatalength; int ret = 0; int num; uint32_t type_info = 0, type_info_tmp = 0; int text_offset = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((msg == NULL) || (msg->databuffer == NULL) || (text == NULL) || (type < DLT_OUTPUT_HEX) || (type > DLT_OUTPUT_ASCII_LIMITED)) return DLT_RETURN_WRONG_PARAMETER; if (textlength <= 0) { dlt_log(LOG_WARNING, "String does not fit binary data!\n"); return DLT_RETURN_WRONG_PARAMETER; } /* start with empty string */ text[0] = 0; /* print payload only as hex */ if (type == DLT_OUTPUT_HEX) return dlt_print_hex_string(text, (int)textlength, msg->databuffer, (int)msg->datasize); /* print payload as mixed */ if (type == DLT_OUTPUT_MIXED_FOR_PLAIN) return dlt_print_mixed_string(text, (int)textlength, msg->databuffer, (int)msg->datasize, 0); if (type == DLT_OUTPUT_MIXED_FOR_HTML) return dlt_print_mixed_string(text, (int)textlength, msg->databuffer, (int)msg->datasize, 1); ptr = msg->databuffer; datalength = (int32_t)msg->datasize; /* Pointer to ptr and datalength */ pptr = &ptr; pdatalength = &datalength; /* non-verbose mode */ /* print payload as hex */ if (DLT_MSG_IS_NONVERBOSE(msg)) { DLT_MSG_READ_VALUE(id_tmp, ptr, datalength, uint32_t); id = DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp); if (textlength < (((unsigned int)datalength * 3) + 20)) { dlt_vlog(LOG_WARNING, "String does not fit binary data (available=%d, required=%d) !\n", (int) textlength, (datalength * 3) + 20); return DLT_RETURN_ERROR; } /* process message id / service id */ if (DLT_MSG_IS_CONTROL(msg)) { if ((id > 0) && (id < DLT_SERVICE_ID_LAST_ENTRY)) snprintf(text + strlen(text), textlength - strlen(text), "%s", service_id_name[id]); /* service id */ else if (!(DLT_MSG_IS_CONTROL_TIME(msg))) snprintf(text + strlen(text), textlength - strlen(text), "service(%u)", id); /* service id */ if (datalength > 0) snprintf(text + strlen(text), textlength - strlen(text), ", "); } else { snprintf(text + strlen(text), textlength - strlen(text), "%u, ", id); /* message id */ } /* process return value */ if (DLT_MSG_IS_CONTROL_RESPONSE(msg)) { if (datalength > 0) { DLT_MSG_READ_VALUE(retval, ptr, datalength, uint8_t); /* No endian conversion necessary */ if ((retval < DLT_SERVICE_RESPONSE_LAST) || (retval == 8)) snprintf(text + strlen(text), textlength - strlen(text), "%s", return_type[retval]); else snprintf(text + strlen(text), textlength - strlen(text), "%.2x", retval); if (datalength >= 1) snprintf(text + strlen(text), textlength - strlen(text), ", "); } } if (type == DLT_OUTPUT_ASCII_LIMITED) { ret = dlt_print_hex_string(text + strlen(text), (int)(textlength - strlen( text)), ptr, (datalength > DLT_COMMON_ASCII_LIMIT_MAX_CHARS ? DLT_COMMON_ASCII_LIMIT_MAX_CHARS : datalength)); if ((datalength > DLT_COMMON_ASCII_LIMIT_MAX_CHARS) && ((textlength - strlen(text)) > 4)) snprintf(text + strlen(text), textlength - strlen(text), " ..."); } else { ret = dlt_print_hex_string(text + strlen(text), (int)(textlength - strlen(text)), ptr, datalength); } return ret; } /* At this point, it is ensured that a extended header is available */ /* verbose mode */ type_info = 0; type_info_tmp = 0; for (num = 0; num < (int)(msg->extendedheader->noar); num++) { if (num != 0) { text_offset = (int)strlen(text); snprintf(text + text_offset, textlength - (size_t)text_offset, " "); } /* first read the type info of the argument */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(msg->standardheader->htyp, type_info_tmp); /* print out argument */ text_offset = (int)strlen(text); if (dlt_message_argument_print(msg, type_info, pptr, pdatalength, (text + text_offset), (textlength - (size_t)text_offset), -1, 0) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_message_filter_check(DltMessage *msg, DltFilter *filter, int verbose) { /* check the filters if message is used */ int num; DltReturnValue found = DLT_RETURN_OK; PRINT_FUNCTION_VERBOSE(verbose); if ((msg == NULL) || (filter == NULL)) return DLT_RETURN_WRONG_PARAMETER; if ((filter->counter == 0) || (!(DLT_IS_HTYP_UEH(msg->standardheader->htyp)))) /* no filter is set, or no extended header is available, so do as filter is matching */ return DLT_RETURN_TRUE; for (num = 0; num < filter->counter; num++) /* check each filter if it matches */ if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && ((filter->apid[num][0] == 0) || (memcmp(filter->apid[num], msg->extendedheader->apid, DLT_ID_SIZE) == 0)) && ((filter->ctid[num][0] == 0) || (memcmp(filter->ctid[num], msg->extendedheader->ctid, DLT_ID_SIZE) == 0)) && ((filter->log_level[num] == 0) || (filter->log_level[num] == DLT_GET_MSIN_MTIN(msg->extendedheader->msin))) && ((filter->payload_min[num] == 0) || (filter->payload_min[num] <= msg->datasize)) && ((filter->payload_max[num] == 0) || (filter->payload_max[num] >= msg->datasize))) { found = DLT_RETURN_TRUE; break; } return found; } int dlt_message_read(DltMessage *msg, uint8_t *buffer, unsigned int length, int resync, int verbose) { uint32_t extra_size = 0; PRINT_FUNCTION_VERBOSE(verbose); if ((msg == NULL) || (buffer == NULL) || (length <= 0)) return DLT_MESSAGE_ERROR_UNKNOWN; /* initialize resync_offset */ msg->resync_offset = 0; /* check if message contains serial header, smaller than standard header */ if (length < sizeof(dltSerialHeader)) /* dlt_log(LOG_ERR, "Length smaller than serial header!\n"); */ return DLT_MESSAGE_ERROR_SIZE; if (memcmp(buffer, dltSerialHeader, sizeof(dltSerialHeader)) == 0) { /* serial header found */ msg->found_serialheader = 1; buffer += sizeof(dltSerialHeader); length -= (unsigned int)sizeof(dltSerialHeader); } else { /* serial header not found */ msg->found_serialheader = 0; if (resync) { /* resync if necessary */ msg->resync_offset = 0; do { if (memcmp(buffer + msg->resync_offset, dltSerialHeader, sizeof(dltSerialHeader)) == 0) { /* serial header found */ msg->found_serialheader = 1; buffer += sizeof(dltSerialHeader); length -= (unsigned int)sizeof(dltSerialHeader); break; } msg->resync_offset++; } while ((sizeof(dltSerialHeader) + (size_t)msg->resync_offset) <= length); /* Set new start offset */ if (msg->resync_offset > 0) { /* Resyncing connection */ buffer += msg->resync_offset; length -= (unsigned int)msg->resync_offset; } } } /* check that standard header fits buffer */ if (length < sizeof(DltStandardHeader)) /* dlt_log(LOG_ERR, "Length smaller than standard header!\n"); */ return DLT_MESSAGE_ERROR_SIZE; memcpy(msg->headerbuffer + sizeof(DltStorageHeader), buffer, sizeof(DltStandardHeader)); /* set ptrs to structures */ msg->storageheader = (DltStorageHeader *)msg->headerbuffer; msg->standardheader = (DltStandardHeader *)(msg->headerbuffer + sizeof(DltStorageHeader)); /* calculate complete size of headers */ extra_size = (uint32_t) (DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp) + (DLT_IS_HTYP_UEH(msg->standardheader->htyp) ? sizeof(DltExtendedHeader) : 0)); msg->headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + extra_size); msg->datasize = (uint32_t) DLT_BETOH_16(msg->standardheader->len) - msg->headersize + (uint32_t) sizeof(DltStorageHeader); /* calculate complete size of payload */ int32_t temp_datasize; temp_datasize = DLT_BETOH_16(msg->standardheader->len) - (int32_t) msg->headersize + (int32_t) sizeof(DltStorageHeader); /* check data size */ if (temp_datasize < 0) { dlt_vlog(LOG_WARNING, "Plausibility check failed. Complete message size too short (%d)!\n", temp_datasize); return DLT_MESSAGE_ERROR_CONTENT; } else { msg->datasize = (uint32_t) temp_datasize; } /* check if verbose mode is on*/ if (verbose) { dlt_vlog(LOG_DEBUG, "BufferLength=%u, HeaderSize=%u, DataSize=%u\n", length, msg->headersize, msg->datasize); } /* load standard header extra parameters and Extended header if used */ if (extra_size > 0) { if (length < (msg->headersize - sizeof(DltStorageHeader))) return DLT_MESSAGE_ERROR_SIZE; memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader), buffer + sizeof(DltStandardHeader), (size_t)extra_size); /* set extended header ptr and get standard header extra parameters */ if (DLT_IS_HTYP_UEH(msg->standardheader->htyp)) msg->extendedheader = (DltExtendedHeader *)(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp)); else msg->extendedheader = NULL; dlt_message_get_extraparameters(msg, verbose); } /* check if payload fits length */ if (length < (msg->headersize - sizeof(DltStorageHeader) + msg->datasize)) /* dlt_log(LOG_ERR,"length does not fit!\n"); */ return DLT_MESSAGE_ERROR_SIZE; /* free last used memory for buffer */ if (msg->databuffer) { if (msg->datasize > msg->databuffersize) { free(msg->databuffer); msg->databuffer = (uint8_t *)malloc(msg->datasize); msg->databuffersize = msg->datasize; } } else { /* get new memory for buffer */ msg->databuffer = (uint8_t *)malloc(msg->datasize); msg->databuffersize = msg->datasize; } if (msg->databuffer == NULL) { dlt_vlog(LOG_WARNING, "Cannot allocate memory for payload buffer of size %u!\n", msg->datasize); return DLT_MESSAGE_ERROR_UNKNOWN; } /* load payload data from buffer */ memcpy(msg->databuffer, buffer + (msg->headersize - sizeof(DltStorageHeader)), msg->datasize); return DLT_MESSAGE_ERROR_OK; } DltReturnValue dlt_message_get_extraparameters(DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (msg == NULL) return DLT_RETURN_WRONG_PARAMETER; if (DLT_IS_HTYP_WEID(msg->standardheader->htyp)) memcpy(msg->headerextra.ecu, msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader), DLT_ID_SIZE); if (DLT_IS_HTYP_WSID(msg->standardheader->htyp)) { memcpy(&(msg->headerextra.seid), msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0), DLT_SIZE_WSID); msg->headerextra.seid = DLT_BETOH_32(msg->headerextra.seid); } if (DLT_IS_HTYP_WTMS(msg->standardheader->htyp)) { memcpy(&(msg->headerextra.tmsp), msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0) + (DLT_IS_HTYP_WSID(msg->standardheader->htyp) ? DLT_SIZE_WSID : 0), DLT_SIZE_WTMS); msg->headerextra.tmsp = DLT_BETOH_32(msg->headerextra.tmsp); } return DLT_RETURN_OK; } DltReturnValue dlt_message_set_extraparameters(DltMessage *msg, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (msg == NULL) return DLT_RETURN_WRONG_PARAMETER; if (DLT_IS_HTYP_WEID(msg->standardheader->htyp)) memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader), msg->headerextra.ecu, DLT_ID_SIZE); if (DLT_IS_HTYP_WSID(msg->standardheader->htyp)) { msg->headerextra.seid = DLT_HTOBE_32(msg->headerextra.seid); memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0), &(msg->headerextra.seid), DLT_SIZE_WSID); } if (DLT_IS_HTYP_WTMS(msg->standardheader->htyp)) { msg->headerextra.tmsp = DLT_HTOBE_32(msg->headerextra.tmsp); memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0) + (DLT_IS_HTYP_WSID(msg->standardheader->htyp) ? DLT_SIZE_WSID : 0), &(msg->headerextra.tmsp), DLT_SIZE_WTMS); } return DLT_RETURN_OK; } DltReturnValue dlt_file_init(DltFile *file, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* initalise structure parameters */ file->handle = NULL; file->counter = 0; file->counter_total = 0; file->index = NULL; file->filter = NULL; file->filter_counter = 0; file->file_position = 0; file->position = 0; file->error_messages = 0; return dlt_message_init(&(file->msg), verbose); } DltReturnValue dlt_file_set_filter(DltFile *file, DltFilter *filter, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* set filter */ file->filter = filter; return DLT_RETURN_OK; } DltReturnValue dlt_file_read_header(DltFile *file, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* Loop until storage header is found */ while (1) { /* load header from file */ if (fread(file->msg.headerbuffer, sizeof(DltStorageHeader) + sizeof(DltStandardHeader), 1, file->handle) != 1) { if (!feof(file->handle)) dlt_log(LOG_WARNING, "Cannot read header from file!\n"); else dlt_log(LOG_DEBUG, "Reached end of file\n"); return DLT_RETURN_ERROR; } /* set ptrs to structures */ file->msg.storageheader = (DltStorageHeader *)file->msg.headerbuffer; file->msg.standardheader = (DltStandardHeader *)(file->msg.headerbuffer + sizeof(DltStorageHeader)); /* check id of storage header */ if (dlt_check_storageheader(file->msg.storageheader) != DLT_RETURN_TRUE) { /* Shift the position back to the place where it stared to read + 1 */ if (fseek(file->handle, (long) (1 - (sizeof(DltStorageHeader) + sizeof(DltStandardHeader))), SEEK_CUR) < 0) { dlt_log(LOG_WARNING, "DLT storage header pattern not found!\n"); return DLT_RETURN_ERROR; } } else { /* storage header is found */ break; } } /* calculate complete size of headers */ file->msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp) + (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0)); /* calculate complete size of payload */ int32_t temp_datasize; temp_datasize = DLT_BETOH_16(file->msg.standardheader->len) + (int32_t) sizeof(DltStorageHeader) - (int32_t) file->msg.headersize; /* check data size */ if (temp_datasize < 0) { dlt_vlog(LOG_WARNING, "Plausibility check failed. Complete message size too short! (%d)\n", temp_datasize); return DLT_RETURN_ERROR; } else { file->msg.datasize = (uint32_t) temp_datasize; } /* check if verbose mode is on */ if (verbose) { dlt_vlog(LOG_DEBUG, "HeaderSize=%u, DataSize=%u\n", file->msg.headersize, file->msg.datasize); } return DLT_RETURN_OK; } DltReturnValue dlt_file_read_header_raw(DltFile *file, int resync, int verbose) { char dltSerialHeaderBuffer[DLT_ID_SIZE]; PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* check if serial header exists, ignore if found */ if (fread(dltSerialHeaderBuffer, sizeof(dltSerialHeaderBuffer), 1, file->handle) != 1) { /* cannot read serial header, not enough data available in file */ if (!feof(file->handle)) dlt_log(LOG_WARNING, "Cannot read header from file!\n"); return DLT_RETURN_ERROR; } if (memcmp(dltSerialHeaderBuffer, dltSerialHeader, sizeof(dltSerialHeader)) == 0) { /* serial header found */ /* nothing to do continue reading */ } else { /* serial header not found */ if (resync) { /* increase error counter */ file->error_messages++; /* resync to serial header */ do { memmove(dltSerialHeaderBuffer, dltSerialHeaderBuffer + 1, sizeof(dltSerialHeader) - 1); if (fread(dltSerialHeaderBuffer + 3, 1, 1, file->handle) != 1) /* cannot read any data, perhaps end of file reached */ return DLT_RETURN_ERROR; if (memcmp(dltSerialHeaderBuffer, dltSerialHeader, sizeof(dltSerialHeader)) == 0) /* serial header synchronised */ break; } while (1); } else /* go back to last file position */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) { return DLT_RETURN_ERROR; } } /* load header from file */ if (fread(file->msg.headerbuffer + sizeof(DltStorageHeader), sizeof(DltStandardHeader), 1, file->handle) != 1) { if (!feof(file->handle)) dlt_log(LOG_WARNING, "Cannot read header from file!\n"); return DLT_RETURN_ERROR; } /* set ptrs to structures */ file->msg.storageheader = (DltStorageHeader *)file->msg.headerbuffer; /* this points now to a empty storage header (filled with '0') */ file->msg.standardheader = (DltStandardHeader *)(file->msg.headerbuffer + sizeof(DltStorageHeader)); /* Skip storage header field, fill this field with '0' */ memset(file->msg.storageheader, 0, sizeof(DltStorageHeader)); /* Set storage header */ dlt_set_storageheader(file->msg.storageheader, DLT_COMMON_DUMMY_ECUID); /* no check for storage header id*/ /* calculate complete size of headers */ file->msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp) + (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0)); /* calculate complete size of payload */ int32_t temp_datasize; temp_datasize = DLT_BETOH_16(file->msg.standardheader->len) + (int32_t) sizeof(DltStorageHeader) - (int32_t) file->msg.headersize; /* check data size */ if (temp_datasize < 0) { dlt_vlog(LOG_WARNING, "Plausibility check failed. Complete message size too short! (%d)\n", temp_datasize); return DLT_RETURN_ERROR; } else { file->msg.datasize = (uint32_t) temp_datasize; } /* check if verbose mode is on */ if (verbose) { dlt_vlog(LOG_DEBUG, "HeaderSize=%u, DataSize=%u\n", file->msg.headersize, file->msg.datasize); } return DLT_RETURN_OK; } DltReturnValue dlt_file_read_header_extended(DltFile *file, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* load standard header extra parameters if used */ if (DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp)) { if (fread(file->msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader), DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp), 1, file->handle) != 1) { dlt_log(LOG_WARNING, "Cannot read standard header extra parameters from file!\n"); return DLT_RETURN_ERROR; } dlt_message_get_extraparameters(&(file->msg), verbose); } /* load Extended header if used */ if (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) == 0) /* there is nothing to be loaded */ return DLT_RETURN_OK; if (fread(file->msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp), (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0), 1, file->handle) != 1) { dlt_log(LOG_WARNING, "Cannot read extended header from file!\n"); return DLT_RETURN_ERROR; } /* set extended header ptr */ if (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp)) file->msg.extendedheader = (DltExtendedHeader *)(file->msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp)); else file->msg.extendedheader = NULL; return DLT_RETURN_OK; } DltReturnValue dlt_file_read_data(DltFile *file, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* free last used memory for buffer */ if (file->msg.databuffer && (file->msg.databuffersize < file->msg.datasize)) { free(file->msg.databuffer); file->msg.databuffer = NULL; } if (file->msg.databuffer == NULL) { /* get new memory for buffer */ file->msg.databuffer = (uint8_t *)malloc(file->msg.datasize); file->msg.databuffersize = file->msg.datasize; } if (file->msg.databuffer == NULL) { dlt_vlog(LOG_WARNING, "Cannot allocate memory for payload buffer of size %u!\n", file->msg.datasize); return DLT_RETURN_ERROR; } /* load payload data from file */ if (fread(file->msg.databuffer, file->msg.datasize, 1, file->handle) != 1) { if (file->msg.datasize != 0) { dlt_vlog(LOG_WARNING, "Cannot read payload data from file of size %u!\n", file->msg.datasize); return DLT_RETURN_ERROR; } } return DLT_RETURN_OK; } DltReturnValue dlt_file_open(DltFile *file, const char *filename, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((file == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* reset counters */ file->counter = 0; file->counter_total = 0; file->position = 0; file->file_position = 0; file->file_length = 0; file->error_messages = 0; if (file->handle) fclose(file->handle); /* open dlt file */ file->handle = fopen(filename, "rb"); if (file->handle == NULL) { dlt_vlog(LOG_WARNING, "File %s cannot be opened!\n", filename); return DLT_RETURN_ERROR; } if (0 != fseek(file->handle, 0, SEEK_END)) { dlt_vlog(LOG_WARNING, "dlt_file_open: Seek failed to 0,SEEK_END"); return DLT_RETURN_ERROR; } file->file_length = ftell(file->handle); if (0 != fseek(file->handle, 0, SEEK_SET)) { dlt_vlog(LOG_WARNING, "dlt_file_open: Seek failed to 0,SEEK_SET"); return DLT_RETURN_ERROR; } if (verbose) /* print file length */ dlt_vlog(LOG_DEBUG, "File is %" PRIu64 "bytes long\n", file->file_length); return DLT_RETURN_OK; } DltReturnValue dlt_file_read(DltFile *file, int verbose) { long *ptr; int found = DLT_RETURN_OK; if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; if (verbose) dlt_vlog(LOG_DEBUG, "%s: Message %d:\n", __func__, file->counter_total); /* allocate new memory for index if number of messages exceeds a multiple of DLT_COMMON_INDEX_ALLOC (e.g.: 1000) */ if (file->counter % DLT_COMMON_INDEX_ALLOC == 0) { ptr = (long *)malloc(((file->counter / DLT_COMMON_INDEX_ALLOC) + 1) * DLT_COMMON_INDEX_ALLOC * sizeof(long)); if (ptr == NULL) return DLT_RETURN_ERROR; if (file->index) { memcpy(ptr, file->index, (size_t)(file->counter) * sizeof(long)); free(file->index); } file->index = ptr; } /* set to end of last succesful read message, because of conflicting calls to dlt_file_read and dlt_file_message */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) { dlt_vlog(LOG_WARNING, "Seek failed to file_position %" PRIu64 "\n", file->file_position); return DLT_RETURN_ERROR; } /* get file position at start of DLT message */ if (verbose) dlt_vlog(LOG_INFO, "Position in file: %" PRIu64 "\n", file->file_position); /* read header */ if (dlt_file_read_header(file, verbose) < DLT_RETURN_OK) { /* go back to last position in file */ fseek(file->handle, file->file_position, SEEK_SET); return DLT_RETURN_ERROR; } if (file->filter) { /* read the extended header if filter is enabled and extended header exists */ if (dlt_file_read_header_extended(file, verbose) < DLT_RETURN_OK) { /* go back to last position in file */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) dlt_vlog(LOG_WARNING, "Seek to last file pos failed!\n"); return DLT_RETURN_ERROR; } /* check the filters if message is used */ if (dlt_message_filter_check(&(file->msg), file->filter, verbose) == DLT_RETURN_TRUE) { /* filter matched, consequently store current message */ /* store index pointer to message position in DLT file */ file->index[file->counter] = file->file_position; file->counter++; file->position = file->counter - 1; found = DLT_RETURN_TRUE; } /* skip payload data */ if (fseek(file->handle, file->msg.datasize, SEEK_CUR) != 0) { /* go back to last position in file */ dlt_vlog(LOG_WARNING, "Seek failed to skip payload data of size %u!\n", file->msg.datasize); if (0 != fseek(file->handle, file->file_position, SEEK_SET)) dlt_log(LOG_WARNING, "Seek back also failed!\n"); return DLT_RETURN_ERROR; } } else { /* filter is disabled */ /* skip additional header parameters and payload data */ if (fseek(file->handle, (long) (file->msg.headersize - sizeof(DltStorageHeader) - sizeof(DltStandardHeader) + file->msg.datasize), SEEK_CUR)) { dlt_vlog(LOG_WARNING, "Seek failed to skip extra header and payload data from file of size %u!\n", file->msg.headersize - (int32_t)sizeof(DltStorageHeader) - (int32_t)sizeof(DltStandardHeader) + file->msg.datasize); /* go back to last position in file */ if (fseek(file->handle, file->file_position, SEEK_SET)) dlt_log(LOG_WARNING, "Seek back also failed!\n"); return DLT_RETURN_ERROR; } /* store index pointer to message position in DLT file */ file->index[file->counter] = file->file_position; file->counter++; file->position = file->counter - 1; found = DLT_RETURN_TRUE; } /* increase total message counter */ file->counter_total++; /* store position to next message */ file->file_position = ftell(file->handle); return found; } DltReturnValue dlt_file_read_raw(DltFile *file, int resync, int verbose) { int found = DLT_RETURN_OK; long *ptr; if (verbose) dlt_vlog(LOG_DEBUG, "%s: Message %d:\n", __func__, file->counter_total); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* allocate new memory for index if number of messages exceeds a multiple of DLT_COMMON_INDEX_ALLOC (e.g.: 1000) */ if (file->counter % DLT_COMMON_INDEX_ALLOC == 0) { ptr = (long *)malloc(((file->counter / DLT_COMMON_INDEX_ALLOC) + 1) * DLT_COMMON_INDEX_ALLOC * sizeof(long)); if (ptr == NULL) return DLT_RETURN_ERROR; if (file->index) { memcpy(ptr, file->index, (size_t)(file->counter) * sizeof(long)); free(file->index); } file->index = ptr; } /* set to end of last successful read message, because of conflicting calls to dlt_file_read and dlt_file_message */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) return DLT_RETURN_ERROR; /* get file position at start of DLT message */ if (verbose) dlt_vlog(LOG_DEBUG, "Position in file: %" PRIu64 "\n", file->file_position); /* read header */ if (dlt_file_read_header_raw(file, resync, verbose) < DLT_RETURN_OK) { /* go back to last position in file */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) dlt_log(LOG_WARNING, "dlt_file_read_raw, fseek failed 1\n"); return DLT_RETURN_ERROR; } /* read the extended header if filter is enabled and extended header exists */ if (dlt_file_read_header_extended(file, verbose) < DLT_RETURN_OK) { /* go back to last position in file */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) dlt_log(LOG_WARNING, "dlt_file_read_raw, fseek failed 2\n"); return DLT_RETURN_ERROR; } if (dlt_file_read_data(file, verbose) < DLT_RETURN_OK) { /* go back to last position in file */ if (0 != fseek(file->handle, file->file_position, SEEK_SET)) dlt_log(LOG_WARNING, "dlt_file_read_raw, fseek failed 3\n"); return DLT_RETURN_ERROR; } /* store index pointer to message position in DLT file */ file->index[file->counter] = file->file_position; file->counter++; file->position = file->counter - 1; found = DLT_RETURN_TRUE; /* increase total message counter */ file->counter_total++; /* store position to next message */ file->file_position = ftell(file->handle); return found; } DltReturnValue dlt_file_close(DltFile *file, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; if (file->handle) fclose(file->handle); file->handle = NULL; return DLT_RETURN_OK; } DltReturnValue dlt_file_message(DltFile *file, int index, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* check if message is in range */ if (index < 0 || index >= file->counter) { dlt_vlog(LOG_WARNING, "Message %d out of range!\r\n", index); return DLT_RETURN_WRONG_PARAMETER; } /* seek to position in file */ if (fseek(file->handle, file->index[index], SEEK_SET) != 0) { dlt_vlog(LOG_WARNING, "Seek to message %d to position %ld failed!\r\n", index, file->index[index]); return DLT_RETURN_ERROR; } /* read all header and payload */ if (dlt_file_read_header(file, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (dlt_file_read_header_extended(file, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; if (dlt_file_read_data(file, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; /* set current position in file */ file->position = index; return DLT_RETURN_OK; } DltReturnValue dlt_file_free(DltFile *file, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if (file == NULL) return DLT_RETURN_WRONG_PARAMETER; /* delete index lost if exists */ if (file->index) free(file->index); file->index = NULL; /* close file */ if (file->handle) fclose(file->handle); file->handle = NULL; return dlt_message_free(&(file->msg), verbose); } void dlt_log_set_level(int level) { if ((level < 0) || (level > LOG_DEBUG)) { if (logging_level < LOG_WARNING) logging_level = LOG_WARNING; dlt_vlog(LOG_WARNING, "Wrong parameter for level: %d\n", level); } else { logging_level = level; } } void dlt_log_set_filename(const char *filename) { /* check nullpointer */ if (filename == NULL) { dlt_log(LOG_WARNING, "Wrong parameter: filename is NULL\n"); return; } strncpy(logging_filename, filename, NAME_MAX); logging_filename[NAME_MAX] = 0; } #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC void dlt_log_set_fifo_basedir(const char *pipe_dir) { strncpy(dltFifoBaseDir, pipe_dir, DLT_PATH_MAX); dltFifoBaseDir[DLT_PATH_MAX - 1] = 0; } #endif #ifdef DLT_SHM_ENABLE void dlt_log_set_shm_name(const char *env_shm_name) { strncpy(dltShmName, env_shm_name, NAME_MAX); dltShmName[NAME_MAX] = 0; } #endif void dlt_print_with_attributes(bool state) { print_with_attributes = state; } DltReturnValue dlt_log_init(int mode) { return dlt_log_init_multiple_logfiles_support((DltLoggingMode)mode, false, 0, 0); } DltReturnValue dlt_log_init_multiple_logfiles_support(const DltLoggingMode mode, const bool enable_multiple_logfiles, const int logging_file_size, const int logging_files_max_size) { if ((mode < DLT_LOG_TO_CONSOLE) || (mode > DLT_LOG_DROPPED)) { dlt_vlog(LOG_WARNING, "Wrong parameter for mode: %d\n", mode); return DLT_RETURN_WRONG_PARAMETER; } logging_mode = mode; if (logging_mode != DLT_LOG_TO_FILE) { return DLT_RETURN_OK; } if (enable_multiple_logfiles) { dlt_user_printf("configure dlt logging using file limits\n"); int result = dlt_log_init_multiple_logfiles(logging_file_size, logging_files_max_size); if (result == DLT_RETURN_OK) { return DLT_RETURN_OK; } dlt_user_printf("dlt logging for limits fails with error code=%d, use logging without limits as fallback\n", result); return dlt_log_init_single_logfile(); } else { dlt_user_printf("configure dlt logging without file limits\n"); return dlt_log_init_single_logfile(); } } DltReturnValue dlt_log_init_single_logfile() { /* internal logging to file */ errno = 0; logging_handle = fopen(logging_filename, "a"); if (logging_handle == NULL) { dlt_user_printf("Internal log file %s cannot be opened, error: %s\n", logging_filename, strerror(errno)); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_log_init_multiple_logfiles(const int logging_file_size, const int logging_files_max_size) { char path_logging_filename[PATH_MAX + 1]; strncpy(path_logging_filename, logging_filename, PATH_MAX); path_logging_filename[PATH_MAX] = 0; const char *directory = dirname(path_logging_filename); if (directory[0]) { char basename_logging_filename[NAME_MAX + 1]; strncpy(basename_logging_filename, logging_filename, NAME_MAX); basename_logging_filename[NAME_MAX] = 0; const char *file_name = basename(basename_logging_filename); char filename_base[NAME_MAX]; if (!dlt_extract_base_name_without_ext(file_name, filename_base, sizeof(filename_base))) return DLT_RETURN_ERROR; const char *filename_ext = get_filename_ext(file_name); if (!filename_ext) return DLT_RETURN_ERROR; DltReturnValue result = multiple_files_buffer_init( &multiple_files_ring_buffer, directory, logging_file_size, logging_files_max_size, false, true, filename_base, filename_ext); return result; } return DLT_RETURN_ERROR; } void dlt_log_free(void) { if (logging_mode == DLT_LOG_TO_FILE) { if (dlt_is_log_in_multiple_files_active()) { dlt_log_free_multiple_logfiles(); } else { dlt_log_free_single_logfile(); } } } void dlt_log_free_single_logfile() { if (logging_handle) fclose(logging_handle); } void dlt_log_free_multiple_logfiles() { if (DLT_RETURN_ERROR == multiple_files_buffer_free(&multiple_files_ring_buffer)) return; // reset indicator of multiple files usage multiple_files_ring_buffer.ohandle = -1; } int dlt_user_printf(const char *format, ...) { if (format == NULL) return -1; va_list args; va_start(args, format); int ret = 0; switch (logging_mode) { case DLT_LOG_TO_CONSOLE: case DLT_LOG_TO_SYSLOG: case DLT_LOG_TO_FILE: case DLT_LOG_DROPPED: default: ret = vfprintf(stdout, format, args); break; case DLT_LOG_TO_STDERR: ret = vfprintf(stderr, format, args); break; } va_end(args); return ret; } DltReturnValue dlt_log(int prio, char *s) { static const char asSeverity[LOG_DEBUG + 2][11] = { "EMERGENCY", "ALERT ", "CRITICAL ", "ERROR ", "WARNING ", "NOTICE ", "INFO ", "DEBUG ", " " }; static const char sFormatString[] = "[%5u.%06u]~DLT~%5d~%s~%s"; struct timespec sTimeSpec; if (s == NULL) return DLT_RETURN_WRONG_PARAMETER; if (logging_level < prio) return DLT_RETURN_OK; if ((prio < 0) || (prio > LOG_DEBUG)) prio = LOG_DEBUG + 1; clock_gettime(CLOCK_MONOTONIC, &sTimeSpec); switch (logging_mode) { case DLT_LOG_TO_CONSOLE: /* log to stdout */ fprintf(stdout, sFormatString, (unsigned int)sTimeSpec.tv_sec, (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s); fflush(stdout); break; case DLT_LOG_TO_STDERR: /* log to stderr */ fprintf(stderr, sFormatString, (unsigned int)sTimeSpec.tv_sec, (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s); break; case DLT_LOG_TO_SYSLOG: /* log to syslog */ #if !defined (__WIN32__) && !defined(_MSC_VER) openlog("DLT", LOG_PID, LOG_DAEMON); syslog(prio, sFormatString, (unsigned int)sTimeSpec.tv_sec, (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s); closelog(); #endif break; case DLT_LOG_TO_FILE: /* log to file */ if (dlt_is_log_in_multiple_files_active()) { dlt_log_multiple_files_write(sFormatString, (unsigned int)sTimeSpec.tv_sec, (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s); } else if (logging_handle) { fprintf(logging_handle, sFormatString, (unsigned int)sTimeSpec.tv_sec, (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s); fflush(logging_handle); } break; case DLT_LOG_DROPPED: default: break; } return DLT_RETURN_OK; } DltReturnValue dlt_vlog(int prio, const char *format, ...) { char outputString[2048] = { 0 }; /* TODO: what is a reasonable string length here? */ va_list args; if (format == NULL) return DLT_RETURN_WRONG_PARAMETER; if (logging_level < prio) return DLT_RETURN_OK; va_start(args, format); vsnprintf(outputString, 2047, format, args); va_end(args); dlt_log(prio, outputString); return DLT_RETURN_OK; } DltReturnValue dlt_vnlog(int prio, size_t size, const char *format, ...) { char *outputString = NULL; va_list args; if (format == NULL) return DLT_RETURN_WRONG_PARAMETER; if ((logging_level < prio) || (size == 0)) return DLT_RETURN_OK; if ((outputString = (char *)calloc(size + 1, sizeof(char))) == NULL) return DLT_RETURN_ERROR; va_start(args, format); vsnprintf(outputString, size, format, args); va_end(args); dlt_log(prio, outputString); free(outputString); outputString = NULL; return DLT_RETURN_OK; } DltReturnValue dlt_receiver_init(DltReceiver *receiver, int fd, DltReceiverType type, int buffersize) { if (NULL == receiver) return DLT_RETURN_WRONG_PARAMETER; receiver->fd = fd; receiver->type = type; /** Reuse the receiver buffer if it exists and the buffer size * is not changed. If not, free the old one and allocate a new buffer. */ if ((NULL != receiver->buffer) && ( buffersize != receiver->buffersize)) { free(receiver->buffer); receiver->buffer = NULL; } if (NULL == receiver->buffer) { receiver->lastBytesRcvd = 0; receiver->bytesRcvd = 0; receiver->totalBytesRcvd = 0; receiver->buf = NULL; receiver->backup_buf = NULL; receiver->buffer = (char *)calloc(1, (size_t)buffersize); receiver->buffersize = (uint32_t)buffersize; } if (NULL == receiver->buffer) { dlt_log(LOG_ERR, "allocate memory for receiver buffer failed.\n"); return DLT_RETURN_ERROR; } else { receiver->buf = receiver->buffer; } return DLT_RETURN_OK; } DltReturnValue dlt_receiver_init_global_buffer(DltReceiver *receiver, int fd, DltReceiverType type, char **buffer) { if (receiver == NULL) return DLT_RETURN_WRONG_PARAMETER; if (*buffer == NULL) { /* allocating the buffer once and using it for all application receivers * by keeping allocated buffer in app_recv_buffer global handle */ *buffer = (char *)malloc(DLT_RECEIVE_BUFSIZE); if (*buffer == NULL) return DLT_RETURN_ERROR; } receiver->lastBytesRcvd = 0; receiver->bytesRcvd = 0; receiver->totalBytesRcvd = 0; receiver->buffersize = DLT_RECEIVE_BUFSIZE; receiver->fd = fd; receiver->type = type; receiver->buffer = *buffer; receiver->backup_buf = NULL; receiver->buf = receiver->buffer; return DLT_RETURN_OK; } DltReturnValue dlt_receiver_free(DltReceiver *receiver) { if (receiver == NULL) return DLT_RETURN_WRONG_PARAMETER; if (receiver->buffer) free(receiver->buffer); if (receiver->backup_buf) free(receiver->backup_buf); receiver->buffer = NULL; receiver->buf = NULL; receiver->backup_buf = NULL; return DLT_RETURN_OK; } DltReturnValue dlt_receiver_free_global_buffer(DltReceiver *receiver) { if (receiver == NULL) return DLT_RETURN_WRONG_PARAMETER; if (receiver->backup_buf) free(receiver->backup_buf); receiver->buffer = NULL; receiver->buf = NULL; receiver->backup_buf = NULL; return DLT_RETURN_OK; } int dlt_receiver_receive(DltReceiver *receiver) { socklen_t addrlen; if (receiver == NULL) return -1; if (receiver->buffer == NULL) return -1; receiver->buf = (char *)receiver->buffer; receiver->lastBytesRcvd = receiver->bytesRcvd; if ((receiver->lastBytesRcvd) && (receiver->backup_buf != NULL)) { memcpy(receiver->buf, receiver->backup_buf, (size_t)receiver->lastBytesRcvd); free(receiver->backup_buf); receiver->backup_buf = NULL; } if (receiver->type == DLT_RECEIVE_SOCKET) /* wait for data from socket */ receiver->bytesRcvd = recv(receiver->fd, receiver->buf + receiver->lastBytesRcvd, receiver->buffersize - (uint32_t) receiver->lastBytesRcvd, 0); else if (receiver->type == DLT_RECEIVE_FD) /* wait for data from fd */ receiver->bytesRcvd = read(receiver->fd, receiver->buf + receiver->lastBytesRcvd, receiver->buffersize - (uint32_t) receiver->lastBytesRcvd); else { /* receiver->type == DLT_RECEIVE_UDP_SOCKET */ /* wait for data from UDP socket */ addrlen = sizeof(receiver->addr); receiver->bytesRcvd = recvfrom(receiver->fd, receiver->buf + receiver->lastBytesRcvd, receiver->buffersize - receiver->lastBytesRcvd, 0, (struct sockaddr *)&(receiver->addr), &addrlen); } if (receiver->bytesRcvd <= 0) { receiver->bytesRcvd = 0; return receiver->bytesRcvd; } /* if */ receiver->totalBytesRcvd += receiver->bytesRcvd; receiver->bytesRcvd += receiver->lastBytesRcvd; return receiver->bytesRcvd; } DltReturnValue dlt_receiver_remove(DltReceiver *receiver, int size) { if (receiver == NULL) return DLT_RETURN_WRONG_PARAMETER; if (receiver->buf == NULL) return DLT_RETURN_ERROR; if ((size > receiver->bytesRcvd) || (size <= 0)) { receiver->buf = receiver->buf + receiver->bytesRcvd; receiver->bytesRcvd = 0; return DLT_RETURN_WRONG_PARAMETER; } receiver->bytesRcvd = receiver->bytesRcvd - size; receiver->buf = receiver->buf + size; return DLT_RETURN_OK; } DltReturnValue dlt_receiver_move_to_begin(DltReceiver *receiver) { if (receiver == NULL) return DLT_RETURN_WRONG_PARAMETER; if ((receiver->buffer == NULL) || (receiver->buf == NULL)) return DLT_RETURN_ERROR; if ((receiver->buffer != receiver->buf) && (receiver->bytesRcvd != 0)) { receiver->backup_buf = calloc((size_t)(receiver->bytesRcvd + 1), sizeof(char)); if (receiver->backup_buf == NULL) dlt_vlog(LOG_WARNING, "Can't allocate memory for backup buf, there will be atleast" "one corrupted message for fd[%d] \n", receiver->fd); else memcpy(receiver->backup_buf, receiver->buf, (size_t)receiver->bytesRcvd); } return DLT_RETURN_OK; } int dlt_receiver_check_and_get(DltReceiver *receiver, void *dest, unsigned int to_get, unsigned int flags) { size_t min_size = (size_t)to_get; uint8_t *src = NULL; if (flags & DLT_RCV_SKIP_HEADER) min_size += sizeof(DltUserHeader); if (!receiver || (receiver->bytesRcvd < (int32_t) min_size) || !receiver->buf || !dest) return DLT_RETURN_WRONG_PARAMETER; src = (uint8_t *)receiver->buf; if (flags & DLT_RCV_SKIP_HEADER) src += sizeof(DltUserHeader); memcpy(dest, src, to_get); if (flags & DLT_RCV_REMOVE) { if (dlt_receiver_remove(receiver, (int)min_size) != DLT_RETURN_OK) { dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n"); return DLT_RETURN_ERROR; } } return to_get; } DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char *ecu) { #if !defined(_MSC_VER) struct timeval tv; #endif if ((storageheader == NULL) || (ecu == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* get time of day */ #if defined(_MSC_VER) time(&(storageheader->seconds)); #else gettimeofday(&tv, NULL); #endif /* prepare storage header */ storageheader->pattern[0] = 'D'; storageheader->pattern[1] = 'L'; storageheader->pattern[2] = 'T'; storageheader->pattern[3] = 0x01; dlt_set_id(storageheader->ecu, ecu); /* Set current time */ #if defined(_MSC_VER) storageheader->microseconds = 0; #else storageheader->seconds = (uint32_t) tv.tv_sec; /* value is long */ storageheader->microseconds = (int32_t) tv.tv_usec; /* value is long */ #endif return DLT_RETURN_OK; } DltReturnValue dlt_check_rcv_data_size(int received, int required) { int _ret = DLT_RETURN_OK; if (received < required) { dlt_vlog(LOG_WARNING, "%s: Received data not complete\n", __func__); _ret = DLT_RETURN_ERROR; } return _ret; } DltReturnValue dlt_check_storageheader(DltStorageHeader *storageheader) { if (storageheader == NULL) return DLT_RETURN_WRONG_PARAMETER; return ((storageheader->pattern[0] == 'D') && (storageheader->pattern[1] == 'L') && (storageheader->pattern[2] == 'T') && (storageheader->pattern[3] == 1)) ? DLT_RETURN_TRUE : DLT_RETURN_OK; } DltReturnValue dlt_buffer_init_static_server(DltBuffer *buf, const unsigned char *ptr, uint32_t size) { if ((buf == NULL) || (ptr == NULL)) return DLT_RETURN_WRONG_PARAMETER; DltBufferHead *head; /* Init parameters */ buf->shm = (unsigned char *)ptr; buf->min_size = size; buf->max_size = size; buf->step_size = 0; /* Init pointers */ head = (DltBufferHead *)buf->shm; head->read = 0; head->write = 0; head->count = 0; buf->mem = (unsigned char *)(buf->shm + sizeof(DltBufferHead)); buf->size = (unsigned int) buf->min_size - (unsigned int) sizeof(DltBufferHead); /* clear memory */ memset(buf->mem, 0, buf->size); dlt_vlog(LOG_DEBUG, "%s: Buffer: Size %u, Start address %lX\n", __func__, buf->size, (unsigned long)buf->mem); return DLT_RETURN_OK; /* OK */ } DltReturnValue dlt_buffer_init_static_client(DltBuffer *buf, const unsigned char *ptr, uint32_t size) { if ((buf == NULL) || (ptr == NULL)) return DLT_RETURN_WRONG_PARAMETER; /* Init parameters */ buf->shm = (unsigned char *)ptr; buf->min_size = size; buf->max_size = size; buf->step_size = 0; /* Init pointers */ buf->mem = (unsigned char *)(buf->shm + sizeof(DltBufferHead)); buf->size = (uint32_t)(buf->min_size - sizeof(DltBufferHead)); dlt_vlog(LOG_DEBUG, "%s: Buffer: Size %u, Start address %lX\n", __func__, buf->size, (unsigned long)buf->mem); return DLT_RETURN_OK; /* OK */ } DltReturnValue dlt_buffer_init_dynamic(DltBuffer *buf, uint32_t min_size, uint32_t max_size, uint32_t step_size) { /*Do not DLT_SEM_LOCK inside here! */ DltBufferHead *head; /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; /* catch 0 logical errors */ if ((min_size == 0) || (max_size == 0) || (step_size == 0)) return DLT_RETURN_WRONG_PARAMETER; if (min_size > max_size) return DLT_RETURN_WRONG_PARAMETER; if (step_size > max_size) return DLT_RETURN_WRONG_PARAMETER; /* Init parameters */ buf->min_size = min_size; buf->max_size = max_size; buf->step_size = step_size; /* allocat memory */ buf->shm = malloc(buf->min_size); if (buf->shm == NULL) { dlt_vlog(LOG_EMERG, "%s: Buffer: Cannot allocate %u bytes\n", __func__, buf->min_size); return DLT_RETURN_ERROR; } /* Init pointers */ head = (DltBufferHead *)buf->shm; head->read = 0; head->write = 0; head->count = 0; buf->mem = (unsigned char *)(buf->shm + sizeof(DltBufferHead)); if (buf->min_size < (uint32_t)sizeof(DltBufferHead)) { dlt_vlog(LOG_ERR, "%s: min_size is too small [%u]\n", __func__, buf->min_size); return DLT_RETURN_WRONG_PARAMETER; } buf->size = (uint32_t) (buf->min_size - sizeof(DltBufferHead)); dlt_vlog(LOG_DEBUG, "%s: Buffer: Size %u, Start address %lX\n", __func__, buf->size, (unsigned long)buf->mem); /* clear memory */ memset(buf->mem, 0, (size_t)buf->size); return DLT_RETURN_OK; /* OK */ } DltReturnValue dlt_buffer_free_static(DltBuffer *buf) { /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; if (buf->mem == NULL) { /* buffer not initialized */ dlt_vlog(LOG_WARNING, "%s: Buffer: Buffer not initialized\n", __func__); return DLT_RETURN_ERROR; /* ERROR */ } return DLT_RETURN_OK; } DltReturnValue dlt_buffer_free_dynamic(DltBuffer *buf) { /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; if (buf->shm == NULL) { /* buffer not initialized */ dlt_vlog(LOG_WARNING, "%s: Buffer: Buffer not initialized\n", __func__); return DLT_RETURN_ERROR; /* ERROR */ } free(buf->shm); buf->shm = NULL; buf->mem = NULL; return DLT_RETURN_OK; } void dlt_buffer_write_block(DltBuffer *buf, int *write, const unsigned char *data, unsigned int size) { /* catch null pointer */ if ((buf != NULL) && (write != NULL) && (data != NULL)) { if (size <= buf->size){ if (( (unsigned int) (*write ) + size) <= buf->size) { /* write one block */ memcpy(buf->mem + *write, data, size); *write += (int) size; } else { /* when (*write) = buf->size, write only the second block * and update write position correspondingly. */ if((unsigned int) (*write) <= buf->size) { /* write two blocks */ memcpy(buf->mem + *write, data, buf->size - (unsigned int) (*write)); memcpy(buf->mem, data + buf->size - *write, size - buf->size + (unsigned int) (*write)); *write += (int) (size - buf->size); } } } else { dlt_vlog(LOG_WARNING, "%s: Write error: ring buffer to small\n", __func__); } } else { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); } } void dlt_buffer_read_block(DltBuffer *buf, int *read, unsigned char *data, unsigned int size) { /* catch nullpointer */ if ((buf != NULL) && (read != NULL) && (data != NULL)) { if (((unsigned int)(*read) + size) <= buf->size) { /* read one block */ memcpy(data, buf->mem + *read, size); *read += (int)size; } else { /* when (*read) = buf->size, read only the second block * and update read position correspondingly. */ if ((unsigned int)(*read) <= buf->size) { /* read two blocks */ memcpy(data, buf->mem + *read, buf->size - (unsigned int)(*read)); memcpy(data + buf->size - *read, buf->mem, size - buf->size + (unsigned int)(*read)); *read += (int) (size - buf->size); } } } else { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); } } int dlt_buffer_check_size(DltBuffer *buf, int needed) { if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; if ((buf->size + sizeof(DltBufferHead) + (size_t) needed) > buf->max_size) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } int dlt_buffer_increase_size(DltBuffer *buf) { DltBufferHead *head, *new_head; unsigned char *new_ptr; /* catch null pointer */ if (buf == NULL) { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* check size */ if (buf->step_size == 0) /* cannot increase size */ return DLT_RETURN_ERROR; /* check size */ if ((buf->size + sizeof(DltBufferHead) + buf->step_size) > buf->max_size) /* max size reached, do not increase */ return DLT_RETURN_ERROR; /* allocate new buffer */ new_ptr = malloc(buf->size + sizeof(DltBufferHead) + buf->step_size); if (new_ptr == NULL) { dlt_vlog(LOG_WARNING, "%s: Buffer: Cannot increase size because allocate %u bytes failed\n", __func__, buf->min_size); return DLT_RETURN_ERROR; } /* copy data */ head = (DltBufferHead *)buf->shm; new_head = (DltBufferHead *)new_ptr; if (head->read < head->write) { memcpy(new_ptr + sizeof(DltBufferHead), buf->mem + head->read, (size_t)(head->write - head->read)); new_head->read = 0; new_head->write = head->write - head->read; new_head->count = head->count; } else { memcpy(new_ptr + sizeof(DltBufferHead), buf->mem + head->read, buf->size - (uint32_t)(head->read)); memcpy(new_ptr + sizeof(DltBufferHead) + buf->size - head->read, buf->mem, (size_t)head->write); new_head->read = 0; new_head->write = (int)(buf->size) + head->write - head->read; new_head->count = head->count; } /* free old data */ free(buf->shm); /* update data */ buf->shm = new_ptr; buf->mem = new_ptr + sizeof(DltBufferHead); buf->size += buf->step_size; dlt_vlog(LOG_DEBUG, "%s: Buffer: Size increased to %u bytes with start address %lX\n", __func__, buf->size + (int32_t)sizeof(DltBufferHead), (unsigned long)buf->mem); return DLT_RETURN_OK; /* OK */ } int dlt_buffer_minimize_size(DltBuffer *buf) { unsigned char *new_ptr; /* catch null pointer */ if (buf == NULL) { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if ((buf->size + sizeof(DltBufferHead)) == buf->min_size) /* already minimized */ return DLT_RETURN_OK; /* allocate new buffer */ new_ptr = malloc(buf->min_size); if (new_ptr == NULL) { dlt_vlog(LOG_WARNING, "%s: Buffer: Cannot set to min size of %u bytes\n", __func__, buf->min_size); return DLT_RETURN_ERROR; } /* free old data */ free(buf->shm); /* update data */ buf->shm = new_ptr; buf->mem = new_ptr + sizeof(DltBufferHead); buf->size = (uint32_t)(buf->min_size - sizeof(DltBufferHead)); /* reset pointers and counters */ ((int *)(buf->shm))[0] = 0; /* pointer to write memory */ ((int *)(buf->shm))[1] = 0; /* pointer to read memory */ ((int *)(buf->shm))[2] = 0; /* number of packets */ dlt_vlog(LOG_DEBUG, "%s: Buffer: Buffer minimized to Size %u bytes with start address %lX\n", __func__, buf->size, (unsigned long)buf->mem); /* clear memory */ memset(buf->mem, 0, buf->size); return DLT_RETURN_OK; /* OK */ } int dlt_buffer_reset(DltBuffer *buf) { /* catch null pointer */ if (buf == NULL) { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } dlt_vlog(LOG_WARNING, "%s: Buffer: Buffer reset triggered. Size: %u, Start address: %lX\n", __func__, buf->size, (unsigned long)buf->mem); /* reset pointers and counters */ ((int *)(buf->shm))[0] = 0; /* pointer to write memory */ ((int *)(buf->shm))[1] = 0; /* pointer to read memory */ ((int *)(buf->shm))[2] = 0; /* number of packets */ /* clear memory */ memset(buf->mem, 0, buf->size); return DLT_RETURN_OK; /* OK */ } DltReturnValue dlt_buffer_push(DltBuffer *buf, const unsigned char *data, unsigned int size) { return dlt_buffer_push3(buf, data, size, 0, 0, 0, 0); } int dlt_buffer_push3(DltBuffer *buf, const unsigned char *data1, unsigned int size1, const unsigned char *data2, unsigned int size2, const unsigned char *data3, unsigned int size3) { int free_size; int write, read, count; DltBufferBlockHead head; /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; if (buf->shm == NULL) { /* buffer not initialised */ dlt_vlog(LOG_ERR, "%s: Buffer: Buffer not initialized\n", __func__); return DLT_RETURN_ERROR; /* ERROR */ } /* get current write pointer */ write = ((int *)(buf->shm))[0]; read = ((int *)(buf->shm))[1]; count = ((int *)(buf->shm))[2]; /* check pointers */ if (((unsigned int)read > buf->size) || ((unsigned int)write > buf->size)) { dlt_vlog(LOG_ERR, "%s: Buffer: Pointer out of range. Read: %d, Write: %d, Size: %u\n", __func__, read, write, buf->size); dlt_buffer_reset(buf); return DLT_RETURN_ERROR; /* ERROR */ } /* calculate free size */ if (read > write) free_size = read - write; else if (count && (write == read)) free_size = 0; else free_size = (int)buf->size - write + read; /* check size */ while (free_size < (int) (sizeof(DltBufferBlockHead) + size1 + size2 + size3)) { /* try to increase size if possible */ if (dlt_buffer_increase_size(buf)) /* increase size is not possible */ /*dlt_log(LOG_ERR, "Buffer: Buffer is full\n"); */ return DLT_RETURN_ERROR; /* ERROR */ /* update pointers */ write = ((int *)(buf->shm))[0]; read = ((int *)(buf->shm))[1]; /* update free size */ if (read > write) free_size = read - write; else if (count && (write == read)) free_size = 0; else free_size = buf->size - write + read; } /* set header */ strncpy(head.head, DLT_BUFFER_HEAD, 4); head.head[3] = 0; head.status = 2; head.size = (int)(size1 + size2 + size3); /* write data */ dlt_buffer_write_block(buf, &write, (unsigned char *)&head, sizeof(DltBufferBlockHead)); if (size1) dlt_buffer_write_block(buf, &write, data1, size1); if (size2) dlt_buffer_write_block(buf, &write, data2, size2); if (size3) dlt_buffer_write_block(buf, &write, data3, size3); /* update global shm pointers */ ((int *)(buf->shm))[0] = write; /* set new write pointer */ ((int *)(buf->shm))[2] += 1; /* increase counter */ return DLT_RETURN_OK; /* OK */ } int dlt_buffer_get(DltBuffer *buf, unsigned char *data, int max_size, int delete) { int used_size; int write, read, count; char head_compare[] = DLT_BUFFER_HEAD; DltBufferBlockHead head; /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; if (buf->shm == NULL) { /* shm not initialised */ dlt_vlog(LOG_ERR, "%s: Buffer: SHM not initialized\n", __func__); return DLT_RETURN_ERROR; /* ERROR */ } /* get current write pointer */ write = ((int *)(buf->shm))[0]; read = ((int *)(buf->shm))[1]; count = ((int *)(buf->shm))[2]; /* check pointers */ if (((unsigned int)read > buf->size) || ((unsigned int)write > buf->size) || (count < 0)) { dlt_vlog(LOG_ERR, "%s: Buffer: Pointer out of range. Read: %d, Write: %d, Count: %d, Size: %u\n", __func__, read, write, count, buf->size); dlt_buffer_reset(buf); return DLT_RETURN_ERROR; /* ERROR */ } /* check if data is in there */ if (count == 0) { if (write != read) { dlt_vlog(LOG_ERR, "%s: Buffer: SHM should be empty, but is not. Read: %d, Write: %d\n", __func__, read, write); dlt_buffer_reset(buf); } return DLT_RETURN_ERROR; /* ERROR */ } /* calculate used size */ if (write > read) used_size = write - read; else used_size = (int)buf->size - read + write; /* first check size */ if (used_size < (int)(sizeof(DltBufferBlockHead))) { dlt_vlog(LOG_ERR, "%s: Buffer: Used size is smaller than buffer block header size. Used size: %d\n", __func__, used_size); dlt_buffer_reset(buf); return DLT_RETURN_ERROR; /* ERROR */ } /* read header */ dlt_buffer_read_block(buf, &read, (unsigned char *)&head, sizeof(DltBufferBlockHead)); /* check header */ if (memcmp((unsigned char *)(head.head), head_compare, sizeof(head_compare)) != 0) { dlt_vlog(LOG_ERR, "%s: Buffer: Header head check failed\n", __func__); dlt_buffer_reset(buf); return DLT_RETURN_ERROR; /* ERROR */ } if (head.status != 2) { dlt_vlog(LOG_ERR, "%s: Buffer: Header status check failed\n", __func__); dlt_buffer_reset(buf); return DLT_RETURN_ERROR; /* ERROR */ } /* second check size */ if (used_size < ((int)sizeof(DltBufferBlockHead) + head.size)) { dlt_vlog(LOG_ERR, "%s: Buffer: Used size is smaller than buffer block header size And read header size. Used size: %d\n", __func__, used_size); dlt_buffer_reset(buf); return DLT_RETURN_ERROR; /* ERROR */ } /* third check size */ if (max_size && (head.size > max_size)) dlt_vlog(LOG_WARNING, "%s: Buffer: Max size is smaller than read header size. Max size: %d\n", __func__, max_size); /* nothing to do but data does not fit provided buffer */ if ((data != NULL) && max_size) { /* read data */ dlt_buffer_read_block(buf, &read, data, (unsigned int)head.size); if (delete) /* update buffer pointers */ ((int *)(buf->shm))[1] = read; /* set new read pointer */ } else if (delete) { if ((unsigned int)(read + head.size) <= buf->size) ((int *)(buf->shm))[1] = read + head.size; /* set new read pointer */ else ((int *)(buf->shm))[1] = read + head.size - (int)buf->size; /* set new read pointer */ } if (delete) { ((int *)(buf->shm))[2] -= 1; /* decrease counter */ if (((int *)(buf->shm))[2] == 0) /* try to minimize size */ dlt_buffer_minimize_size(buf); } return head.size; /* OK */ } int dlt_buffer_pull(DltBuffer *buf, unsigned char *data, int max_size) { return dlt_buffer_get(buf, data, max_size, 1); } int dlt_buffer_copy(DltBuffer *buf, unsigned char *data, int max_size) { return dlt_buffer_get(buf, data, max_size, 0); } int dlt_buffer_remove(DltBuffer *buf) { return dlt_buffer_get(buf, 0, 0, 1); } void dlt_buffer_info(DltBuffer *buf) { /* check nullpointer */ if (buf == NULL) { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); return; } dlt_vlog(LOG_DEBUG, "Buffer: Available size: %u, Buffer: Buffer full start address: %lX, Buffer: Buffer start address: %lX\n", buf->size, (unsigned long)buf->shm, (unsigned long)buf->mem); } void dlt_buffer_status(DltBuffer *buf) { int write, read, count; /* check nullpointer */ if (buf == NULL) { dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__); return; } /* check if buffer available */ if (buf->shm == NULL) return; write = ((int *)(buf->shm))[0]; read = ((int *)(buf->shm))[1]; count = ((int *)(buf->shm))[2]; dlt_vlog(LOG_DEBUG, "Buffer: Write: %d, Read: %d, Count: %d\n", write, read, count); } uint32_t dlt_buffer_get_total_size(DltBuffer *buf) { /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; return buf->max_size; } int dlt_buffer_get_used_size(DltBuffer *buf) { int write, read, count; /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; /* check if buffer available */ if (buf->shm == NULL) return DLT_RETURN_OK; write = ((int *)(buf->shm))[0]; read = ((int *)(buf->shm))[1]; count = ((int *)(buf->shm))[2]; if (count == 0) return DLT_RETURN_OK; if (write > read) return write - read; return (int)buf->size - read + write; } int dlt_buffer_get_message_count(DltBuffer *buf) { /* catch null pointer */ if (buf == NULL) return DLT_RETURN_WRONG_PARAMETER; /* check if buffer available */ if (buf->shm == NULL) return DLT_RETURN_OK; return ((int *)(buf->shm))[2]; } #if !defined (__WIN32__) DltReturnValue dlt_setup_serial(int fd, speed_t speed) { # if !defined (__WIN32__) && !defined(_MSC_VER) struct termios config; if (isatty(fd) == 0) return DLT_RETURN_ERROR; if (tcgetattr(fd, &config) < 0) return DLT_RETURN_ERROR; /* Input flags - Turn off input processing * convert break to null byte, no CR to NL translation, * no NL to CR translation, don't mark parity errors or breaks * no input parity check, don't strip high bit off, * no XON/XOFF software flow control */ config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); /* Output flags - Turn off output processing * no CR to NL translation, no NL to CR-NL translation, * no NL to CR translation, no column 0 CR suppression, * no Ctrl-D suppression, no fill characters, no case mapping, * no local output processing * * config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | * ONOCR | ONOEOT| OFILL | OLCUC | OPOST); */ config.c_oflag = 0; /* No line processing: * echo off, echo newline off, canonical mode off, * extended input processing off, signal chars off */ config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); /* Turn off character processing * clear current char size mask, no parity checking, * no output processing, force 8 bit input */ config.c_cflag &= ~(CSIZE | PARENB); config.c_cflag |= CS8; /* One input byte is enough to return from read() * Inter-character timer off */ config.c_cc[VMIN] = 1; config.c_cc[VTIME] = 0; /* Communication speed (simple version, using the predefined * constants) */ if ((cfsetispeed(&config, speed) < 0) || (cfsetospeed(&config, speed) < 0)) return DLT_RETURN_ERROR; /* Finally, apply the configuration */ if (tcsetattr(fd, TCSAFLUSH, &config) < 0) return DLT_RETURN_ERROR; return DLT_RETURN_OK; # else return DLT_RETURN_ERROR; # endif } speed_t dlt_convert_serial_speed(int baudrate) { # if !defined (__WIN32__) && !defined(_MSC_VER) && !defined(__CYGWIN__) speed_t ret; switch (baudrate) { case 50: { ret = B50; break; } case 75: { ret = B75; break; } case 110: { ret = B110; break; } case 134: { ret = B134; break; } case 150: { ret = B150; break; } case 200: { ret = B200; break; } case 300: { ret = B300; break; } case 600: { ret = B600; break; } case 1200: { ret = B1200; break; } case 1800: { ret = B1800; break; } case 2400: { ret = B2400; break; } case 4800: { ret = B4800; break; } case 9600: { ret = B9600; break; } case 19200: { ret = B19200; break; } case 38400: { ret = B38400; break; } case 57600: { ret = B57600; break; } case 115200: { ret = B115200; break; } # ifdef __linux__ case 230400: { ret = B230400; break; } case 460800: { ret = B460800; break; } case 500000: { ret = B500000; break; } case 576000: { ret = B576000; break; } case 921600: { ret = B921600; break; } case 1000000: { ret = B1000000; break; } case 1152000: { ret = B1152000; break; } case 1500000: { ret = B1500000; break; } case 2000000: { ret = B2000000; break; } case 2500000: { ret = B2500000; break; } case 3000000: { ret = B3000000; break; } case 3500000: { ret = B3500000; break; } case 4000000: { ret = B4000000; break; } # endif /* __linux__ */ default: { ret = B115200; break; } } return ret; # else return 0; # endif } #endif void dlt_get_version(char *buf, size_t size) { if ((buf == NULL) && (size > 0)) { dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n"); return; } /* Clang does not like these macros, because they are not reproducable */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdate-time" snprintf(buf, size, "DLT Package Version: %s %s, Package Revision: %s, build on %s %s\n%s %s %s %s\n", _DLT_PACKAGE_VERSION, _DLT_PACKAGE_VERSION_STATE, _DLT_PACKAGE_REVISION, __DATE__, __TIME__, _DLT_SYSTEMD_ENABLE, _DLT_SYSTEMD_WATCHDOG_ENABLE, _DLT_TEST_ENABLE, _DLT_SHM_ENABLE); #pragma GCC diagnostic pop } void dlt_get_major_version(char *buf, size_t size) { if ((buf == NULL) && (size > 0)) { dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n"); return; } snprintf(buf, size, "%s", _DLT_PACKAGE_MAJOR_VERSION); } void dlt_get_minor_version(char *buf, size_t size) { if ((buf == NULL) && (size > 0)) { dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n"); return; } snprintf(buf, size, "%s", _DLT_PACKAGE_MINOR_VERSION); } uint32_t dlt_uptime(void) { #if defined (__WIN32__) || defined(_MSC_VER) return (uint32_t)(GetTickCount() * 10); /* GetTickCount() return DWORD */ #else struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) return (uint32_t)ts.tv_sec * 10000 + (uint32_t)ts.tv_nsec / 100000; /* in 0.1 ms = 100 us */ else return 0; #endif } DltReturnValue dlt_message_print_header(DltMessage *message, char *text, uint32_t size, int verbose) { if ((message == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("%s\n", text); return DLT_RETURN_OK; } DltReturnValue dlt_message_print_hex(DltMessage *message, char *text, uint32_t size, int verbose) { if ((message == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("%s ", text); if (dlt_message_payload(message, text, size, DLT_OUTPUT_HEX, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("[%s]\n", text); return DLT_RETURN_OK; } DltReturnValue dlt_message_print_ascii(DltMessage *message, char *text, uint32_t size, int verbose) { if ((message == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("%s ", text); if (dlt_message_payload(message, text, size, DLT_OUTPUT_ASCII, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("[%s]\n", text); return DLT_RETURN_OK; } DltReturnValue dlt_message_print_mixed_plain(DltMessage *message, char *text, uint32_t size, int verbose) { if ((message == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("%s \n", text); if (dlt_message_payload(message, text, size, DLT_OUTPUT_MIXED_FOR_PLAIN, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("[%s]\n", text); return DLT_RETURN_OK; } DltReturnValue dlt_message_print_mixed_html(DltMessage *message, char *text, uint32_t size, int verbose) { if ((message == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("%s \n", text); if (dlt_message_payload(message, text, size, DLT_OUTPUT_MIXED_FOR_HTML, verbose) < DLT_RETURN_OK) return DLT_RETURN_ERROR; dlt_user_printf("[%s]\n", text); return DLT_RETURN_OK; } DltReturnValue dlt_message_argument_print(DltMessage *msg, uint32_t type_info, uint8_t **ptr, int32_t *datalength, char *text, size_t textlength, int byteLength, int __attribute__((unused)) verbose) { /* check null pointers */ if ((msg == NULL) || (ptr == NULL) || (datalength == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; uint16_t length = 0, length2 = 0, length3 = 0; uint8_t value8u = 0; uint16_t value16u = 0, value16u_tmp = 0; uint32_t value32u = 0, value32u_tmp = 0; uint64_t value64u = 0, value64u_tmp = 0; int8_t value8i = 0; int16_t value16i = 0, value16i_tmp = 0; int32_t value32i = 0, value32i_tmp = 0; int64_t value64i = 0, value64i_tmp = 0; float32_t value32f = 0, value32f_tmp = 0; int32_t value32f_tmp_int32i = 0, value32f_tmp_int32i_swaped = 0; float64_t value64f = 0, value64f_tmp = 0; int64_t value64f_tmp_int64i = 0, value64f_tmp_int64i_swaped = 0; uint32_t quantisation_tmp = 0; // pointer to the value string char* value_text = text; // pointer to the "unit" attribute string, if there is one (only for *INT and FLOAT*) const uint8_t* unit_text_src = NULL; // length of the "unit" attribute string, if there is one (only for *INT and FLOAT*) size_t unit_text_len = 0; /* apparently this makes no sense but needs to be done to prevent compiler warning. * This variable is only written by DLT_MSG_READ_VALUE macro in if (type_info & DLT_TYPE_INFO_FIXP) * case but never read anywhere */ quantisation_tmp += quantisation_tmp; if ((type_info & DLT_TYPE_INFO_STRG) && (((type_info & DLT_TYPE_INFO_SCOD) == DLT_SCOD_ASCII) || ((type_info & DLT_TYPE_INFO_SCOD) == DLT_SCOD_UTF8))) { /* string type or utf8-encoded string type */ if (byteLength < 0) { DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); } else { length = (uint16_t)byteLength; } if (type_info & DLT_TYPE_INFO_VARI) { DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length2 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); if ((*datalength) < length2) return DLT_RETURN_ERROR; if (print_with_attributes) { // Print "name" attribute, if we have one with non-zero size. if (length2 > 1) { snprintf(text, textlength, "%s:", *ptr); value_text += length2+1-1; // +1 for ":" and -1 for NUL textlength -= length2+1-1; } } *ptr += length2; *datalength -= length2; } DLT_MSG_READ_STRING(value_text, *ptr, *datalength, textlength, length); if ((*datalength) < 0) return DLT_RETURN_ERROR; } else if (type_info & DLT_TYPE_INFO_BOOL) { /* Boolean type */ if (type_info & DLT_TYPE_INFO_VARI) { DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length2 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); if ((*datalength) < length2) return DLT_RETURN_ERROR; if (print_with_attributes) { // Print "name" attribute, if we have one with non-zero size. if (length2 > 1) { snprintf(text, textlength, "%s:", *ptr); value_text += length2+1-1; // +1 for ":" and -1 for NUL textlength -= length2+1-2; } } *ptr += length2; *datalength -= length2; } value8u = 0; DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */ if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "%d", value8u); } else if ((type_info & DLT_TYPE_INFO_UINT) && (DLT_SCOD_BIN == (type_info & DLT_TYPE_INFO_SCOD))) { if (DLT_TYLE_8BIT == (type_info & DLT_TYPE_INFO_TYLE)) { DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */ if ((*datalength) < 0) return DLT_RETURN_ERROR; char binary[10] = { '\0' }; /* e.g.: "0b1100 0010" */ int i; for (i = (1 << 7); i > 0; i >>= 1) { if ((1 << 3) == i) strcat(binary, " "); strcat(binary, (i == (value8u & i)) ? "1" : "0"); } snprintf(value_text, textlength, "0b%s", binary); } if (DLT_TYLE_16BIT == (type_info & DLT_TYPE_INFO_TYLE)) { DLT_MSG_READ_VALUE(value16u, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; char binary[20] = { '\0' }; /* e.g.: "0b1100 0010 0011 0110" */ int i; for (i = (1 << 15); i > 0; i >>= 1) { if (((1 << 3) == i) || ((1 << 7) == i) || ((1 << 11) == i)) strcat(binary, " "); strcat(binary, (i == (value16u & i)) ? "1" : "0"); } snprintf(value_text, textlength, "0b%s", binary); } } else if ((type_info & DLT_TYPE_INFO_UINT) && (DLT_SCOD_HEX == (type_info & DLT_TYPE_INFO_SCOD))) { if (DLT_TYLE_8BIT == (type_info & DLT_TYPE_INFO_TYLE)) { DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */ if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "0x%02x", value8u); } if (DLT_TYLE_16BIT == (type_info & DLT_TYPE_INFO_TYLE)) { DLT_MSG_READ_VALUE(value16u, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "0x%04x", value16u); } if (DLT_TYLE_32BIT == (type_info & DLT_TYPE_INFO_TYLE)) { DLT_MSG_READ_VALUE(value32u, *ptr, *datalength, uint32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "0x%08x", value32u); } if (DLT_TYLE_64BIT == (type_info & DLT_TYPE_INFO_TYLE)) { *ptr += 4; DLT_MSG_READ_VALUE(value32u, *ptr, *datalength, uint32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "0x%08x", value32u); *ptr -= 8; DLT_MSG_READ_VALUE(value32u, *ptr, *datalength, uint32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text + strlen(value_text), textlength - strlen(value_text), "%08x", value32u); *ptr += 4; } } else if ((type_info & DLT_TYPE_INFO_SINT) || (type_info & DLT_TYPE_INFO_UINT)) { /* signed or unsigned argument received */ if (type_info & DLT_TYPE_INFO_VARI) { DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length2 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length3 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); if ((*datalength) < length2) return DLT_RETURN_ERROR; if (print_with_attributes) { // Print "name" attribute, if we have one with non-zero size. if (length2 > 1) { snprintf(text, textlength, "%s:", *ptr); value_text += length2+1-1; // +1 for the ":", and -1 for nul textlength -= length2+1-1; } } *ptr += length2; *datalength -= length2; if ((*datalength) < length3) return DLT_RETURN_ERROR; // We want to add the "unit" attribute only after the value, so remember its pointer and length here. unit_text_src = *ptr; unit_text_len = length3; *ptr += length3; *datalength -= length3; } if (type_info & DLT_TYPE_INFO_FIXP) { DLT_MSG_READ_VALUE(quantisation_tmp, *ptr, *datalength, uint32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: case DLT_TYLE_16BIT: case DLT_TYLE_32BIT: { if ((*datalength) < 4) return DLT_RETURN_ERROR; *ptr += 4; *datalength -= 4; break; } case DLT_TYLE_64BIT: { if ((*datalength) < 8) return DLT_RETURN_ERROR; *ptr += 8; *datalength -= 8; break; } case DLT_TYLE_128BIT: { if ((*datalength) < 16) return DLT_RETURN_ERROR; *ptr += 16; *datalength -= 16; break; } default: { return DLT_RETURN_ERROR; } } } switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { if (type_info & DLT_TYPE_INFO_SINT) { value8i = 0; DLT_MSG_READ_VALUE(value8i, *ptr, *datalength, int8_t); /* No endian conversion necessary */ if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "%d", value8i); } else { value8u = 0; DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */ if ((*datalength) < 0) return DLT_RETURN_ERROR; snprintf(value_text, textlength, "%d", value8u); } break; } case DLT_TYLE_16BIT: { if (type_info & DLT_TYPE_INFO_SINT) { value16i = 0; value16i_tmp = 0; DLT_MSG_READ_VALUE(value16i_tmp, *ptr, *datalength, int16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; value16i = (int16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16i_tmp); snprintf(value_text, textlength, "%hd", value16i); } else { value16u = 0; value16u_tmp = 0; DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; value16u = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); snprintf(value_text, textlength, "%hu", value16u); } break; } case DLT_TYLE_32BIT: { if (type_info & DLT_TYPE_INFO_SINT) { value32i = 0; value32i_tmp = 0; DLT_MSG_READ_VALUE(value32i_tmp, *ptr, *datalength, int32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; value32i = (int32_t) DLT_ENDIAN_GET_32(msg->standardheader->htyp, (uint32_t)value32i_tmp); snprintf(value_text, textlength, "%d", value32i); } else { value32u = 0; value32u_tmp = 0; DLT_MSG_READ_VALUE(value32u_tmp, *ptr, *datalength, uint32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; value32u = DLT_ENDIAN_GET_32(msg->standardheader->htyp, value32u_tmp); snprintf(value_text, textlength, "%u", value32u); } break; } case DLT_TYLE_64BIT: { if (type_info & DLT_TYPE_INFO_SINT) { value64i = 0; value64i_tmp = 0; DLT_MSG_READ_VALUE(value64i_tmp, *ptr, *datalength, int64_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; value64i = (int64_t) DLT_ENDIAN_GET_64(msg->standardheader->htyp, (uint64_t)value64i_tmp); #if defined (__WIN32__) && !defined(_MSC_VER) snprintf(value_text, textlength, "%I64d", value64i); #else snprintf(value_text, textlength, "%" PRId64, value64i); #endif } else { value64u = 0; value64u_tmp = 0; DLT_MSG_READ_VALUE(value64u_tmp, *ptr, *datalength, uint64_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; value64u = DLT_ENDIAN_GET_64(msg->standardheader->htyp, value64u_tmp); #if defined (__WIN32__) && !defined(_MSC_VER) snprintf(value_text, textlength, "%I64u", value64u); #else snprintf(value_text, textlength, "%" PRIu64, value64u); #endif } break; } case DLT_TYLE_128BIT: { if (*datalength >= 16) dlt_print_hex_string(value_text, (int) textlength, *ptr, 16); if ((*datalength) < 16) return DLT_RETURN_ERROR; *ptr += 16; *datalength -= 16; break; } default: { return DLT_RETURN_ERROR; } } } else if (type_info & DLT_TYPE_INFO_FLOA) { /* float data argument */ if (type_info & DLT_TYPE_INFO_VARI) { DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length2 = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length3 = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); if ((*datalength) < length2) return DLT_RETURN_ERROR; if (print_with_attributes) { // Print "name" attribute, if we have one with non-zero size. if (length2 > 1) { snprintf(text, textlength, "%s:", *ptr); value_text += length2+1-1; // +1 for ":" and -1 for NUL textlength -= length2+1-1; } } *ptr += length2; *datalength -= length2; if ((*datalength) < length3) return DLT_RETURN_ERROR; // We want to add the "unit" attribute only after the value, so remember its pointer and length here. unit_text_src = *ptr; unit_text_len = length3; *ptr += length3; *datalength -= length3; } switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { if (*datalength >= 1) dlt_print_hex_string(value_text, (int) textlength, *ptr, 1); if ((*datalength) < 1) return DLT_RETURN_ERROR; *ptr += 1; *datalength -= 1; break; } case DLT_TYLE_16BIT: { if (*datalength >= 2) dlt_print_hex_string(value_text, (int) textlength, *ptr, 2); if ((*datalength) < 2) return DLT_RETURN_ERROR; *ptr += 2; *datalength -= 2; break; } case DLT_TYLE_32BIT: { if (sizeof(float32_t) == 4) { value32f = 0; value32f_tmp = 0; value32f_tmp_int32i = 0; value32f_tmp_int32i_swaped = 0; DLT_MSG_READ_VALUE(value32f_tmp, *ptr, *datalength, float32_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; memcpy(&value32f_tmp_int32i, &value32f_tmp, sizeof(float32_t)); value32f_tmp_int32i_swaped = (int32_t) DLT_ENDIAN_GET_32(msg->standardheader->htyp, (uint32_t)value32f_tmp_int32i); memcpy(&value32f, &value32f_tmp_int32i_swaped, sizeof(float32_t)); snprintf(value_text, textlength, "%g", value32f); } else { dlt_log(LOG_ERR, "Invalid size of float32_t\n"); return DLT_RETURN_ERROR; } break; } case DLT_TYLE_64BIT: { if (sizeof(float64_t) == 8) { value64f = 0; value64f_tmp = 0; value64f_tmp_int64i = 0; value64f_tmp_int64i_swaped = 0; DLT_MSG_READ_VALUE(value64f_tmp, *ptr, *datalength, float64_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; memcpy(&value64f_tmp_int64i, &value64f_tmp, sizeof(float64_t)); value64f_tmp_int64i_swaped = (int64_t) DLT_ENDIAN_GET_64(msg->standardheader->htyp, (uint64_t)value64f_tmp_int64i); memcpy(&value64f, &value64f_tmp_int64i_swaped, sizeof(float64_t)); #ifdef __arm__ snprintf(value_text, textlength, "ILLEGAL"); #else snprintf(value_text, textlength, "%g", value64f); #endif } else { dlt_log(LOG_ERR, "Invalid size of float64_t\n"); return DLT_RETURN_ERROR; } break; } case DLT_TYLE_128BIT: { if (*datalength >= 16) dlt_print_hex_string(value_text, textlength, *ptr, 16); if ((*datalength) < 16) return DLT_RETURN_ERROR; *ptr += 16; *datalength -= 16; break; } default: { return DLT_RETURN_ERROR; } } } else if (type_info & DLT_TYPE_INFO_RAWD) { /* raw data argument */ DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); if (type_info & DLT_TYPE_INFO_VARI) { DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length2 = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); if ((*datalength) < length2) return DLT_RETURN_ERROR; if (print_with_attributes) { // Print "name" attribute, if we have one with non-zero size. if (length2 > 1) { snprintf(text, textlength, "%s:", *ptr); value_text += length2+1-1; // +1 for ":" and -1 for NUL textlength -= length2+1-1; } } *ptr += length2; *datalength -= length2; } if ((*datalength) < length) return DLT_RETURN_ERROR; if (dlt_print_hex_string_delim(value_text, (int) textlength, *ptr, length, '\'') < DLT_RETURN_OK) return DLT_RETURN_ERROR; *ptr += length; *datalength -= length; } else if (type_info & DLT_TYPE_INFO_TRAI) { /* trace info argument */ DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t); if ((*datalength) < 0) return DLT_RETURN_ERROR; length = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp); DLT_MSG_READ_STRING(value_text, *ptr, *datalength, textlength, length); if ((*datalength) < 0) return DLT_RETURN_ERROR; } else { return DLT_RETURN_ERROR; } if (*datalength < 0) { dlt_log(LOG_ERR, "Payload of DLT message corrupted\n"); return DLT_RETURN_ERROR; } // Now write "unit" attribute, but only if it has more than only a nul-termination char. if (print_with_attributes) { if (unit_text_len > 1) { // 'value_text' still points to the +start+ of the value text size_t currLen = strlen(value_text); char* unitText = value_text + currLen; textlength -= currLen; snprintf(unitText, textlength, ":%s", unit_text_src); } } return DLT_RETURN_OK; } void dlt_check_envvar() { char *env_log_filename = getenv("DLT_LOG_FILENAME"); if (env_log_filename != NULL) dlt_log_set_filename(env_log_filename); char *env_log_level_str = getenv("DLT_LOG_LEVEL"); if (env_log_level_str != NULL) { int level = 0; if (sscanf(env_log_level_str, "%d", &level)) dlt_log_set_level(level); } char *env_log_mode = getenv("DLT_LOG_MODE"); if (env_log_mode != NULL) { int mode = 0; if (sscanf(env_log_mode, "%d", &mode)) dlt_log_init(mode); } #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC char *env_pipe_dir = getenv("DLT_PIPE_DIR"); if (env_pipe_dir != NULL) dlt_log_set_fifo_basedir(env_pipe_dir); else dlt_log_set_fifo_basedir(DLT_USER_IPC_PATH); #endif #ifdef DLT_SHM_ENABLE char *env_shm_name = getenv("DLT_SHM_NAME"); if (env_shm_name != NULL) dlt_log_set_shm_name(env_shm_name); #endif } int dlt_set_loginfo_parse_service_id(char *resp_text, uint32_t *service_id, uint8_t *service_opt) { int ret = -1; char get_log_info_tag[GET_LOG_INFO_LENGTH]; char service_opt_str[SERVICE_OPT_LENGTH]; if ((resp_text == NULL) || (service_id == NULL) || (service_opt == NULL)) return DLT_RETURN_ERROR; /* ascii type, syntax is 'get_log_info, ..' */ /* check target id */ strncpy(get_log_info_tag, "get_log_info", strlen("get_log_info") + 1); ret = memcmp((void *)resp_text, (void *)get_log_info_tag, sizeof(get_log_info_tag) - 1); if (ret == 0) { *service_id = DLT_SERVICE_ID_GET_LOG_INFO; /* reading the response mode from the resp_text. eg. option 7*/ service_opt_str[0] = *(resp_text + GET_LOG_INFO_LENGTH + 1); service_opt_str[1] = *(resp_text + GET_LOG_INFO_LENGTH + 2); service_opt_str[2] = 0; *service_opt = (uint8_t) atoi(service_opt_str); } return ret; } int16_t dlt_getloginfo_conv_ascii_to_uint16_t(char *rp, int *rp_count) { char num_work[5] = { 0 }; char *endptr; if ((rp == NULL) || (rp_count == NULL)) return -1; /* ------------------------------------------------------ * from: [89 13 ] -> to: ['+0x'1389\0] -> to num * ------------------------------------------------------ */ num_work[0] = *(rp + *rp_count + 3); num_work[1] = *(rp + *rp_count + 4); num_work[2] = *(rp + *rp_count + 0); num_work[3] = *(rp + *rp_count + 1); num_work[4] = 0; *rp_count += 6; return (uint16_t)strtol(num_work, &endptr, 16); } int16_t dlt_getloginfo_conv_ascii_to_int16_t(char *rp, int *rp_count) { char num_work[3] = { 0 }; char *endptr; if ((rp == NULL) || (rp_count == NULL)) return -1; /* ------------------------------------------------------ * from: [89 ] -> to: ['0x'89\0] -> to num * ------------------------------------------------------ */ num_work[0] = *(rp + *rp_count + 0); num_work[1] = *(rp + *rp_count + 1); num_work[2] = 0; *rp_count += 3; return (signed char)strtol(num_work, &endptr, 16); } void dlt_getloginfo_conv_ascii_to_string(char *rp, int *rp_count, char *wp, int len) { if ((rp == NULL ) || (rp_count == NULL ) || (wp == NULL )) return; /* ------------------------------------------------------ * from: [72 65 6d 6f ] -> to: [0x72,0x65,0x6d,0x6f,0x00] * ------------------------------------------------------ */ int count = dlt_getloginfo_conv_ascii_to_id(rp, rp_count, wp, len); *(wp + count) = '\0'; return; } int dlt_getloginfo_conv_ascii_to_id(char *rp, int *rp_count, char *wp, int len) { char number16[3] = { 0 }; char *endptr; int count; if ((rp == NULL) || (rp_count == NULL) || (wp == NULL)) return 0; /* ------------------------------------------------------ * from: [72 65 6d 6f ] -> to: [0x72,0x65,0x6d,0x6f] * ------------------------------------------------------ */ for (count = 0; count < len; count++) { number16[0] = *(rp + *rp_count + 0); number16[1] = *(rp + *rp_count + 1); *(wp + count) = (char) strtol(number16, &endptr, 16); *rp_count += 3; } return count; } void dlt_hex_ascii_to_binary(const char *ptr, uint8_t *binary, int *size) { char ch = *ptr; int pos = 0; binary[pos] = 0; int first = 1; int found; for (;;) { if (ch == 0) { *size = pos; return; } found = 0; if ((ch >= '0') && (ch <= '9')) { binary[pos] = (uint8_t) ((binary[pos] << 4) + (ch - '0')); found = 1; } else if ((ch >= 'A') && (ch <= 'F')) { binary[pos] = (uint8_t) ((binary[pos] << 4) + (ch - 'A' + 10)); found = 1; } else if ((ch >= 'a') && (ch <= 'f')) { binary[pos] = (uint8_t) ((binary[pos] << 4) + (ch - 'a' + 10)); found = 1; } if (found) { if (first) { first = 0; } else { first = 1; pos++; if (pos >= *size) return; binary[pos] = 0; } } ch = *(++ptr); } } DltReturnValue dlt_file_quick_parsing(DltFile *file, const char *filename, int type, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); int ret = DLT_RETURN_OK; char text[DLT_CONVERT_TEXTBUFSIZE] = { 0 }; if ((file == NULL) || (filename == NULL)) return DLT_RETURN_WRONG_PARAMETER; FILE *output = fopen(filename, "w+"); if (output == NULL) { dlt_vlog(LOG_ERR, "Cannot open output file %s for parsing\n", filename); return DLT_RETURN_ERROR; } while (ret >= DLT_RETURN_OK && file->file_position < file->file_length) { /* get file position at start of DLT message */ if (verbose) dlt_vlog(LOG_DEBUG, "Position in file: %" PRIu64 "\n", file->file_position); /* read all header and payload */ ret = dlt_file_read_header(file, verbose); if (ret < DLT_RETURN_OK) break; ret = dlt_file_read_header_extended(file, verbose); if (ret < DLT_RETURN_OK) break; ret = dlt_file_read_data(file, verbose); if (ret < DLT_RETURN_OK) break; if (file->filter) { /* check the filters if message is used */ ret = dlt_message_filter_check(&(file->msg), file->filter, verbose); if (ret != DLT_RETURN_TRUE) continue; } ret = dlt_message_header(&(file->msg), text, DLT_CONVERT_TEXTBUFSIZE, verbose); if (ret < DLT_RETURN_OK) break; fprintf(output, "%s", text); ret = dlt_message_payload(&(file->msg), text, DLT_CONVERT_TEXTBUFSIZE, type, verbose); if (ret < DLT_RETURN_OK) break; fprintf(output, "[%s]\n", text); /* store index pointer to message position in DLT file */ file->counter++; file->position = file->counter_total - 1; /* increase total message counter */ file->counter_total++; /* store position to next message */ file->file_position = ftell(file->handle); } /* while() */ fclose(output); return ret; } int dlt_execute_command(char *filename, char *command, ...) { va_list val; int argc; char **args = NULL; int ret = 0; if (command == NULL) return -1; /* Determine number of variadic arguments */ va_start(val, command); for (argc = 2; va_arg(val, char *) != NULL; argc++); va_end(val); /* Allocate args, put references to command */ args = (char **) malloc( (uint32_t) argc * sizeof(char*)); args[0] = command; va_start(val, command); for (int i = 0; args[i] != NULL; i++) args[i + 1] = va_arg(val, char *); va_end(val); /* Run command in child process */ pid_t pid = fork(); if (pid == 0) { /* child process */ /* Redirect output if required */ if (filename != NULL) { int fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) err(-1, "%s failed on open()", __func__); if (dup2(fd, STDOUT_FILENO) == -1) { close(fd); err(-1, "%s failed on dup2()", __func__); } close(fd); } /* Run command */ execvp(command, (char **)args); } else if (pid == -1) /* error in fork */ { ret = -1; } else { /* parent */ wait(&ret); } free(args); return ret; } char *get_filename_ext(const char *filename) { if (filename == NULL) { fprintf(stderr, "ERROR: %s: invalid arguments\n", __FUNCTION__); return NULL; } char *dot = strrchr(filename, '.'); return (!dot || dot == filename) ? NULL : dot; } bool dlt_extract_base_name_without_ext(const char* const abs_file_name, char* base_name, long base_name_len) { if (abs_file_name == NULL || base_name == NULL) return false; const char* last_separator = strrchr(abs_file_name, '.'); if (!last_separator) return false; long length = last_separator - abs_file_name; length = length > base_name_len ? base_name_len : length; strncpy(base_name, abs_file_name, length); base_name[length] = '\0'; return true; } void dlt_log_multiple_files_write(const char* format, ...) { char output_string[2048] = { 0 }; va_list args; va_start (args, format); vsnprintf(output_string, 2047, format, args); va_end (args); multiple_files_buffer_write(&multiple_files_ring_buffer, (unsigned char*)output_string, strlen(output_string)); } bool dlt_is_log_in_multiple_files_active() { return multiple_files_ring_buffer.ohandle > -1; } dlt-daemon-2.18.10/src/shared/dlt_common_cfg.h000066400000000000000000000115541446635226000211050ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_common_cfg.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_common_cfg.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_COMMON_CFG_H #define DLT_COMMON_CFG_H /*************/ /* Changable */ /*************/ /* Buffer length for temporary buffer */ #define DLT_COMMON_BUFFER_LENGTH 255 /* Number of ASCII chars to be printed in one line as HEX and as ASCII */ /* e.g. XX XX XX XX ABCD is DLT_COMMON_HEX_CHARS = 4 */ #define DLT_COMMON_HEX_CHARS 16 /* Length of line number */ #define DLT_COMMON_HEX_LINELEN 8 /* Length of one char */ #define DLT_COMMON_CHARLEN 1 /* Number of indices to be allocated at one, if no more indeces are left */ #define DLT_COMMON_INDEX_ALLOC 1000 /* If limited output is called, * this is the maximum number of characters to be printed out */ #define DLT_COMMON_ASCII_LIMIT_MAX_CHARS 20 /* This defines the dummy ECU ID set in storage header during import * of a message from a DLT file in RAW format (without storage header) */ #define DLT_COMMON_DUMMY_ECUID "ECU" /************************/ /* Don't change please! */ /************************/ /* ASCII value for space */ #define DLT_COMMON_ASCII_CHAR_SPACE 32 /* ASCII value for tilde */ #define DLT_COMMON_ASCII_CHAR_TILDE 126 /* ASCII value for lesser than */ #define DLT_COMMON_ASCII_CHAR_LT 60 #endif /* DLT_COMMON_CFG_H */ dlt-daemon-2.18.10/src/shared/dlt_config_file_parser.c000066400000000000000000000352201446635226000226050ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015, Advanced Driver Information Technology * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Christoph Lipka * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_config_file_parser.c */ #include "dlt_config_file_parser.h" #include #include #include #include #include #include "dlt_common.h" #include "dlt-daemon_cfg.h" /* internal defines */ #define DLT_CONFIG_FILE_NEW_SECTION 0x0a #define DLT_CONFIG_FILE_NEW_DATA 0x0b /* internal helper functions */ /** * dlt_config_file_trim_line * * Trim all whitespace from a string * * @param line String to remove whitespace from */ static void dlt_config_file_trim_line(char *line) { if (line == NULL) return; char *i = line; char *j = line; while (*j != '\0') { *i = *j++; if (!isspace(*i)) i++; } *i = '\0'; } /** * dlt_config_file_ignore_line * * Check if a line has to be ignored, because it contains a comment or is empty * * @param line Line of configuration file * @return 0 if ignore, -1 do not ignore */ static int dlt_config_file_ignore_line(char *line) { if ((line[0] == '#') || (line[0] == ';') || (line[0] == '\n') || (line[0] == '\0')) return 0; /* ignore */ else return -1; /* do not ignore */ } /** * dlt_config_file_is_section_name * * Check if section name already used * * @param file DltConfigFile * @param name Name of section * @return 0, section name not used, -1 section name already used */ static int dlt_config_file_is_section_name(DltConfigFile *file, char *name) { int i = 0; if ((file == NULL) || (name == NULL)) return -1; for (i = 0; i < file->num_sections; i++) { DltConfigFileSection *s = &file->sections[i]; if (strncmp(s->name, name, DLT_CONFIG_FILE_ENTRY_MAX_LEN) == 0) return -1; } return 0; /* section name not used */ } /** * dlt_config_file_set_section * * Store section in internal data structure * * @param file DltConfigFile * @param name Name of section * @return 0 on success, else -1 */ static int dlt_config_file_set_section(DltConfigFile *file, char *name) { int section = file->num_sections; /* check if adding another section would exceed max number of sections */ if (section >= DLT_CONFIG_FILE_SECTIONS_MAX) { dlt_log(LOG_WARNING, "Cannot store more sections\n"); return -1; /* reached max number of sections */ } /* do not store section with same name again */ if (dlt_config_file_is_section_name(file, name) != 0) { dlt_log(LOG_WARNING, "Cannot store section name again\n"); return -1; } DltConfigFileSection *s = &file->sections[section]; /* alloc data for entries */ s->name = calloc(sizeof(char), DLT_CONFIG_FILE_ENTRY_MAX_LEN + 1); if (s->name == NULL) { dlt_log(LOG_ERR, "Cannot allocate memory for internal data structure\n"); return -1; } s->keys = calloc(sizeof(char), DLT_CONFIG_FILE_ENTRY_MAX_LEN * DLT_CONFIG_FILE_KEYS_MAX + 1); if (s->keys == NULL) { free(s->name); s->name = NULL; dlt_log(LOG_ERR, "Cannot allocate memory for internal data structure\n"); return -1; } strncpy(file->sections[section].name, name, DLT_CONFIG_FILE_ENTRY_MAX_LEN); file->num_sections += 1; return 0; } /** * dlt_config_file_set_section_data * * Store data pair of a section * * @param file DltConfigFile * @param str1 string used for key * @param str2 string used for value * @return 0 on success, else -1 */ static int dlt_config_file_set_section_data(DltConfigFile *file, char *str1, char *str2) { DltConfigKeyData **tmp = NULL; if ((file == NULL) || (str1 == NULL) || (str2 == NULL)) return -1; DltConfigFileSection *s = &file->sections[file->num_sections - 1]; int key_number = s->num_entries; if (key_number + 1 >= DLT_CONFIG_FILE_KEYS_MAX) { dlt_log(LOG_WARNING, "Cannot store more keys in section\n"); return -1; /* reached max number of keys per section */ } /* copy data into structure */ strncpy(&s->keys[key_number * DLT_CONFIG_FILE_ENTRY_MAX_LEN], str1, DLT_CONFIG_FILE_ENTRY_MAX_LEN); if (s->list == NULL) { /* creating a list if it doesnt exists */ s->list = malloc(sizeof(DltConfigKeyData)); if (s->list == NULL) { dlt_log(LOG_WARNING, "Could not allocate initial memory to list \n"); return -1; } tmp = &s->list; } else { tmp = &s->list; while (*(tmp) != NULL) tmp = &(*tmp)->next; /* Adding new entry to the list */ *tmp = malloc(sizeof(DltConfigKeyData)); if (*tmp == NULL) { dlt_log(LOG_WARNING, "Could not allocate memory to list \n"); return -1; } } (*tmp)->key = strdup(str1); (*tmp)->data = strdup(str2); (*tmp)->next = NULL; s->num_entries += 1; return 0; } /** * dlt_config_file_has_section * * Check if a certain line in config file is a section header * * @param line Line in configuration file * @return 0 if section header, else -1 */ static int dlt_config_file_line_has_section(char *line) { (void)line; /* avoid compiler warnings */ if (line[0] == '[') /* section found */ return 0; else return -1; } /** * dlt_config_file_get_section_name_from_string * * Extract section name from line * * @param line Line in configuration file containing a section header * @param name Section name * @return 0 on success, else -1 */ static int dlt_config_file_get_section_name_from_string(char *line, char *name) { int i = 0; int j = 0; if ((line == NULL) || (name == NULL)) return -1; for (i = 0; i < DLT_CONFIG_FILE_ENTRY_MAX_LEN; i++) { if ((line[i] == '[') || isspace(line[i])) continue; else if ((line[i] == ']') || (line[i] == '\n') || (line[i] == '\0')) break; else name[j++] = line[i]; } return 0; } /** * dlt_config_file_get_key_value * * Get key and value from a line of configuration file * * @param line Line on configuration file * @param[out] str1 String to be used as key * @param[out] str2 String to be used as value * @return 0 on success, else -1 */ static int dlt_config_file_get_key_value(char *line, char *str1, char *str2) { char *delimiter = "="; char *ptr; char *save_ptr; if ((line == NULL) || (str1 == NULL) || (str2 == NULL)) return -1; ptr = strtok_r(line, delimiter, &save_ptr); if (ptr != NULL) { /* get key */ strncpy(str1, ptr, DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1); str1[DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1] = '\0'; } else { return -1; } ptr = strtok_r(NULL, delimiter, &save_ptr); if (ptr != NULL) { strncpy(str2, ptr, DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1); str2[DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1] = '\0'; } else { return -1; } return 0; } /** * dlt_config_file_read_line * * Read line from configuration file * * @param line Line from configuration file * @param[out] str1 String contains section header or key * @param[out] str2 String contains value or is empty * @return 0 on success, else -1 */ static int dlt_config_file_read_line(char *line, char *str1, char *str2) { if ((line == NULL) || (str1 == NULL) || (str2 == NULL)) return -1; /* reset values to zero */ memset(str1, 0, DLT_CONFIG_FILE_ENTRY_MAX_LEN); memset(str2, 0, DLT_CONFIG_FILE_ENTRY_MAX_LEN); /* check if line contains a section */ if ((dlt_config_file_line_has_section(line)) == 0) { /* retrieve section name */ if (dlt_config_file_get_section_name_from_string(line, str1) != 0) return -1; return DLT_CONFIG_FILE_NEW_SECTION; } /* copy strings as key value pair into str1, str2 */ if (dlt_config_file_get_key_value(line, str1, str2) != 0) return -1; return DLT_CONFIG_FILE_NEW_DATA; } /** * dlt_config_file_read_file * * Read configuration file line by line and fill internal structures * * @param file DltConfigFile * @param hdl FILE handle of opened configuration file */ static void dlt_config_file_read_file(DltConfigFile *file, FILE *hdl) { int ret = 0; char line[DLT_CONFIG_FILE_LINE_MAX_LEN] = { '\0' }; char str1[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' }; char str2[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' }; int line_number = 0; int is_section_valid = -1; /* to check if section name is given twice or invalid */ /* read configuration file line by line */ while (fgets(line, DLT_CONFIG_FILE_LINE_MAX_LEN, hdl) != NULL) { line_number++; /* ignore empty and comment lines */ if (dlt_config_file_ignore_line(line) == 0) continue; /* trim line end */ dlt_config_file_trim_line(line); /* parse content of line */ ret = dlt_config_file_read_line(line, str1, str2); switch (ret) { case DLT_CONFIG_FILE_NEW_SECTION: /* store str1 as new section */ is_section_valid = -1; if ((ret = dlt_config_file_set_section(file, str1)) == 0) is_section_valid = 0; break; case DLT_CONFIG_FILE_NEW_DATA: /* store str1 and str2 as new data for section */ if (is_section_valid == 0) ret = dlt_config_file_set_section_data(file, str1, str2); break; default: /* something is wrong with the line */ dlt_vlog(LOG_WARNING, "Line (%d) \"%s\" is invalid\n", line_number, line); } } } /** * dlt_config_file_find_section * * Find a section * * @param file DltConfigFile * @param section Name of section * @return number of section on success, else -1 */ static int dlt_config_file_find_section(const DltConfigFile *file, const char *section) { int i = 0; if ((file == NULL) || (section == NULL) || (file->num_sections <= 0)) { dlt_log(LOG_WARNING, "Section cannot be found due to invalid parameters\n"); return -1; } for (i = 0; i < file->num_sections; i++) { DltConfigFileSection *s = &file->sections[i]; if (strncmp(s->name, section, DLT_CONFIG_FILE_ENTRY_MAX_LEN) == 0) return i; } return -1; } /************************** interface implementation ***************************/ DltConfigFile *dlt_config_file_init(char *file_name) { DltConfigFile *file; FILE *hdl = NULL; if ((file_name == NULL) || (strlen(file_name) >= DLT_CONFIG_FILE_PATH_MAX_LEN)) { dlt_log(LOG_ERR, "Given configuration file invalid\n"); return NULL; } file = calloc(sizeof(DltConfigFile), 1); if (file == NULL) { dlt_log(LOG_ERR, "Setup internal data structure to parse config file failed\n"); return NULL; } file->sections = calloc(sizeof(DltConfigFileSection), DLT_CONFIG_FILE_SECTIONS_MAX); /* open file */ if ((hdl = fopen(file_name, "r")) == NULL) { dlt_log(LOG_ERR, "Cannot open configuration file\n"); free(file); return NULL; } dlt_config_file_read_file(file, hdl); /* all information stored internally */ fclose(hdl); return file; } void dlt_config_file_release(DltConfigFile *file) { int i = 0; if (file != NULL) { int max = file->num_sections; for (i = 0; i < max; i++) { DltConfigFileSection *s = &file->sections[i]; DltConfigKeyData *node = file->sections[i].list; free(s->name); if (s->keys != NULL) free(s->keys); while (node) { DltConfigKeyData *tmp = node; node = node->next; free(tmp->key); free(tmp->data); free(tmp); } } free(file->sections); free(file); } } int dlt_config_file_get_section_name(const DltConfigFile *file, int num, char *name) { if ((file == NULL) || (name == NULL) || (num < 0) || (num >= file->num_sections)) return -1; strncpy(name, (file->sections + num)->name, DLT_CONFIG_FILE_ENTRY_MAX_LEN); name[DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1] = '\0'; return 0; } int dlt_config_file_get_num_sections(const DltConfigFile *file, int *num) { if ((file == NULL) || (file->num_sections < 0)) return -1; /* * Note: Since General section could be used in configuration file, * this number could be also containing General section. */ *num = file->num_sections; return 0; } int dlt_config_file_get_value(const DltConfigFile *file, const char *section, const char *key, char *value) { DltConfigFileSection *s = NULL; DltConfigKeyData **tmp = NULL; int num_section = 0; if ((file == NULL) || (section == NULL) || (key == NULL) || (value == NULL)) return -1; /* clean value */ memset(value, 0, DLT_CONFIG_FILE_ENTRY_MAX_LEN); num_section = dlt_config_file_find_section(file, section); if (num_section == -1) return -1; s = (file->sections + num_section); tmp = &s->list; while (*(tmp) != NULL) { if (strncmp((*tmp)->key, key, DLT_CONFIG_FILE_ENTRY_MAX_LEN) == 0) { strncpy(value, (*tmp)->data, DLT_CONFIG_FILE_ENTRY_MAX_LEN); return 0; } else { /* not found yet see list for more */ tmp = &(*tmp)->next; } } dlt_vlog(LOG_WARNING, "Entry does not exist in section: %s\n", key); return -1; } int dlt_config_file_check_section_name_exists(const DltConfigFile *file, const char *name) { int ret = 0; if ((file == NULL) || (file->num_sections <= 0) || (name == NULL)) return -1; ret = dlt_config_file_find_section(file, name); if (ret == -1) return ret; return 0; } dlt-daemon-2.18.10/src/shared/dlt_config_file_parser.h000066400000000000000000000136541446635226000226210ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015, Advanced Driver Information Technology * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Christoph Lipka * * \copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_config_file_parser.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_config_file_parser.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** cl Christoph Lipka ADIT ** *******************************************************************************/ #ifndef _DLT_CONFIG_FILE_PARSER_H_ #define _DLT_CONFIG_FILE_PARSER_H_ /* definitions */ #define DLT_CONFIG_FILE_PATH_MAX_LEN 100 /* absolute path including filename */ #define DLT_CONFIG_FILE_ENTRY_MAX_LEN 100 /* Entry for section, key and value */ #define DLT_CONFIG_FILE_LINE_MAX_LEN 210 #define DLT_CONFIG_FILE_SECTIONS_MAX 125 #define DLT_CONFIG_FILE_KEYS_MAX 25 /* Maximal keys per section */ typedef struct DltConfigKeyData { char *key; char *data; struct DltConfigKeyData *next; } DltConfigKeyData; /* Config file section structure */ typedef struct { int num_entries; /* number of entries */ char *name; /* name of section */ char *keys; /* keys */ DltConfigKeyData *list; } DltConfigFileSection; typedef struct { int num_sections; /* number of sections */ DltConfigFileSection *sections; /* sections */ } DltConfigFile; /** * dlt_config_file_init * * Load the configuration file and stores all data in * internal data structures. * * @param file_name File to be opened * @return Pointer to DltConfigFile object or NULL on error */ DltConfigFile *dlt_config_file_init(char *file_name); /** * dlt_config_file_release * * Release config file and frees all internal data. Has to be called after * after all data is read. * * @param file DltConfigFile */ void dlt_config_file_release(DltConfigFile *file); /** * dlt_config_file_get_section_name * * Get name of section number. * * @param[in] file DltConfigFile * @param[in] num Number of section * @param[out] name Section name * @return 0 on success, else -1 */ int dlt_config_file_get_section_name(const DltConfigFile *file, int num, char *name); /** * dlt_config_file_get_num_sections * * Get the number of sections inside configuration file * * @param[in] file DltConfigFile * @param[out] num Number of sections inside configuration file * @return 0 on success, else -1 */ int dlt_config_file_get_num_sections(const DltConfigFile *file, int *num); /** * dlt_config_file_get_value * * Get value of key in specified section. * * @param[in] file DltConfigFile * @param[in] section Name of section * @param[in] key Key * @param[out] value Value * @return 0 on success, else -1 */ int dlt_config_file_get_value(const DltConfigFile *file, const char *section, const char *key, char *value); /** * dlt_config_file_check_section_name_exists * * Get name of section number. * * @param[in] file DltConfigFile * @param[in] name Section name * @return 0 on success/exist, else -1 */ int dlt_config_file_check_section_name_exists(const DltConfigFile *file, const char *name); #endif dlt-daemon-2.18.10/src/shared/dlt_multiple_files.c000066400000000000000000000434171446635226000220110ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2022, Daimler TSS GmbH * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see https://www.covesa.global/. */ /*! * \author * Oleg Tropmann * Daniel Weber * * \copyright Copyright © 2022 Daimler TSS GmbH. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_log.c */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dlt_multiple_files.h" #include "dlt_common.h" unsigned int multiple_files_buffer_storage_dir_info(const char *path, const char *file_name, char *newest, char *oldest) { int i = 0; unsigned int num_log_files = 0; struct dirent **files = { 0 }; char *tmp_old = NULL; char *tmp_new = NULL; if ((path == NULL) || (file_name == NULL) || (newest == NULL) || (oldest == NULL)) { fprintf(stderr, "multiple_files_buffer_storage_dir_info: Invalid parameter(s)"); return 0; } const int file_cnt = scandir(path, &files, NULL, alphasort); if (file_cnt <= 0) return 0; for (i = 0; i < file_cnt; i++) { int len = 0; len = strlen(file_name); if ((strncmp(files[i]->d_name, file_name, len) == 0) && (files[i]->d_name[len] == MULTIPLE_FILES_FILENAME_INDEX_DELIM[0])) { num_log_files++; if ((tmp_old == NULL) || (strlen(tmp_old) >= strlen(files[i]->d_name))) { if (tmp_old == NULL) { tmp_old = files[i]->d_name; } else if (strlen(tmp_old) > strlen(files[i]->d_name)) { /* when file name is smaller, it is older */ tmp_old = files[i]->d_name; } else if (strcmp(tmp_old, files[i]->d_name) > 0) { /* filename length is equal, do a string compare */ tmp_old = files[i]->d_name; } } if ((tmp_new == NULL) || (strlen(tmp_new) <= strlen(files[i]->d_name))) { if (tmp_new == NULL) { tmp_new = files[i]->d_name; } else if (strlen(tmp_new) < strlen(files[i]->d_name)) { /* when file name is longer, it is younger */ tmp_new = files[i]->d_name; } else if (strcmp(tmp_new, files[i]->d_name) < 0) { tmp_new = files[i]->d_name; } } } } if (num_log_files > 0) { if ((tmp_old != NULL) && (strlen(tmp_old) < NAME_MAX)) { strncpy(oldest, tmp_old, NAME_MAX); oldest[NAME_MAX] = '\0'; } else if ((tmp_old != NULL) && (strlen(tmp_old) >= NAME_MAX)) { printf("length mismatch of file %s\n", tmp_old); } if ((tmp_new != NULL) && (strlen(tmp_new) < NAME_MAX)) { strncpy(newest, tmp_new, NAME_MAX); oldest[NAME_MAX] = '\0'; } else if ((tmp_new != NULL) && (strlen(tmp_new) >= NAME_MAX)) { printf("length mismatch of file %s\n", tmp_new); } } /* free scandir result */ for (i = 0; i < file_cnt; i++) free(files[i]); free(files); return num_log_files; } void multiple_files_buffer_file_name(MultipleFilesRingBuffer *files_buffer, const size_t length, const unsigned int idx) { char file_index[11]; /* UINT_MAX = 4294967295 -> 10 digits */ snprintf(file_index, sizeof(file_index), "%010u", idx); /* create log file name */ char* file_name = files_buffer->filename; memset(file_name, 0, length * sizeof(char)); const size_t size = length - strlen(file_name) - 1; strncat(file_name, files_buffer->filenameBase, size); strncat(file_name, MULTIPLE_FILES_FILENAME_INDEX_DELIM, size); strncat(file_name, file_index, size); strncat(file_name, files_buffer->filenameExt, size); } unsigned int multiple_files_buffer_get_idx_of_log_file(char *file) { if ((file == NULL) || (file[0] == '\0')) return 0; const char d[2] = MULTIPLE_FILES_FILENAME_INDEX_DELIM; char *token; token = strtok(file, d); /* we are interested in 2. token because of log file name */ token = strtok(NULL, d); return token != NULL ? strtol(token, NULL, 10) : 0; } DltReturnValue multiple_files_buffer_create_new_file(MultipleFilesRingBuffer *files_buffer) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return DLT_RETURN_ERROR; } time_t t; struct tm tmp; char file_path[PATH_MAX + 1]; unsigned int idx = 0; int ret = 0; /* set filename */ if (files_buffer->filenameTimestampBased) { /* timestamp format: "yyyymmdd_hhmmss" */ char timestamp[16]; t = time(NULL); tzset(); localtime_r(&t, &tmp); strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", &tmp); ret = snprintf(files_buffer->filename, sizeof(files_buffer->filename), "%s%s%s%s", files_buffer->filenameBase, MULTIPLE_FILES_FILENAME_TIMESTAMP_DELIM, timestamp, files_buffer->filenameExt); if ((ret < 0) || ((size_t)ret >= (int)sizeof(files_buffer->filename))) { fprintf(stderr, "filename cannot be concatenated\n"); return DLT_RETURN_ERROR; } ret = snprintf(file_path, sizeof(file_path), "%s/%s", files_buffer->directory, files_buffer->filename); if ((ret < 0) || ((size_t)ret >= (int)sizeof(file_path))) { fprintf(stderr, "file path cannot be concatenated\n"); return DLT_RETURN_ERROR; } } else { char newest[NAME_MAX + 1] = { 0 }; char oldest[NAME_MAX + 1] = { 0 }; /* targeting newest file, ignoring number of files in dir returned */ if (0 == multiple_files_buffer_storage_dir_info(files_buffer->directory, files_buffer->filenameBase, newest, oldest)) { printf("No multiple files found\n"); } idx = multiple_files_buffer_get_idx_of_log_file(newest) + 1; multiple_files_buffer_file_name(files_buffer, sizeof(files_buffer->filename), idx); ret = snprintf(file_path, sizeof(file_path), "%s/%s", files_buffer->directory, files_buffer->filename); if ((ret < 0) || (ret >= NAME_MAX)) { fprintf(stderr, "filename cannot be concatenated\n"); return DLT_RETURN_ERROR; } } /* open DLT output file */ errno = 0; files_buffer->ohandle = open(file_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (files_buffer->ohandle == -1) { /* file cannot be opened */ fprintf(stderr, "file %s cannot be created, error: %s\n", file_path, strerror(errno)); return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } ssize_t multiple_files_buffer_get_total_size(const MultipleFilesRingBuffer *files_buffer) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return -1; } struct dirent *dp; char filename[PATH_MAX + 1]; ssize_t size = 0; struct stat status; /* go through all dlt files in directory */ DIR *dir = opendir(files_buffer->directory); if (!dir) { fprintf(stderr, "directory %s cannot be opened, error=%s\n", files_buffer->directory, strerror(errno)); return -1; } while ((dp = readdir(dir)) != NULL) { // consider files matching with a specific base name and a particular extension if (strstr(dp->d_name, files_buffer->filenameBase) && strstr(dp->d_name, files_buffer->filenameExt)) { int res = snprintf(filename, sizeof(filename), "%s/%s", files_buffer->directory, dp->d_name); /* if the total length of the string is greater than the buffer, silently forget it. */ /* snprintf: a return value of size or more means that the output was truncated */ /* if an output error is encountered, a negative value is returned. */ if (((unsigned int)res < sizeof(filename)) && (res > 0)) { errno = 0; if (0 == stat(filename, &status)) size += status.st_size; else fprintf(stderr, "file %s cannot be stat-ed, error=%s\n", filename, strerror(errno)); } } } closedir(dir); /* return size */ return size; } int multiple_files_buffer_delete_oldest_file(MultipleFilesRingBuffer *files_buffer) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return -1; /* ERROR */ } struct dirent *dp; char filename[PATH_MAX + 1]; char filename_oldest[PATH_MAX + 1]; unsigned long size_oldest = 0; struct stat status; time_t time_oldest = 0; int index_oldest = INT_MAX; filename[0] = 0; filename_oldest[0] = 0; /* go through all dlt files in directory */ DIR *dir = opendir(files_buffer->directory); if(!dir) return -1; while ((dp = readdir(dir)) != NULL) { if (strstr(dp->d_name, files_buffer->filenameBase) && strstr(dp->d_name, files_buffer->filenameExt)) { int res = snprintf(filename, sizeof(filename), "%s/%s", files_buffer->directory, dp->d_name); /* if the total length of the string is greater than the buffer, silently forget it. */ /* snprintf: a return value of size or more means that the output was truncated */ /* if an output error is encountered, a negative value is returned. */ if (((unsigned int) res >= sizeof(filename)) || (res <= 0)) { printf("Filename for delete oldest too long. Skip file.\n"); continue; } if (files_buffer->filenameTimestampBased) { errno = 0; if (0 == stat(filename, &status)) { if ((time_oldest == 0) || (status.st_mtime < time_oldest)) { time_oldest = status.st_mtime; size_oldest = status.st_size; strncpy(filename_oldest, filename, PATH_MAX); filename_oldest[PATH_MAX] = 0; } } else { printf("Old file %s cannot be stat-ed, error=%s\n", filename, strerror(errno)); } } else { //index based const int index = multiple_files_buffer_get_idx_of_log_file(filename); if (index < index_oldest) { index_oldest = index; snprintf(filename, sizeof(filename), "%s/%s", files_buffer->directory, dp->d_name); strncpy(filename_oldest, filename, PATH_MAX); filename_oldest[PATH_MAX] = 0; } } } } closedir(dir); /* delete file */ if (filename_oldest[0]) { if (remove(filename_oldest)) { fprintf(stderr, "Remove file %s failed! error=%s\n", filename_oldest, strerror(errno)); return -1; /* ERROR */ } } else { fprintf(stderr, "No file to be removed!\n"); return -1; /* ERROR */ } /* return size of deleted file*/ return size_oldest; } DltReturnValue multiple_files_buffer_check_size(MultipleFilesRingBuffer *files_buffer) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return DLT_RETURN_ERROR; } struct stat status; /* check for existence of buffer files directory */ errno = 0; if (stat(files_buffer->directory, &status) == -1) { fprintf(stderr, "Buffer files directory: %s doesn't exist, error=%s\n", files_buffer->directory, strerror(errno)); return DLT_RETURN_ERROR; } /* check for accessibility of buffer files directory */ else if (access(files_buffer->directory, W_OK) != 0) { fprintf(stderr, "Buffer files directory: %s doesn't have the write access \n", files_buffer->directory); return DLT_RETURN_ERROR; } ssize_t total_size = 0; /* check size of complete buffer file */ while ((total_size = multiple_files_buffer_get_total_size(files_buffer)) > (files_buffer->maxSize - files_buffer->fileSize)) { /* remove the oldest files as long as new file will not fit in completely into complete multiple files buffer */ if (multiple_files_buffer_delete_oldest_file(files_buffer) < 0) return DLT_RETURN_ERROR; } return total_size == -1 ? DLT_RETURN_ERROR : DLT_RETURN_OK; } DltReturnValue multiple_files_buffer_open_file_for_append(MultipleFilesRingBuffer *files_buffer) { if (files_buffer == NULL || files_buffer->filenameTimestampBased) return DLT_RETURN_ERROR; char newest[NAME_MAX + 1] = {0}; char oldest[NAME_MAX + 1] = {0}; /* targeting the newest file, ignoring number of files in dir returned */ if (0 == multiple_files_buffer_storage_dir_info(files_buffer->directory, files_buffer->filenameBase, newest, oldest) ) { // no file for appending found. Create a new one printf("No multiple files for appending found. Create a new one\n"); return multiple_files_buffer_create_new_file(files_buffer); } char file_path[PATH_MAX + 1]; int ret = snprintf(file_path, sizeof(file_path), "%s/%s", files_buffer->directory, newest); if ((ret < 0) || (ret >= NAME_MAX)) { fprintf(stderr, "filename cannot be concatenated\n"); return DLT_RETURN_ERROR; } /* open DLT output file */ errno = 0; files_buffer->ohandle = open(file_path, O_WRONLY | O_APPEND); /* mode: wb */ return files_buffer->ohandle == -1 ? DLT_RETURN_ERROR : DLT_RETURN_OK; } DltReturnValue multiple_files_buffer_init(MultipleFilesRingBuffer *files_buffer, const char *directory, const int file_size, const int max_size, const bool filename_timestamp_based, const bool append, const char *filename_base, const char *filename_ext) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return DLT_RETURN_ERROR; } /* init parameters */ strncpy(files_buffer->directory, directory, NAME_MAX); files_buffer->directory[NAME_MAX] = 0; files_buffer->fileSize = file_size; files_buffer->maxSize = max_size; files_buffer->filenameTimestampBased = filename_timestamp_based; strncpy(files_buffer->filenameBase, filename_base, NAME_MAX); files_buffer->filenameBase[NAME_MAX] = 0; strncpy(files_buffer->filenameExt, filename_ext, NAME_MAX); files_buffer->filenameExt[NAME_MAX] = 0; if (DLT_RETURN_ERROR == multiple_files_buffer_check_size(files_buffer)) return DLT_RETURN_ERROR; return (!files_buffer->filenameTimestampBased && append) ? multiple_files_buffer_open_file_for_append(files_buffer) : multiple_files_buffer_create_new_file(files_buffer); } void multiple_files_buffer_rotate_file(MultipleFilesRingBuffer *files_buffer, const int size) { /* check file size here */ if ((lseek(files_buffer->ohandle, 0, SEEK_CUR) + size) < files_buffer->fileSize) return; /* close old file */ close(files_buffer->ohandle); files_buffer->ohandle = -1; /* check complete files size, remove old logs if needed */ if (DLT_RETURN_ERROR == multiple_files_buffer_check_size(files_buffer)) return; /* create new file */ multiple_files_buffer_create_new_file(files_buffer); } DltReturnValue multiple_files_buffer_write_chunk(const MultipleFilesRingBuffer *files_buffer, const unsigned char *data, const int size) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return DLT_RETURN_ERROR; } if (data && (files_buffer->ohandle >= 0)) { if (write(files_buffer->ohandle, data, size) != size) { fprintf(stderr, "file write failed!\n"); return DLT_RETURN_ERROR; } } return DLT_RETURN_OK; } DltReturnValue multiple_files_buffer_write(MultipleFilesRingBuffer *files_buffer, const unsigned char *data, const int size) { if (files_buffer->ohandle < 0) return DLT_RETURN_ERROR; multiple_files_buffer_rotate_file(files_buffer, size); /* write data into log file */ return multiple_files_buffer_write_chunk(files_buffer, data, size); } DltReturnValue multiple_files_buffer_free(const MultipleFilesRingBuffer *files_buffer) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); return DLT_RETURN_ERROR; } if (files_buffer->ohandle < 0) return DLT_RETURN_ERROR; /* close last used log file */ close(files_buffer->ohandle); return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/shared/dlt_offline_trace.c000066400000000000000000000077641446635226000216010ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_offline_trace.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_offline_trace.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include DltReturnValue dlt_offline_trace_write(MultipleFilesRingBuffer *trace, const unsigned char *data1, const int size1, const unsigned char *data2, const int size2, const unsigned char *data3, const int size3) { if (trace->ohandle < 0) return DLT_RETURN_ERROR; multiple_files_buffer_rotate_file(trace, size1 + size2 + size3); /* write data into log file */ if (multiple_files_buffer_write_chunk(trace, data1, size1) != DLT_RETURN_OK) return DLT_RETURN_ERROR; if (multiple_files_buffer_write_chunk(trace, data2, size2) != DLT_RETURN_OK) return DLT_RETURN_ERROR; if (multiple_files_buffer_write_chunk(trace, data3, size3) != DLT_RETURN_OK) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } dlt-daemon-2.18.10/src/shared/dlt_protocol.c000066400000000000000000000055471446635226000206370ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2016 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Christoph Lipka * * \copyright Copyright © 2016 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_protocol.c */ #include "dlt_protocol.h" const char *const dlt_service_names[] = { "DLT_SERVICE_ID", "DLT_SERVICE_ID_SET_LOG_LEVEL", "DLT_SERVICE_ID_SET_TRACE_STATUS", "DLT_SERVICE_ID_GET_LOG_INFO", "DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL", "DLT_SERVICE_ID_STORE_CONFIG", "DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT", "DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS", "DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH", "DLT_SERVICE_ID_SET_VERBOSE_MODE", "DLT_SERVICE_ID_SET_MESSAGE_FILTERING", "DLT_SERVICE_ID_SET_TIMING_PACKETS", "DLT_SERVICE_ID_GET_LOCAL_TIME", "DLT_SERVICE_ID_USE_ECU_ID", "DLT_SERVICE_ID_USE_SESSION_ID", "DLT_SERVICE_ID_USE_TIMESTAMP", "DLT_SERVICE_ID_USE_EXTENDED_HEADER", "DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL", "DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS", "DLT_SERVICE_ID_GET_SOFTWARE_VERSION", "DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW" }; const char *const dlt_user_service_names[] = { "DLT_USER_SERVICE_ID", "DLT_SERVICE_ID_UNREGISTER_CONTEXT", "DLT_SERVICE_ID_CONNECTION_INFO", "DLT_SERVICE_ID_TIMEZONE", "DLT_SERVICE_ID_MARKER", "DLT_SERVICE_ID_OFFLINE_LOGSTORAGE", "DLT_SERVICE_ID_PASSIVE_NODE_CONNECT", "DLT_SERVICE_ID_PASSIVE_NODE_CONNECTION_STATUS", "DLT_SERVICE_ID_SET_ALL_LOG_LEVEL", "DLT_SERVICE_ID_SET_ALL_TRACE_STATUS", "DLT_SERVICE_ID_UNDEFINED", /* 0xF0A is not defined */ "DLT_SERVICE_ID_RESERVED", "DLT_SERVICE_ID_RESERVED", "DLT_SERVICE_ID_RESERVED", "DLT_SERVICE_ID_RESERVED" }; const char *dlt_get_service_name(unsigned int id) { if (id == DLT_SERVICE_ID_CALLSW_CINJECTION) return "DLT_SERVICE_ID_CALLSW_CINJECTION"; else if ((id == DLT_SERVICE_ID) || (id >= DLT_USER_SERVICE_ID_LAST_ENTRY) || ((id >= DLT_SERVICE_ID_LAST_ENTRY) && (id <= DLT_USER_SERVICE_ID))) return "UNDEFINED"; else if ((id > DLT_SERVICE_ID) && (id < DLT_SERVICE_ID_LAST_ENTRY)) return dlt_service_names[id]; else /* user services */ return dlt_user_service_names[id & 0xFF]; } dlt-daemon-2.18.10/src/shared/dlt_shm.c000066400000000000000000000325021446635226000175540ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_shm.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_shm.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include #include #include #include #include #if !defined(_MSC_VER) #include #include #endif #include #include void dlt_shm_print_hex(char *ptr, int size) { int num; for (num = 0; num < size; num++) { if ((num % 16) == 15) printf("%.2x\n", ((unsigned char *)ptr)[num]); else printf("%.2x ", ((unsigned char *)ptr)[num]); } printf("\n"); } DltReturnValue dlt_shm_init_server(DltShm *buf, const char *name, int size) { unsigned char *ptr; /* Check if buffer and name available */ if (buf == NULL || name == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* Init parameters */ buf->shmfd = 0; buf->sem = NULL; /** * Create the shared memory segment. * @name Name of the new shared memory object. * (shm_open will create a file under /dev/shm/) * @oflag O_CREAT | O_EXCL | O_RDWR * O_CREAT | O_EXCL: The shm_open() fails if the shared memory exists. * O_RDWR: Open the object for read-write access. * @mode 0666 * The shared memory object's permission. */ buf->shmfd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0666); if (buf->shmfd == -1) { dlt_vlog(LOG_ERR, "%s: shm_open() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Set the size of shm */ if (ftruncate(buf->shmfd, size) == -1) { dlt_vlog(LOG_ERR, "%s: ftruncate() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Now we attach the segment to our data space. */ ptr = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, buf->shmfd, 0); if (ptr == MAP_FAILED) { dlt_vlog(LOG_ERR, "%s: mmap() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /** * Create the semaphore with input name * @name name * Name of the new semaphore * (sem_open will create a file under /dev/shm/sem.) * @oflag O_CREAT | O_EXCEL * The sem_open() fails if the semaphore name exists. * @mode 0777 * The permissions to be placed on the new semaphore. * @value 1 * Initial value for the new semaphore. */ buf->sem = sem_open(name, O_CREAT | O_EXCL, 0666, 1); if (buf->sem == SEM_FAILED) { dlt_vlog(LOG_ERR, "%s: sem_open() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Init buffer */ dlt_buffer_init_static_server(&(buf->buffer), ptr, size); /* The 'buf->shmfd' is no longer needed */ if (close(buf->shmfd) == -1) { dlt_vlog(LOG_ERR, "%s: Failed to close shared memory" " file descriptor: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } return DLT_RETURN_OK; /* OK */ } DltReturnValue dlt_shm_init_client(DltShm *buf, const char *name) { struct stat shm_buf; unsigned char *ptr; /* Check if buffer and name available */ if (buf == NULL || name == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } /* Init parameters */ buf->shmfd = 0; buf->sem = NULL; /** * Open the existing shared memory segment created by the server. * @name Name of the existing shared memory object. * (shm_open will open the file under /dev/shm/) * @oflag O_RDWR * Open the object for read-write access. * @mode 0 * We are not creating a new object, this argument should be specified as 0. */ buf->shmfd = shm_open(name, O_RDWR, 0); if (buf->shmfd == -1) { dlt_vlog(LOG_ERR, "%s: shm_open() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Get the size of shm */ if (fstat(buf->shmfd, &shm_buf) == -1) { dlt_vlog(LOG_ERR, "%s: fstat() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Now we attach the segment to our data space. */ ptr = (unsigned char *)mmap(NULL, shm_buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, buf->shmfd, 0); if (ptr == MAP_FAILED) { dlt_vlog(LOG_ERR, "%s: mmap() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /** * Open the existing semaphore with name created by the server * The call requires only two arguments. * @name name * Name of the existing semaphore * (sem_open will open a file under /dev/shm/sem.) * @oflag 0 * We are accessing an existing semaphore, oflag should be specified as 0. */ buf->sem = sem_open(name, 0); if (buf->sem == SEM_FAILED) { dlt_vlog(LOG_ERR, "%s: sem_open() failed: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Init buffer */ dlt_buffer_init_static_client(&(buf->buffer), ptr, shm_buf.st_size); /* The 'buf->shmfd' is no longer needed */ if (close(buf->shmfd) == -1) { dlt_vlog(LOG_ERR, "%s: Failed to close shared memory" " file descriptor: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } return DLT_RETURN_OK; /* OK */ } void dlt_shm_info(DltShm *buf) { /* Check if buffer available */ if (buf == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return; } dlt_buffer_info(&(buf->buffer)); } void dlt_shm_status(DltShm *buf) { /* Check if buffer available */ if (buf == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return; } dlt_buffer_status(&(buf->buffer)); } int dlt_shm_get_total_size(DltShm *buf) { /* Check if buffer available */ if (buf == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } return dlt_buffer_get_total_size(&(buf->buffer)); } int dlt_shm_get_used_size(DltShm *buf) { int ret; /* Check if buffer available */ if ((buf == NULL) || (buf->buffer.mem == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_get_used_size(&(buf->buffer)); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_get_message_count(DltShm *buf) { /* Check if buffer available */ if (buf == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } return dlt_buffer_get_message_count(&(buf->buffer)); } int dlt_shm_push(DltShm *buf, const unsigned char *data1, unsigned int size1, const unsigned char *data2, unsigned int size2, const unsigned char *data3, unsigned int size3) { int ret; /* Check if buffer available */ if ((buf == NULL) || (buf->buffer.mem == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_push3(&(buf->buffer), data1, size1, data2, size2, data3, size3); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_pull(DltShm *buf, unsigned char *data, int max_size) { int ret; /* Check if buffer available */ if ((buf == NULL) || (buf->buffer.mem == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_pull(&(buf->buffer), data, max_size); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_copy(DltShm *buf, unsigned char *data, int max_size) { int ret; /* Check if buffer available */ if ((buf == NULL) || (buf->buffer.mem == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_copy(&(buf->buffer), data, max_size); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_remove(DltShm *buf) { int ret; /* Check if buffer available */ if ((buf == NULL) || (buf->buffer.mem == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; } DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_remove(&(buf->buffer)); DLT_SHM_SEM_FREE(buf->sem); return ret; } DltReturnValue dlt_shm_free_server(DltShm *buf, const char *name) { if ((buf == NULL) || (buf->buffer.shm == NULL) || name == NULL) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (munmap(buf->buffer.shm, buf->buffer.min_size) == -1) { dlt_vlog(LOG_ERR, "%s: munmap() failed: %s\n", __func__, strerror(errno)); } if (shm_unlink(name) == -1) { dlt_vlog(LOG_ERR, "%s: shm_unlink() failed: %s\n", __func__, strerror(errno)); } if (sem_close(buf->sem) == -1) { dlt_vlog(LOG_ERR, "%s: sem_close() failed: %s\n", __func__, strerror(errno)); } if (sem_unlink(name) == -1) { dlt_vlog(LOG_ERR, "%s: sem_unlink() failed: %s\n", __func__, strerror(errno)); } /* Reset parameters */ buf->shmfd = 0; buf->sem = NULL; return dlt_buffer_free_static(&(buf->buffer)); } DltReturnValue dlt_shm_free_client(DltShm *buf) { if ((buf == NULL) || (buf->buffer.shm == NULL)) { dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return DLT_RETURN_WRONG_PARAMETER; } if (munmap(buf->buffer.shm, buf->buffer.min_size) == -1) { dlt_vlog(LOG_ERR, "%s: munmap() failed: %s\n", __func__, strerror(errno)); } if (sem_close(buf->sem) == -1) { dlt_vlog(LOG_ERR, "%s: sem_close() failed: %s\n", __func__, strerror(errno)); } /* Reset parameters */ buf->shmfd = 0; buf->sem = NULL; return dlt_buffer_free_static(&(buf->buffer)); } dlt-daemon-2.18.10/src/shared/dlt_user_shared.c000066400000000000000000000161611446635226000212740ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user_shared.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_user_shared.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include #include #include #include /* writev() */ #include /* timeval */ #include "dlt_user_shared.h" #include "dlt_user_shared_cfg.h" DltReturnValue dlt_user_set_userheader(DltUserHeader *userheader, uint32_t mtype) { if (userheader == 0) return DLT_RETURN_ERROR; if (mtype <= 0) return DLT_RETURN_ERROR; userheader->pattern[0] = 'D'; userheader->pattern[1] = 'U'; userheader->pattern[2] = 'H'; userheader->pattern[3] = 1; userheader->message = mtype; return DLT_RETURN_OK; } int dlt_user_check_userheader(DltUserHeader *userheader) { if (userheader == 0) return -1; return (userheader->pattern[0] == 'D') && (userheader->pattern[1] == 'U') && (userheader->pattern[2] == 'H') && (userheader->pattern[3] == 1); } DltReturnValue dlt_user_log_out2(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2) { struct iovec iov[2]; uint32_t bytes_written; if (handle < 0) /* Invalid handle */ return DLT_RETURN_ERROR; iov[0].iov_base = ptr1; iov[0].iov_len = len1; iov[1].iov_base = ptr2; iov[1].iov_len = len2; bytes_written = (uint32_t) writev(handle, iov, 2); if (bytes_written != (len1 + len2)) return DLT_RETURN_ERROR; return DLT_RETURN_OK; } DltReturnValue dlt_user_log_out2_with_timeout(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2) { if (handle < 0) /* Invalid handle */ return DLT_RETURN_ERROR; fd_set fds; FD_ZERO(&fds); FD_SET(handle, &fds); struct timeval tv = { DLT_WRITEV_TIMEOUT_SEC, DLT_WRITEV_TIMEOUT_USEC }; if (select(handle+1, NULL, &fds, NULL, &tv) < 0) { return DLT_RETURN_ERROR; } if (FD_ISSET(handle, &fds)) { return dlt_user_log_out2(handle, ptr1, len1, ptr2, len2); } else { return DLT_RETURN_ERROR; } } DltReturnValue dlt_user_log_out3(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3, size_t len3) { struct iovec iov[3]; uint32_t bytes_written; if (handle < 0) /* Invalid handle */ return DLT_RETURN_ERROR; iov[0].iov_base = ptr1; iov[0].iov_len = len1; iov[1].iov_base = ptr2; iov[1].iov_len = len2; iov[2].iov_base = ptr3; iov[2].iov_len = len3; bytes_written = (uint32_t) writev(handle, iov, 3); if (bytes_written != (len1 + len2 + len3)) { switch (errno) { case ETIMEDOUT: { return DLT_RETURN_PIPE_ERROR; /* ETIMEDOUT - connect timeout */ break; } case EBADF: { return DLT_RETURN_PIPE_ERROR; /* EBADF - handle not open */ break; } case EPIPE: { return DLT_RETURN_PIPE_ERROR; /* EPIPE - pipe error */ break; } case EAGAIN: { return DLT_RETURN_PIPE_FULL; /* EAGAIN - data could not be written */ break; } default: { break; } } return DLT_RETURN_ERROR; } return DLT_RETURN_OK; } DltReturnValue dlt_user_log_out3_with_timeout(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3, size_t len3) { if (handle < 0) /* Invalid handle */ return DLT_RETURN_ERROR; fd_set fds; FD_ZERO(&fds); FD_SET(handle, &fds); struct timeval tv = { DLT_WRITEV_TIMEOUT_SEC, DLT_WRITEV_TIMEOUT_USEC }; if (select(handle+1, NULL, &fds, NULL, &tv) < 0) { return DLT_RETURN_ERROR; } if (FD_ISSET(handle, &fds)) { return dlt_user_log_out3(handle, ptr1, len1, ptr2, len2, ptr3, len3); } else { return DLT_RETURN_ERROR; } } dlt-daemon-2.18.10/src/shared/dlt_user_shared.h000066400000000000000000000260171446635226000213020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user_shared.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_user_shared.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_USER_SHARED_H #define DLT_USER_SHARED_H #include "dlt_types.h" #include "dlt_user.h" #include /** * This is the header of each message to be exchanged between application and daemon. */ typedef struct { char pattern[DLT_ID_SIZE]; /**< This pattern should be DUH0x01 */ uint32_t message; /**< messsage info */ } DLT_PACKED DltUserHeader; /** * This is the internal message content to exchange control msg register app information between application and daemon. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ pid_t pid; /**< process id of user application */ uint32_t description_length; /**< length of description */ } DLT_PACKED DltUserControlMsgRegisterApplication; /** * This is the internal message content to exchange control msg unregister app information between application and daemon. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ pid_t pid; /**< process id of user application */ } DLT_PACKED DltUserControlMsgUnregisterApplication; /** * This is the internal message content to exchange control msg register information between application and daemon. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ int32_t log_level_pos; /**< offset in management structure on user-application side */ int8_t log_level; /**< log level */ int8_t trace_status; /**< trace status */ pid_t pid; /**< process id of user application */ uint32_t description_length; /**< length of description */ } DLT_PACKED DltUserControlMsgRegisterContext; /** * This is the internal message content to exchange control msg unregister information between application and daemon. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ char ctid[DLT_ID_SIZE]; /**< context id */ pid_t pid; /**< process id of user application */ } DLT_PACKED DltUserControlMsgUnregisterContext; /** * This is the internal message content to exchange control msg log level information between application and daemon. */ typedef struct { uint8_t log_level; /**< log level */ uint8_t trace_status; /**< trace status */ int32_t log_level_pos; /**< offset in management structure on user-application side */ } DLT_PACKED DltUserControlMsgLogLevel; /** * This is the internal message content to exchange control msg injection information between application and daemon. */ typedef struct { int32_t log_level_pos; /**< offset in management structure on user-application side */ uint32_t service_id; /**< service id of injection */ uint32_t data_length_inject; /**< length of injection message data field */ } DLT_PACKED DltUserControlMsgInjection; /** * This is the internal message content to exchange information about application log level and trace stats between * application and daemon. */ typedef struct { char apid[DLT_ID_SIZE]; /**< application id */ uint8_t log_level; /**< log level */ uint8_t trace_status; /**< trace status */ } DLT_PACKED DltUserControlMsgAppLogLevelTraceStatus; /** * This is the internal message content to set the logging mode: off, external, internal, both. */ typedef struct { int8_t log_mode; /**< the mode to be used for logging: off, external, internal, both */ } DLT_PACKED DltUserControlMsgLogMode; /** * This is the internal message content to get the logging state: 0 = off, 1 = external client connected. */ typedef struct { int8_t log_state; /**< the state to be used for logging state: 0 = off, 1 = external client connected */ } DLT_PACKED DltUserControlMsgLogState; /** * This is the internal message content to get the number of lost messages reported to the daemon. */ typedef struct { uint32_t overflow_counter; /**< counts the number of lost messages */ char apid[4]; /**< application which lost messages */ } DLT_PACKED DltUserControlMsgBufferOverflow; /************************************************************************************************** * The folowing functions are used shared between the user lib and the daemon implementation **************************************************************************************************/ /** * Set user header marker and store message type in user header * @param userheader pointer to the userheader * @param mtype user message type of internal message * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_set_userheader(DltUserHeader *userheader, uint32_t mtype); /** * Check if user header contains its marker * @param userheader pointer to the userheader * @return 0 no, 1 yes, negative value if there was an error */ int dlt_user_check_userheader(DltUserHeader *userheader); /** * Atomic write to file descriptor, using vector of 2 elements * @param handle file descriptor * @param ptr1 generic pointer to first segment of data to be written * @param len1 length of first segment of data to be written * @param ptr2 generic pointer to second segment of data to be written * @param len2 length of second segment of data to be written * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_out2(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2); /** * Atomic write to file descriptor, using vector of 2 elements with a timeout of 1s * @param handle file descriptor * @param ptr1 generic pointer to first segment of data to be written * @param len1 length of first segment of data to be written * @param ptr2 generic pointer to second segment of data to be written * @param len2 length of second segment of data to be written * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_out2_with_timeout(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2); /** * Atomic write to file descriptor, using vector of 3 elements * @param handle file descriptor * @param ptr1 generic pointer to first segment of data to be written * @param len1 length of first segment of data to be written * @param ptr2 generic pointer to second segment of data to be written * @param len2 length of second segment of data to be written * @param ptr3 generic pointer to third segment of data to be written * @param len3 length of third segment of data to be written * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_out3(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3, size_t len3); /** * Atomic write to file descriptor, using vector of 3 elements with a timeout of 1s * @param handle file descriptor * @param ptr1 generic pointer to first segment of data to be written * @param len1 length of first segment of data to be written * @param ptr2 generic pointer to second segment of data to be written * @param len2 length of second segment of data to be written * @param ptr3 generic pointer to third segment of data to be written * @param len3 length of third segment of data to be written * @return Value from DltReturnValue enum */ DltReturnValue dlt_user_log_out3_with_timeout(int handle, void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3, size_t len3); #endif /* DLT_USER_SHARED_H */ dlt-daemon-2.18.10/src/shared/dlt_user_shared_cfg.h000066400000000000000000000113241446635226000221140ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_user_shared_cfg.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_user_shared_cfg.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ #ifndef DLT_USER_SHARED_CFG_H #define DLT_USER_SHARED_CFG_H /*************/ /* Changable */ /*************/ /************************/ /* Don't change please! */ /************************/ /* The different types of internal messages between user application and daemon. */ #define DLT_USER_MESSAGE_LOG 1 #define DLT_USER_MESSAGE_REGISTER_APPLICATION 2 #define DLT_USER_MESSAGE_UNREGISTER_APPLICATION 3 #define DLT_USER_MESSAGE_REGISTER_CONTEXT 4 #define DLT_USER_MESSAGE_UNREGISTER_CONTEXT 5 #define DLT_USER_MESSAGE_LOG_LEVEL 6 #define DLT_USER_MESSAGE_INJECTION 7 #define DLT_USER_MESSAGE_OVERFLOW 8 #define DLT_USER_MESSAGE_APP_LL_TS 9 #define DLT_USER_MESSAGE_LOG_SHM 10 #define DLT_USER_MESSAGE_LOG_MODE 11 #define DLT_USER_MESSAGE_LOG_STATE 12 #define DLT_USER_MESSAGE_MARKER 13 #define DLT_USER_MESSAGE_NOT_SUPPORTED 16 /* Internal defined values */ /* must be different from DltLogLevelType */ #define DLT_USER_LOG_LEVEL_NOT_SET -2 /* must be different from DltTraceStatusType */ #define DLT_USER_TRACE_STATUS_NOT_SET -2 #endif /* DLT_USER_SHARED_CFG_H */ dlt-daemon-2.18.10/src/system/000077500000000000000000000000001446635226000160325ustar00rootroot00000000000000dlt-daemon-2.18.10/src/system/CMakeLists.txt000066400000000000000000000032511446635226000205730ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD OR WITH_SYSTEMD_JOURNAL) message( STATUS "Added ${systemd_SRCS} to dlt-system") endif(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD OR WITH_SYSTEMD_JOURNAL) set(dlt_system_SRCS dlt-system.c dlt-system-options.c dlt-system-process-handling.c dlt-system-logfile.c dlt-system-processes.c dlt-system-shell.c dlt-system-syslog.c dlt-system-watchdog.c dlt-system-journal.c) if(WITH_DLT_FILETRANSFER) set(dlt_system_SRCS ${dlt_system_SRCS} dlt-system-filetransfer.c) add_definitions(-DDLT_FILETRANSFER_ENABLE) endif(WITH_DLT_FILETRANSFER) add_executable(dlt-system ${dlt_system_SRCS} ${systemd_SRCS}) target_link_libraries(dlt-system dlt) if(WITH_SYSTEMD_JOURNAL) if(SYSTEMD_VERSION LESS 209) target_link_libraries(dlt-system systemd-journal systemd-id128) else(SYSTEMD_VERSION LESS 209) target_link_libraries(dlt-system systemd) endif(SYSTEMD_VERSION LESS 209) endif(WITH_SYSTEMD_JOURNAL) if(WITH_DLT_FILETRANSFER) target_link_libraries(dlt-system ${ZLIB_LIBRARY}) endif(WITH_DLT_FILETRANSFER) set_target_properties(dlt-system PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-system RUNTIME DESTINATION bin COMPONENT base) INSTALL(FILES dlt-system.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) dlt-daemon-2.18.10/src/system/dlt-system-filetransfer.c000066400000000000000000000607501446635226000227750ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Lassi Marttala * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-filetransfer.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-filetransfer.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include #ifdef linux # include #endif #include #include #include #include #include #include #include #include #include "dlt-system.h" #include "dlt.h" #include "dlt_filetransfer.h" #ifdef linux # define INOTIFY_SZ (sizeof(struct inotify_event)) # define INOTIFY_LEN (INOTIFY_SZ + NAME_MAX + 1) #endif #define Z_CHUNK_SZ 1024 * 128 #define COMPRESS_EXTENSION ".gz" #define SUBDIR_COMPRESS ".tocompress" #define SUBDIR_TOSEND ".tosend" /* From dlt_filetransfer */ extern uint32_t getFileSerialNumber(const char *file, int *ok); DLT_IMPORT_CONTEXT(dltsystem) DLT_DECLARE_CONTEXT(filetransferContext) #ifdef linux s_ft_inotify ino; #endif char *origin_name(char *src) { if (strlen((char *)basename(src)) > 10) { return (char *)(basename(src) + 10); } else { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-filetransfer, error in recreating origin name!")); return NULL; } } char *unique_name(char *src) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, creating unique temporary file name.")); time_t t = time(NULL); int ok; uint32_t l = getFileSerialNumber(src, &ok) ^ t; if (!ok) return (char *)NULL; char *basename_f = basename(src); /* Length of ULONG_MAX + 1 */ int len = 11 + strlen(basename_f); if (len > NAME_MAX) { DLT_LOG(dltsystem, DLT_LOG_WARN, DLT_STRING("dlt-system-filetransfer, unique name creation needs to shorten the filename:"), DLT_STRING(basename_f)); len = NAME_MAX; } char *ret = malloc(len); MALLOC_ASSERT(ret); snprintf(ret, len, "%010" PRIu32 "%s", l, basename_f); return ret; } /** * Function which only calls the relevant part to transfer the payload */ void send_dumped_file(FiletransferOptions const *opts, char *dst_tosend) { /* check if a client is connected to the deamon. If not, try again in a second */ while (dlt_get_log_state() != 1) sleep(1); char *fn = origin_name(dst_tosend); DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, sending dumped file:"), DLT_STRING(fn)); if (dlt_user_log_file_header_alias(&filetransferContext, dst_tosend, fn) == 0) { int pkgcount = dlt_user_log_file_packagesCount(&filetransferContext, dst_tosend); int lastpkg = 0; int success = 1; while (lastpkg < pkgcount) { int total = 2; int used = 2; dlt_user_check_buffer(&total, &used); while ((total - used) < (total / 2)) { struct timespec t; t.tv_sec = 0; t.tv_nsec = 1000000ul * opts->TimeoutBetweenLogs; nanosleep(&t, NULL); dlt_user_log_resend_buffer(); dlt_user_check_buffer(&total, &used); } lastpkg++; if (dlt_user_log_file_data(&filetransferContext, dst_tosend, lastpkg, opts->TimeoutBetweenLogs) < 0) { success = 0; break; } } if (success) dlt_user_log_file_end(&filetransferContext, dst_tosend, 1); } DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, sent dumped file")); } /** * compress file, delete the source file * modification: compress into subdirectory * File whis is compress will be deleted afterwards * @param src File to be sent * @param dst destination where to compress the file * @param level of compression **/ int compress_file_to(char *src, char *dst, int level) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, compressing file from:"), DLT_STRING(src), DLT_STRING("to:"), DLT_STRING(dst)); char *buf; char dst_mode[8]; snprintf(dst_mode, 8, "wb%d", level); gzFile dst_file; FILE *src_file; dst_file = gzopen(dst, dst_mode); if (dst_file == Z_NULL) return -1; src_file = fopen(src, "r"); if (src_file == NULL) { gzclose(dst_file); return -1; } buf = malloc(Z_CHUNK_SZ); MALLOC_ASSERT(buf); while (!feof(src_file)) { int read = fread(buf, 1, Z_CHUNK_SZ, src_file); if (ferror(src_file)) { free(buf); gzclose(dst_file); fclose(src_file); return -1; } gzwrite(dst_file, buf, read); } if (remove(src) < 0) DLT_LOG(dltsystem, DLT_LOG_WARN, DLT_STRING("Could not remove file"), DLT_STRING(src)); free(buf); fclose(src_file); gzclose(dst_file); return 0; } /*!Sends one file over DLT. */ /** * If configured in opts, compresses it, then sends it. * uses subdirecties for compressing and before sending, to avoid that those files get changed in the meanwhile * */ int send_one(char *src, FiletransferOptions const *opts, int which) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, sending a file.")); /* Prepare all needed file names */ char *fn = basename(src); if (fn == NULL) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("basename not valid")); return -1; } char *src_copy = strndup(src, PATH_MAX); MALLOC_ASSERT(src_copy); /*dirname overwrites its argument anyway, */ /*but depending on argument returned address might change */ char *fdir = dirname(src_copy); char *dst_tosend;/*file which is going to be sent */ char *rn = unique_name(src);/*new unique filename based on inode */ if (rn == NULL) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("file information not available, may be file got overwritten")); return -1; } /* Compress if needed */ if (opts->Compression[which] > 0) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, Moving file to tmp directory for compressing it.")); char *dst_tocompress;/*file which is going to be compressed, the compressed one is named dst_tosend */ int len = strlen(fdir) + strlen(SUBDIR_COMPRESS) + strlen(rn) + 3;/*the filename in .tocompress +2 for 2*"/", +1 for \0 */ dst_tocompress = malloc(len); MALLOC_ASSERT(dst_tocompress); snprintf(dst_tocompress, len, "%s/%s/%s", fdir, SUBDIR_COMPRESS, rn); /*moving in subdir, from where it can be compressed */ if (rename(src, dst_tocompress) < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not move file"), DLT_STRING(src), DLT_STRING(dst_tocompress)); free(rn); free(dst_tocompress); free(src_copy); return -1; } len = strlen(fdir) + strlen(SUBDIR_TOSEND) + strlen(rn) + strlen(COMPRESS_EXTENSION) + 3;/*the resulting filename in .tosend +2 for 2*"/", +1 for \0 */ dst_tosend = malloc(len); MALLOC_ASSERT(dst_tosend); snprintf(dst_tosend, len, "%s/%s/%s%s", fdir, SUBDIR_TOSEND, rn, COMPRESS_EXTENSION); if (compress_file_to(dst_tocompress, dst_tosend, opts->CompressionLevel[which]) != 0) { free(rn); free(dst_tosend); free(dst_tocompress); free(src_copy); return -1; } free(dst_tocompress); } else { /*move it directly into "tosend" */ DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, Moving file to tmp directory.")); int len = strlen(fdir) + strlen(SUBDIR_TOSEND) + strlen(rn) + 3; dst_tosend = malloc(len);/*the resulting filename in .tosend +2 for 2*"/", +1 for \0 */ snprintf(dst_tosend, len, "%s/%s/%s", fdir, SUBDIR_TOSEND, rn); DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, Rename:"), DLT_STRING(src), DLT_STRING("to: "), DLT_STRING(dst_tosend)); /*moving in subdir, from where it can be compressed */ if (rename(src, dst_tosend) < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not move file"), DLT_STRING(src), DLT_STRING(dst_tosend)); free(rn); free(dst_tosend); free(src_copy); return -1; } } DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, File ready to send")); send_dumped_file(opts, dst_tosend); free(rn); free(dst_tosend); free(src_copy); return 0; } int flush_dir_send(FiletransferOptions const *opts, const char *compress_dir, const char *send_dir) { struct dirent *dp; DIR *dir; dir = opendir(send_dir); if (dir != NULL) { while ((dp = readdir(dir)) != NULL) { if (dp->d_type != DT_REG) continue; char *fn; DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, old compressed file found in send directory:"), DLT_STRING(dp->d_name)); int len = strlen(send_dir) + strlen(dp->d_name) + 2; fn = malloc(len); MALLOC_ASSERT(fn); snprintf(fn, len, "%s/%s", send_dir, dp->d_name); /*if we have a file here and in the to_compress dir, we delete the to_send file: we can not be sure, that it has been properly compressed! */ if (!strncmp(dp->d_name + strlen(dp->d_name) - strlen(COMPRESS_EXTENSION), COMPRESS_EXTENSION, strlen(COMPRESS_EXTENSION))) { /*ends with ".gz" */ /*old file name (not: path) would have been: */ char tmp[strlen(dp->d_name) - strlen(COMPRESS_EXTENSION) + 1]; strncpy(tmp, dp->d_name, strlen(dp->d_name) - strlen(COMPRESS_EXTENSION)); tmp[strlen(dp->d_name) - strlen(COMPRESS_EXTENSION)] = '\0'; int len = strlen(tmp) + strlen(compress_dir) + 1 + 1;/*2 sizes + 1*"/" + \0 */ char *path_uncompressed = malloc(len); MALLOC_ASSERT(path_uncompressed); snprintf(path_uncompressed, len, "%s/%s", compress_dir, tmp); struct stat sb; if (stat(path_uncompressed, &sb) == -1) { /*uncompressed equivalent does not exist. We can send it out. */ DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, sending file.")); send_dumped_file(opts, fn); } else { /*There is an uncompressed file. Compression seems to have been interrupted -> delete the compressed file instead of sending it! */ DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING( "dlt-system-filetransfer, uncompressed version exists. Deleting partially compressed version.")); if (sb.st_mode & S_IFREG) { if (remove(fn) != 0) /*"Error deleting file". Continue? If we would cancel, maybe the dump is never sent! Deletion would again be tried in next LC. */ DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error deleting file:"), DLT_STRING(fn)); } else { /*"Oldfile is a not reg file. Is this possible? Can we compress a directory?: %s\n",path_uncompressed); */ DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING( "dlt-system-filetransfer, Oldfile is a not regular file! Do we have a problem?"), DLT_STRING(fn)); } } free(path_uncompressed);/*it is no more used. It would be transferred in next step. */ }/*it is a .gz file */ else { /*uncompressed file. We can just resend it, the action to put it here was a move action. */ DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, Sending uncompressed file from previous LC."), DLT_STRING(fn)); send_dumped_file(opts, fn); } free(fn); } } else { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not open directory"), DLT_STRING(send_dir)); return -1; } closedir(dir);/*end: send_dir */ return 0; } int flush_dir_compress(FiletransferOptions const *opts, int which, const char *compress_dir, const char *send_dir) { /*check for files in compress_dir. Assumption: a file which lies here, should have been compressed, but that action was interrupted. */ /*As it can arrive here only by a rename, it is most likely to be a complete file */ struct dirent *dp; DIR *dir; dir = opendir(compress_dir); if (dir != NULL) { while ((dp = readdir(dir)) != NULL) { if (dp->d_type != DT_REG) continue; DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, old file found in compress-directory.")); /*compress file into to_send dir */ int len = strlen(compress_dir) + strlen(dp->d_name) + 2; char *cd_filename = malloc(len); MALLOC_ASSERT(cd_filename); snprintf(cd_filename, len, "%s/%s", compress_dir, dp->d_name); len = strlen(send_dir) + strlen(dp->d_name) + strlen(COMPRESS_EXTENSION) + 2; char *dst_tosend = malloc(len);/*the resulting filename in .tosend +2 for 1*"/", +1 for \0 + .gz */ MALLOC_ASSERT(dst_tosend); snprintf(dst_tosend, len, "%s/%s%s", send_dir, dp->d_name, COMPRESS_EXTENSION); if (compress_file_to(cd_filename, dst_tosend, opts->CompressionLevel[which]) != 0) { free(dst_tosend); free(cd_filename); closedir(dir); return -1; } /*send file */ send_dumped_file(opts, dst_tosend); free(dst_tosend); free(cd_filename); } } else { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not open directory"), DLT_STRING(compress_dir)); return -1; } closedir(dir);/*end: compress_dir */ return 0; } int flush_dir_original(FiletransferOptions const *opts, int which) { struct dirent *dp; DIR *dir; const char *sdir = opts->Directory[which]; dir = opendir(sdir); if (dir != NULL) { while ((dp = readdir(dir)) != NULL) { if (dp->d_type != DT_REG) /*we don't send directories */ continue; DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, old file found in directory.")); int len = strlen(sdir) + strlen(dp->d_name) + 2; char *fn = malloc(len); MALLOC_ASSERT(fn); snprintf(fn, len, "%s/%s", sdir, dp->d_name); if (send_one(fn, opts, which) < 0) { closedir(dir); free(fn); return -1; } free(fn); } } else { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not open directory"), DLT_STRING(sdir)); return -1; } closedir(dir); return 0; } /*!Cleans the surveyed directories and subdirectories. Sends residing files into trace */ /** * @param opts FiletransferOptions * @param which which directory is affected -> position in list of opts->Directory * @return Returns 0 if everything was okay. If there was a failure a value < 0 will be returned. */ int flush_dir(FiletransferOptions const *opts, int which) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, flush directory of old files.")); char *compress_dir; char *send_dir; int len = strlen(opts->Directory[which]) + strlen(SUBDIR_COMPRESS) + 2; compress_dir = malloc (len); MALLOC_ASSERT(compress_dir); snprintf(compress_dir, len, "%s/%s", opts->Directory[which], SUBDIR_COMPRESS); len = strlen(opts->Directory[which]) + strlen(SUBDIR_TOSEND) + 2; send_dir = malloc (len); MALLOC_ASSERT(send_dir); snprintf(send_dir, len, "%s/%s", opts->Directory[which], SUBDIR_TOSEND); /*1st: scan the tosend directory. */ if (0 != flush_dir_send(opts, compress_dir, send_dir)) { free(send_dir); free(compress_dir); return -1; } /*1nd: scan the tocompress directory. */ if (0 != flush_dir_compress(opts, which, compress_dir, send_dir)) { free(send_dir); free(compress_dir); return -1; } free(send_dir);/*no more used */ free(compress_dir); /*last step: scan the original directory - we can reuse the send_one function */ if (0 != flush_dir_original(opts, which)) return -1; return 0; } /*!Initializes the surveyed directories */ /**On startup, the inotifiy handlers are created, and existing files shall be sent into DLT stream * @param config DltSystemConfiguration * @return Returns 0 if everything was okay. If there was a failure a value < 0 will be returned. */ int init_filetransfer_dirs(DltSystemConfiguration *config) { FiletransferOptions const *opts = &(config->Filetransfer); DLT_REGISTER_CONTEXT(filetransferContext, config->Filetransfer.ContextId, "Filetransfer Adapter"); DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, initializing inotify on directories.")); int i; #ifdef linux ino.handle = inotify_init(); if (ino.handle < 0) { DLT_LOG(filetransferContext, DLT_LOG_FATAL, DLT_STRING("Failed to initialize inotify in dlt-system file transfer.")); return -1; } #endif for (i = 0; i < opts->Count; i++) { /*create subdirectories for processing the files */ char *subdirpath; int len = strlen(opts->Directory[i]) + strlen(SUBDIR_COMPRESS) + 2; subdirpath = malloc (len); MALLOC_ASSERT(subdirpath); snprintf(subdirpath, len, "%s/%s", opts->Directory[i], SUBDIR_COMPRESS); int ret = mkdir(subdirpath, 0777); if ((0 != ret) && (EEXIST != errno)) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-filetransfer, error creating subdirectory: "), DLT_STRING(subdirpath), DLT_STRING(" Errorcode: "), DLT_INT(errno)); free (subdirpath); return -1; } free(subdirpath); len = strlen(opts->Directory[i]) + strlen(SUBDIR_TOSEND) + 2; subdirpath = malloc (len); MALLOC_ASSERT(subdirpath); snprintf(subdirpath, len, "%s/%s", opts->Directory[i], SUBDIR_TOSEND); ret = mkdir(subdirpath, 0777); if ((0 != ret) && (EEXIST != errno)) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-filetransfer, error creating subdirectory: "), DLT_STRING(subdirpath), DLT_STRING(" Errorcode: "), DLT_INT(errno)); free (subdirpath); return -1; } free(subdirpath); #ifdef linux ino.fd[i] = inotify_add_watch(ino.handle, opts->Directory[i], IN_CLOSE_WRITE | IN_MOVED_TO); if (ino.fd[i] < 0) { char buf[1024]; snprintf(buf, 1024, "Failed to add inotify watch to directory %s in dlt-system file transfer.", opts->Directory[i]); DLT_LOG(filetransferContext, DLT_LOG_FATAL, DLT_STRING(buf)); return -1; } #endif flush_dir(opts, i); } return 0; } int process_files(FiletransferOptions const *opts) { #ifdef linux DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, processing files.")); static char buf[INOTIFY_LEN]; ssize_t len = read(ino.handle, buf, INOTIFY_LEN); if (len < 0) { DLT_LOG(filetransferContext, DLT_LOG_ERROR, DLT_STRING("Error while reading events for files in dlt-system file transfer.")); return -1; } unsigned int i = 0; while (i < (len - INOTIFY_SZ)) { struct inotify_event *ie = (struct inotify_event *)&buf[i]; if (ie->len > 0) { if ((ie->mask & IN_CLOSE_WRITE) || (ie->mask & IN_MOVED_TO)) { int j; for (j = 0; j < opts->Count; j++) if (ie->wd == ino.fd[j]) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, found new file."), DLT_STRING(ie->name)); int length = strlen(opts->Directory[j]) + ie->len + 1; if (length > PATH_MAX) { DLT_LOG(filetransferContext, DLT_LOG_ERROR, DLT_STRING( "dlt-system-filetransfer: Very long path for file transfer. Cancelling transfer! Length is: "), DLT_INT(length)); return -1; } char *tosend = malloc(length); snprintf(tosend, length, "%s/%s", opts->Directory[j], ie->name); send_one(tosend, opts, j); free(tosend); } } } i += INOTIFY_SZ + ie->len; } #endif return 0; } void filetransfer_fd_handler(DltSystemConfiguration *config) { process_files(&(config->Filetransfer)); }dlt-daemon-2.18.10/src/system/dlt-system-journal.c000066400000000000000000000346211446635226000217610ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-journal.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-journal.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #if defined(DLT_SYSTEMD_JOURNAL_ENABLE) #include #include #include #include #include #include #include "dlt-system.h" #include #include #include /* for PRI formatting macro */ #include #define DLT_SYSTEM_JOURNAL_BUFFER_SIZE 256 #define DLT_SYSTEM_JOURNAL_BUFFER_SIZE_BIG 2048 #define DLT_SYSTEM_JOURNAL_ASCII_FIRST_VISIBLE_CHARACTER 31 #define DLT_SYSTEM_JOURNAL_BOOT_ID_MAX_LENGTH 9 + 32 + 1 typedef struct { char real[DLT_SYSTEM_JOURNAL_BUFFER_SIZE]; char monotonic[DLT_SYSTEM_JOURNAL_BUFFER_SIZE]; } MessageTimestamp; DLT_IMPORT_CONTEXT(dltsystem) DLT_DECLARE_CONTEXT(journalContext) int journal_checkUserBufferForFreeSpace() { int total_size, used_size; dlt_user_check_buffer(&total_size, &used_size); if ((total_size - used_size) < (total_size / 2)) return -1; return 1; } int dlt_system_journal_get(sd_journal *j, char *target, const char *field, size_t max_size) { char *data; size_t length; int error_code; size_t field_size; /* pre check parameters */ if ((max_size < 1) || (target == 0) || (field == 0) || (j == 0)) return -1; /* intialise empty target */ target[0] = 0; /* get data from journal */ error_code = sd_journal_get_data(j, field, (const void **)&data, &length); /* check if an error */ if (error_code) return error_code; /* calculate field size */ field_size = strlen(field) + 1; /*check length */ if (length < field_size) return -1; /* copy string */ if (max_size <= (length - field_size)) { /* truncate */ strncpy(target, data + field_size, max_size - 1); target[max_size - 1] = 0; } else { /* full copy */ strncpy(target, data + field_size, length - field_size); target[length - field_size] = 0; } /* debug messages */ /*printf("%s = %s\n",field,target); */ /* Success */ return 0; } void dlt_system_journal_get_timestamp(sd_journal *journal, MessageTimestamp *timestamp) { int ret = 0; time_t time_secs = 0; uint64_t time_usecs = 0; struct tm timeinfo; char buffer_realtime[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }; char buffer_realtime_formatted[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }; char buffer_monotime[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }; /* Try to get realtime from message source and if not successful try to get realtime from journal entry */ ret = dlt_system_journal_get(journal, buffer_realtime, "_SOURCE_REALTIME_TIMESTAMP", sizeof(buffer_realtime)); if ((ret == 0) && (strlen(buffer_realtime) > 0)) { errno = 0; time_usecs = strtoull(buffer_realtime, NULL, 10); if (errno != 0) time_usecs = 0; } else if ((ret = sd_journal_get_realtime_usec(journal, &time_usecs)) < 0) { DLT_LOG(dltsystem, DLT_LOG_WARN, DLT_STRING("dlt-system-journal failed to get realtime: "), DLT_STRING(strerror(-ret))); /* just to be sure to have a defined value */ time_usecs = 0; } time_secs = (time_t)(time_usecs / 1000000); tzset(); localtime_r(&time_secs, &timeinfo); strftime(buffer_realtime_formatted, sizeof(buffer_realtime_formatted), "%Y/%m/%d %H:%M:%S", &timeinfo); snprintf(timestamp->real, sizeof(timestamp->real), "%s.%06" PRIu64, buffer_realtime_formatted, time_usecs % 1000000); /* Try to get monotonic time from message source and if not successful try to get monotonic time from journal entry */ ret = dlt_system_journal_get(journal, buffer_monotime, "_SOURCE_MONOTONIC_TIMESTAMP", sizeof(buffer_monotime)); if ((ret == 0) && (strlen(buffer_monotime) > 0)) { errno = 0; time_usecs = strtoull(buffer_monotime, NULL, 10); if (errno != 0) time_usecs = 0; } else if ((ret = sd_journal_get_monotonic_usec(journal, &time_usecs, NULL)) < 0) { DLT_LOG(dltsystem, DLT_LOG_WARN, DLT_STRING("dlt-system-journal failed to get monotonic time: "), DLT_STRING(strerror(-ret))); /* just to be sure to have a defined value */ time_usecs = 0; } snprintf(timestamp->monotonic, sizeof(timestamp->monotonic), "%" PRId64 ".%06" PRIu64, time_usecs / 1000000, time_usecs % 1000000); } void get_journal_msg(sd_journal *j, DltSystemConfiguration *config) { uint32_t ts; int r; char buffer_process[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }, buffer_priority[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }, buffer_pid[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }, buffer_comm[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }, buffer_message[DLT_SYSTEM_JOURNAL_BUFFER_SIZE_BIG] = { 0 }, buffer_transport[DLT_SYSTEM_JOURNAL_BUFFER_SIZE] = { 0 }; MessageTimestamp timestamp; int loglevel, systemd_loglevel; char *systemd_log_levels[] = { "Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debug" }; for(;;) { r = sd_journal_next(j); if (r < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-journal failed to get next entry:"), DLT_STRING(strerror(-r))); sd_journal_close(j); return; } else if (r == 0) { return; } #if defined(DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYSTEM) && defined(DLT_SYSTEMD_JOURNAL_ENABLE) config->Journal.MessageReceived = 1; #endif /* get all data from current journal entry */ dlt_system_journal_get_timestamp(j, ×tamp); /* get data from journal entry, empty string if invalid fields */ dlt_system_journal_get(j, buffer_comm, "_COMM", sizeof(buffer_comm)); dlt_system_journal_get(j, buffer_pid, "_PID", sizeof(buffer_pid)); dlt_system_journal_get(j, buffer_priority, "PRIORITY", sizeof(buffer_priority)); dlt_system_journal_get(j, buffer_message, "MESSAGE", sizeof(buffer_message)); dlt_system_journal_get(j, buffer_transport, "_TRANSPORT", sizeof(buffer_transport)); /* prepare process string */ if (strcmp(buffer_transport, "kernel") == 0) snprintf(buffer_process, DLT_SYSTEM_JOURNAL_BUFFER_SIZE, "kernel:"); else snprintf(buffer_process, DLT_SYSTEM_JOURNAL_BUFFER_SIZE, "%s[%s]:", buffer_comm, buffer_pid); /* map log level on demand */ loglevel = DLT_LOG_INFO; systemd_loglevel = atoi(buffer_priority); if (config->Journal.MapLogLevels) { /* Map log levels from journal to DLT */ switch (systemd_loglevel) { case 0: /* Emergency */ case 1: /* Alert */ case 2: /* Critical */ loglevel = DLT_LOG_FATAL; break; case 3: /* Error */ loglevel = DLT_LOG_ERROR; break; case 4: /* Warning */ loglevel = DLT_LOG_WARN; break; case 5: /* Notice */ case 6: /* Informational */ loglevel = DLT_LOG_INFO; break; case 7: /* Debug */ loglevel = DLT_LOG_DEBUG; break; default: loglevel = DLT_LOG_INFO; break; } } if ((systemd_loglevel >= 0) && (systemd_loglevel <= 7)) snprintf(buffer_priority, DLT_SYSTEM_JOURNAL_BUFFER_SIZE, "%s:", systemd_log_levels[systemd_loglevel]); else snprintf(buffer_priority, DLT_SYSTEM_JOURNAL_BUFFER_SIZE, "prio_unknown:"); /* write log entry */ if (config->Journal.UseOriginalTimestamp == 0) { DLT_LOG(journalContext, loglevel, DLT_STRING(timestamp.real), DLT_STRING(timestamp.monotonic), DLT_STRING(buffer_process), DLT_STRING(buffer_priority), DLT_STRING(buffer_message) ); } else { /* since we are talking about points in time, I'd prefer truncating over arithmetic rounding */ ts = (uint32_t)(atof(timestamp.monotonic) * 10000); DLT_LOG_TS(journalContext, loglevel, ts, DLT_STRING(timestamp.real), DLT_STRING(buffer_process), DLT_STRING(buffer_priority), DLT_STRING(buffer_message) ); } if (journal_checkUserBufferForFreeSpace() == -1) { /* buffer is nearly full */ /* wait 500ms for writing next entry */ struct timespec t; t.tv_sec = 0; t.tv_nsec = 1000000ul * 500; nanosleep(&t, NULL); } } } void register_journal_fd(sd_journal **j, struct pollfd *pollfd, int i, DltSystemConfiguration *config) { DLT_REGISTER_CONTEXT(journalContext, config->Journal.ContextId, "Journal Adapter"); sd_journal *j_tmp; char match[DLT_SYSTEM_JOURNAL_BOOT_ID_MAX_LENGTH] = "_BOOT_ID="; sd_id128_t boot_id; int r; r = sd_journal_open(&j_tmp, SD_JOURNAL_LOCAL_ONLY /*SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY*/); printf("journal open return %d\n", r); if (r < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-journal, cannot open journal:"), DLT_STRING(strerror(-r))); printf("journal open failed: %s\n", strerror(-r)); j_tmp = NULL; } if (config->Journal.CurrentBoot) { /* show only current boot entries */ r = sd_id128_get_boot(&boot_id); if (r < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-journal failed to get boot id:"), DLT_STRING(strerror(-r))); sd_journal_close(j_tmp); j_tmp = NULL; } sd_id128_to_string(boot_id, match + 9); r = sd_journal_add_match(j_tmp, match, strlen(match)); if (r < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-journal failed to get match:"), DLT_STRING(strerror(-r))); sd_journal_close(j_tmp); j_tmp = NULL; } } if (config->Journal.Follow) { /* show only last 10 entries and follow */ r = sd_journal_seek_tail(j_tmp); if (r < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-journal failed to seek to tail:"), DLT_STRING(strerror(-r))); sd_journal_close(j_tmp); j_tmp = NULL; } r = sd_journal_previous_skip(j_tmp, 10); if (r < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-journal failed to seek back 10 entries:"), DLT_STRING(strerror(-r))); sd_journal_close(j_tmp); j_tmp = NULL; } } pollfd[i].fd = sd_journal_get_fd(j_tmp); if(pollfd[i].fd < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error while getting journal fd: "), DLT_STRING(strerror(pollfd[i].fd))); j_tmp = NULL; } pollfd[i].events = sd_journal_get_events(j_tmp); if(pollfd[i].events < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error while getting journal events: "), DLT_STRING(strerror(pollfd[i].events))); j_tmp = NULL; } *j = j_tmp; } void* journal_thread(void* journalParams) { struct journal_fd_params* params = (struct journal_fd_params*)journalParams; int ready; while (*params->quit == 0) { ready = poll(params->journalPollFd, 1, -1); if (ready == -1) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error while poll. Exit with: "), DLT_STRING(strerror(ready))); continue; } if(params->journalPollFd->revents & POLLIN) { if (sd_journal_process(params->j) == SD_JOURNAL_APPEND) { get_journal_msg(params->j, params->config); } } } // void* is only necessary to fulfill pthread_create signature return NULL; } #endif /* DLT_SYSTEMD_JOURNAL_ENABLE */ dlt-daemon-2.18.10/src/system/dlt-system-logfile.c000066400000000000000000000114451446635226000217270ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-logfile.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-logfile.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include #include "dlt-system.h" /* Modes of sending */ #define SEND_MODE_OFF 0 #define SEND_MODE_ONCE 1 #define SEND_MODE_ON 2 DLT_IMPORT_CONTEXT(dltsystem) DltContext logfileContext[DLT_SYSTEM_LOG_FILE_MAX]; int logfile_delays[DLT_SYSTEM_LOG_FILE_MAX]; void send_file(LogFileOptions const *fileopt, int n) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-logfile, sending file.")); FILE *pFile; DltContext context = logfileContext[n]; char buffer[1024]; int bytes; int seq = 1; pFile = fopen((*fileopt).Filename[n], "r"); if (pFile != NULL) { while (!feof(pFile)) { bytes = fread(buffer, 1, sizeof(buffer) - 1, pFile); if (bytes >= 0) buffer[bytes] = 0; else buffer[0] = 0; if (feof(pFile)) { DLT_LOG(context, DLT_LOG_INFO, DLT_INT(seq * -1), DLT_STRING(buffer)); break; } else { DLT_LOG(context, DLT_LOG_INFO, DLT_INT(seq++), DLT_STRING(buffer)); } } fclose(pFile); } else { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-logfile, failed to open file."), DLT_STRING((*fileopt).Filename[n])); } } void register_contexts(LogFileOptions const *fileopts) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-logfile, registering file contexts.")); int i; for (i = 0; i < (*fileopts).Count; i++) DLT_REGISTER_CONTEXT(logfileContext[i], (*fileopts).ContextId[i], (*fileopts).Filename[i]); } void logfile_init(void *v_conf) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-logfile, in thread.")); DltSystemConfiguration *conf = (DltSystemConfiguration *)v_conf; register_contexts(&(conf->LogFile)); for (int i = 0; i < conf->LogFile.Count; i++) logfile_delays[i] = conf->LogFile.TimeDelay[i]; } void logfile_fd_handler(void *v_conf) { DltSystemConfiguration *conf = (DltSystemConfiguration *)v_conf; for (int i = 0; i < conf->LogFile.Count; i++) { if (conf->LogFile.Mode[i] == SEND_MODE_OFF) continue; if (logfile_delays[i] <= 0) { send_file(&(conf->LogFile), i); logfile_delays[i] = conf->LogFile.TimeDelay[i]; if (conf->LogFile.Mode[i] == SEND_MODE_ONCE) conf->LogFile.Mode[i] = SEND_MODE_OFF; } else { logfile_delays[i]--; } } } dlt-daemon-2.18.10/src/system/dlt-system-options.c000066400000000000000000000404341446635226000220010ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-options.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-options.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** lm Lassi Marttala BMW ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include "dlt-system.h" #include #include /** * Print information how to use this program. */ void usage(char *prog_name) { char version[255]; dlt_get_version(version, 255); printf("Usage: %s [options]\n", prog_name); printf("Application to forward syslog messages to DLT, transfer system information, logs and files.\n"); printf("%s\n", version); printf("Options:\n"); printf(" -d Daemonize. Detach from terminal and run in background.\n"); printf(" -c filename Use configuration file. \n"); printf(" Default: %s\n", DEFAULT_CONF_FILE); printf(" -h This help message.\n"); } /** * Initialize command line options with default values. */ void init_cli_options(DltSystemCliOptions *options) { options->ConfigurationFileName = strdup(DEFAULT_CONF_FILE); options->freeConfigFileName = 0; options->Daemonize = 0; } /** * Read command line options and set the values in provided structure */ int read_command_line(DltSystemCliOptions *options, int argc, char *argv[]) { init_cli_options(options); int opt; while ((opt = getopt(argc, argv, "c:hd")) != -1) switch (opt) { case 'd': { options->Daemonize = 1; break; } case 'c': { options->ConfigurationFileName = malloc(strlen(optarg) + 1); options->freeConfigFileName = 1; MALLOC_ASSERT(options->ConfigurationFileName); strcpy(options->ConfigurationFileName, optarg); /* strcpy unritical here, because size matches exactly the size to be copied */ break; } case 'h': { usage(argv[0]); exit(0); return -1; /*for parasoft */ } default: { fprintf(stderr, "Unknown option '%c'\n", optopt); usage(argv[0]); return -1; } } return 0; } /** * Initialize configuration to default values. */ void init_configuration(DltSystemConfiguration *config) { int i = 0; /* Common */ strncpy(config->ApplicationId, "SYS", DLT_ID_SIZE); /* Shell */ config->Shell.Enable = 0; /* Syslog */ config->Syslog.Enable = 0; strncpy(config->Syslog.ContextId, "SYSL", DLT_ID_SIZE); config->Syslog.Port = 47111; /* Journal */ config->Journal.Enable = 0; strncpy(config->Journal.ContextId, "JOUR", DLT_ID_SIZE); config->Journal.CurrentBoot = 1; config->Journal.Follow = 0; config->Journal.MapLogLevels = 1; config->Journal.UseOriginalTimestamp = 1; /* File transfer */ config->Filetransfer.Enable = 0; strncpy(config->Filetransfer.ContextId, "FILE", DLT_ID_SIZE); config->Filetransfer.TimeStartup = 30; config->Filetransfer.TimeoutBetweenLogs = 10; config->Filetransfer.Count = 0; for (i = 0; i < DLT_SYSTEM_LOG_DIRS_MAX; i++) { config->Filetransfer.Directory[i] = NULL; config->Filetransfer.Compression[i] = 0; config->Filetransfer.CompressionLevel[i] = 5; } /* Log file */ config->LogFile.Enable = 0; config->LogFile.Count = 0; for (i = 0; i < DLT_SYSTEM_LOG_FILE_MAX; i++) { strncpy(config->LogFile.ContextId[i], "\0", DLT_ID_SIZE); config->LogFile.Filename[i] = NULL; config->LogFile.Mode[i] = 0; config->LogFile.TimeDelay[i] = 0; } /* Log process */ config->LogProcesses.Enable = 0; strncpy(config->LogProcesses.ContextId, "PROC", DLT_ID_SIZE); config->LogProcesses.Count = 0; for (i = 0; i < DLT_SYSTEM_LOG_PROCESSES_MAX; i++) { config->LogProcesses.Name[i] = NULL; config->LogProcesses.Filename[i] = NULL; config->LogProcesses.Mode[i] = 0; config->LogProcesses.TimeDelay[i] = 0; } } /** * Read options from the configuration file */ int read_configuration_file(DltSystemConfiguration *config, char *file_name) { FILE *file; char *line, *token, *value, *pch; int ret = 0; init_configuration(config); file = fopen(file_name, "r"); if (file == NULL) { fprintf(stderr, "dlt-system-options, could not open configuration file.\n"); return -1; } line = malloc(MAX_LINE); token = malloc(MAX_LINE); value = malloc(MAX_LINE); MALLOC_ASSERT(line); MALLOC_ASSERT(token); MALLOC_ASSERT(value); while (fgets(line, MAX_LINE, file) != NULL) { token[0] = 0; value[0] = 0; pch = strtok (line, " =\r\n"); while (pch != NULL) { if (pch[0] == '#') break; if (token[0] == 0) { strncpy(token, pch, MAX_LINE - 1); token[MAX_LINE - 1] = 0; } else { strncpy(value, pch, MAX_LINE); value[MAX_LINE - 1] = 0; break; } pch = strtok (NULL, " =\r\n"); } if (token[0] && value[0]) { /* Common */ if (strcmp(token, "ApplicationId") == 0) { strncpy(config->ApplicationId, value, DLT_ID_SIZE); } /* Shell */ else if (strcmp(token, "ShellEnable") == 0) { config->Shell.Enable = atoi(value); } /* Syslog */ else if (strcmp(token, "SyslogEnable") == 0) { config->Syslog.Enable = atoi(value); } else if (strcmp(token, "SyslogContextId") == 0) { strncpy(config->Syslog.ContextId, value, DLT_ID_SIZE); } else if (strcmp(token, "SyslogPort") == 0) { config->Syslog.Port = atoi(value); } /* Journal */ else if (strcmp(token, "JournalEnable") == 0) { config->Journal.Enable = atoi(value); } else if (strcmp(token, "JournalContextId") == 0) { strncpy(config->Journal.ContextId, value, DLT_ID_SIZE); } else if (strcmp(token, "JournalCurrentBoot") == 0) { config->Journal.CurrentBoot = atoi(value); } else if (strcmp(token, "JournalFollow") == 0) { config->Journal.Follow = atoi(value); } else if (strcmp(token, "JournalMapLogLevels") == 0) { config->Journal.MapLogLevels = atoi(value); } else if (strcmp(token, "JournalUseOriginalTimestamp") == 0) { config->Journal.UseOriginalTimestamp = atoi(value); } /* File transfer */ else if (strcmp(token, "FiletransferEnable") == 0) { config->Filetransfer.Enable = atoi(value); } else if (strcmp(token, "FiletransferContextId") == 0) { strncpy(config->Filetransfer.ContextId, value, DLT_ID_SIZE); } else if (strcmp(token, "FiletransferTimeStartup") == 0) { config->Filetransfer.TimeStartup = atoi(value); } else if (strcmp(token, "FiletransferTimeoutBetweenLogs") == 0) { config->Filetransfer.TimeoutBetweenLogs = atoi(value); } else if (strcmp(token, "FiletransferDirectory") == 0) { config->Filetransfer.Directory[config->Filetransfer.Count] = malloc(strlen(value) + 1); MALLOC_ASSERT(config->Filetransfer.Directory[config->Filetransfer.Count]); strcpy(config->Filetransfer.Directory[config->Filetransfer.Count], value); /* strcpy unritical here, because size matches exactly the size to be copied */ } else if (strcmp(token, "FiletransferCompression") == 0) { config->Filetransfer.Compression[config->Filetransfer.Count] = atoi(value); } else if (strcmp(token, "FiletransferCompressionLevel") == 0) { config->Filetransfer.CompressionLevel[config->Filetransfer.Count] = atoi(value); if (config->Filetransfer.Count < (DLT_SYSTEM_LOG_DIRS_MAX - 1)) { config->Filetransfer.Count++; } else { fprintf(stderr, "Too many file transfer directories configured. Maximum: %d\n", DLT_SYSTEM_LOG_DIRS_MAX); ret = -1; break; } } /* Log files */ else if (strcmp(token, "LogFileEnable") == 0) { config->LogFile.Enable = atoi(value); } else if (strcmp(token, "LogFileFilename") == 0) { config->LogFile.Filename[config->LogFile.Count] = malloc(strlen(value) + 1); MALLOC_ASSERT(config->LogFile.Filename[config->LogFile.Count]); strcpy(config->LogFile.Filename[config->LogFile.Count], value); /* strcpy unritical here, because size matches exactly the size to be copied */ } else if (strcmp(token, "LogFileMode") == 0) { config->LogFile.Mode[config->LogFile.Count] = atoi(value); } else if (strcmp(token, "LogFileTimeDelay") == 0) { config->LogFile.TimeDelay[config->LogFile.Count] = atoi(value); } else if (strcmp(token, "LogFileContextId") == 0) { strncpy(config->LogFile.ContextId[config->LogFile.Count], value, DLT_ID_SIZE); if (config->LogFile.Count < (DLT_SYSTEM_LOG_FILE_MAX - 1)) { config->LogFile.Count++; } else { fprintf(stderr, "Too many log files configured. Maximum: %d\n", DLT_SYSTEM_LOG_FILE_MAX); ret = -1; break; } } /* Log Processes */ else if (strcmp(token, "LogProcessesEnable") == 0) { config->LogProcesses.Enable = atoi(value); } else if (strcmp(token, "LogProcessesContextId") == 0) { strncpy(config->LogProcesses.ContextId, value, DLT_ID_SIZE); } else if (strcmp(token, "LogProcessName") == 0) { config->LogProcesses.Name[config->LogProcesses.Count] = malloc(strlen(value) + 1); MALLOC_ASSERT(config->LogProcesses.Name[config->LogProcesses.Count]); strcpy(config->LogProcesses.Name[config->LogProcesses.Count], value); /* strcpy unritical here, because size matches exactly the size to be copied */ } else if (strcmp(token, "LogProcessFilename") == 0) { config->LogProcesses.Filename[config->LogProcesses.Count] = malloc(strlen(value) + 1); MALLOC_ASSERT(config->LogProcesses.Filename[config->LogProcesses.Count]); strcpy(config->LogProcesses.Filename[config->LogProcesses.Count], value); /* strcpy unritical here, because size matches exactly the size to be copied */ } else if (strcmp(token, "LogProcessMode") == 0) { config->LogProcesses.Mode[config->LogProcesses.Count] = atoi(value); } else if (strcmp(token, "LogProcessTimeDelay") == 0) { config->LogProcesses.TimeDelay[config->LogProcesses.Count] = atoi(value); if (config->LogProcesses.Count < (DLT_SYSTEM_LOG_PROCESSES_MAX - 1)) { config->LogProcesses.Count++; } else { fprintf(stderr, "Too many processes to log configured. Maximum: %d\n", DLT_SYSTEM_LOG_PROCESSES_MAX); ret = -1; break; } } } } fclose(file); free(value); free(token); free(line); return ret; } void cleanup_config(DltSystemConfiguration *config, DltSystemCliOptions *options) { /* command line options */ if ((options->ConfigurationFileName) != NULL && options->freeConfigFileName) { free(options->ConfigurationFileName); options->ConfigurationFileName = NULL; } /* File transfer */ for(int i = 0 ; i < DLT_SYSTEM_LOG_DIRS_MAX ; i++) { if ((config->Filetransfer.Directory[i]) != NULL) { free(config->Filetransfer.Directory[i]); config->Filetransfer.Directory[i] = NULL; } } /* Log files */ for(int i = 0 ; i < DLT_SYSTEM_LOG_FILE_MAX ; i++) { if ((config->LogFile.Filename[i]) != NULL) { free(config->LogFile.Filename[i]); config->LogFile.Filename[i] = NULL; } } /* Log Processes */ for(int i = 0 ; i < DLT_SYSTEM_LOG_PROCESSES_MAX ; i++) { if ((config->LogProcesses.Filename[i]) != NULL) { free(config->LogProcesses.Filename[i]); config->LogProcesses.Filename[i] = NULL; } if ((config->LogProcesses.Name[i]) != NULL) { free(config->LogProcesses.Name[i]); config->LogProcesses.Name[i] = NULL; } } } dlt-daemon-2.18.10/src/system/dlt-system-process-handling.c000066400000000000000000000246321446635226000235500ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-process-handling.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-systemprocess-handling.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include "dlt.h" #include "dlt-system.h" #include #include #include #include #include #include #include #include #include #include #include DLT_IMPORT_CONTEXT(dltsystem) DLT_IMPORT_CONTEXT(syslogContext) DLT_IMPORT_CONTEXT(journalContext) DLT_IMPORT_CONTEXT(watchdogContext) DLT_IMPORT_CONTEXT(procContext) DLT_IMPORT_CONTEXT(filetransferContext) extern DltContext logfileContext[DLT_SYSTEM_LOG_FILE_MAX]; volatile uint8_t quit = 0; #if defined(DLT_FILETRANSFER_ENABLE) extern s_ft_inotify ino; #endif int daemonize() { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-process-handling, daemonize")); /* Fork new process */ int f = fork(); if (f < 0) return f; if (f > 0) exit(0); /* Create a new process group */ if (setsid() < 0) return -1; /** * Close all file descriptors and point * stdin, stdout and stderr to /dev/null */ int i; for (i = getdtablesize(); i >= 0; i--) close(i); int fd = open("/dev/null", O_RDWR); if (fd < 0) return -1; if ((dup(fd) < 0) || (dup(fd) < 0)) { close(fd); return -1; } /** * Ignore signals related to child processes and * terminal handling. */ signal(SIGCHLD, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); /*no close(fd); - we just intentionally pointed stdx to null! tbd: set ignore for coverity */ return 0; } /* Unregisters all DLT Contexts and closes all file descriptors */ void cleanup_processes(struct pollfd *pollfd, struct pollfd *journalPollFd, sd_journal *j, DltSystemConfiguration *config) { //Syslog cleanup if (config->Syslog.Enable) DLT_UNREGISTER_CONTEXT(syslogContext); //Journal cleanup #if defined(DLT_SYSTEMD_JOURNAL_ENABLE) if (config->Journal.Enable) DLT_UNREGISTER_CONTEXT(journalContext); if(j != NULL) sd_journal_close(j); if(journalPollFd->fd > 0) close(journalPollFd->fd); #else // silence warnings (void)j; (void)journalPollFd->fd; #endif //Logfile cleanup if (config->LogFile.Enable) { for (int i = 0; i < config->LogFile.Count; i++) DLT_UNREGISTER_CONTEXT(logfileContext[i]); } //LogProcess cleanup if (config->LogProcesses.Enable) { DLT_UNREGISTER_CONTEXT(procContext); } //Watchdog cleanup #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) DLT_UNREGISTER_CONTEXT(watchdogContext); #endif //FileTransfer cleanup #if defined(DLT_FILETRANSFER_ENABLE) if (config->Filetransfer.Enable) { DLT_UNREGISTER_CONTEXT(filetransferContext); } #endif for (int i = 0; i < MAX_FD_NUMBER; i++) { if(pollfd[i].fd > 0) close(pollfd[i].fd); } } /* Creates timer for LogFile and LogProcess, that need to be called every second. */ int register_timer_fd(struct pollfd *pollfd, int fdcnt) { struct itimerspec timerValue; memset(&timerValue, '\0', sizeof(timerValue)); timerValue.it_value.tv_sec = 1; timerValue.it_value.tv_nsec = 0; timerValue.it_interval.tv_sec = 1; timerValue.it_interval.tv_nsec = 0; int timerfd = timerfd_create(CLOCK_MONOTONIC, 0); if (timerfd < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Failed to create timer fd")); return -1; } pollfd[fdcnt].fd = timerfd; pollfd[fdcnt].events = POLLIN; if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) { // init timer with 1 second DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not start timer")); return -1; } return 0; } /* Routine for executing LogProcess and LogFile, when timer expires */ void timer_fd_handler(int fd, DltSystemConfiguration *config) { uint64_t timersElapsed = 0ULL; int r = read(fd, &timersElapsed, 8U); // only needed to reset fd event if (r < 0) DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error while reading timer fd: "), DLT_STRING(strerror(r))); if(config->LogProcesses.Enable) logprocess_fd_handler(config); if(config->LogFile.Enable) logfile_fd_handler(config); } void start_dlt_system_processes(DltSystemConfiguration *config) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-process-handling, start threads")); if (config->Shell.Enable) init_shell(); int fdcnt = 0; /* Init FDs for all activated processes*/ struct pollfd pollfd[MAX_FD_NUMBER]; // Holds all FDs and events uint8_t fdType[MAX_FD_NUMBER]; // Holds corresponding enum for process identification for(int cnt = 0 ; cnt < MAX_FD_NUMBER ; cnt++) { pollfd[cnt].fd = 0; pollfd[cnt].events = 0; } //init FD for LogFile and LogProcesses if (config->LogProcesses.Enable || config->LogFile.Enable) { fdType[fdcnt] = fdType_timer; if (register_timer_fd(pollfd, fdcnt) == 0) { if(config->LogProcesses.Enable) logprocess_init(config); if(config->LogFile.Enable) logfile_init(config); fdcnt++; } } //init FD for Syslog int syslogSock = 0; if (config->Syslog.Enable) { fdType[fdcnt] = fdType_syslog; syslogSock = register_syslog_fd(pollfd, fdcnt, config); fdcnt++; } //init FD for Journal sd_journal *j = NULL; struct pollfd journalPollFd; #if defined(DLT_SYSTEMD_JOURNAL_ENABLE) pthread_t journalThreadHandle; if (config->Journal.Enable) { register_journal_fd(&j, &journalPollFd, 0, config); struct journal_fd_params params = { &quit, &journalPollFd, j, config }; if (pthread_create(&journalThreadHandle, NULL, &journal_thread, (void*)¶ms) != 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Failed to create journal_thread thread "), DLT_STRING(strerror(errno))); } } #endif //init FD for FileTransfer #if defined(DLT_FILETRANSFER_ENABLE) if (config->Filetransfer.Enable) { init_filetransfer_dirs(config); pollfd[fdcnt].fd = ino.handle; pollfd[fdcnt].events = POLLIN; fdType[fdcnt] = fdType_filetransfer; fdcnt++; } #endif //init FD for Watchdog #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) fdType[fdcnt] = fdType_watchdog; register_watchdog_fd(pollfd, fdcnt); #endif while (quit == 0) { int ready; ready = poll(pollfd, MAX_FD_NUMBER, -1); if (ready == -1 && quit == 0) DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error while poll. Exit with: "), DLT_STRING(strerror(ready))); for (int i = 0; i < MAX_FD_NUMBER; i++) { if(pollfd[i].revents & POLLIN){ if (fdType[i] == fdType_syslog && syslogSock > 0) { syslog_fd_handler(syslogSock); } else if (fdType[i] == fdType_timer) { timer_fd_handler(pollfd[i].fd, config); } #if defined(DLT_FILETRANSFER_ENABLE) else if (fdType[i] == fdType_filetransfer) { filetransfer_fd_handler(config); } #endif #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) else if (fdType[i] == fdType_watchdog) { #if defined(DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYSTEM) && defined(DLT_SYSTEMD_JOURNAL_ENABLE) watchdog_fd_handler(pollfd[i].fd, &config->Journal.MessageReceived); #else watchdog_fd_handler(pollfd[i].fd); #endif } #endif } } } #if defined(DLT_SYSTEMD_JOURNAL_ENABLE) if (config->Journal.Enable) { pthread_join(journalThreadHandle, NULL); } #endif cleanup_processes(pollfd, &journalPollFd, j, config); } void dlt_system_signal_handler(int sig) { switch (sig) { case SIGHUP: case SIGTERM: case SIGINT: case SIGQUIT: quit = 1; break; default: break; } } dlt-daemon-2.18.10/src/system/dlt-system-processes.c000066400000000000000000000131451446635226000223130ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-processes.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-processes.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include #include #include #include #include #include #include #include "dlt-system.h" /* Modes of sending */ #define SEND_MODE_OFF 0 #define SEND_MODE_ONCE 1 #define SEND_MODE_ON 2 int process_delays[DLT_SYSTEM_LOG_PROCESSES_MAX]; DLT_IMPORT_CONTEXT(dltsystem) DLT_DECLARE_CONTEXT(procContext) void send_process(LogProcessOptions const *popts, int n) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-processes, send process info.")); FILE *pFile; struct dirent *dp; char filename[PATH_MAX]; char buffer[1024]; int bytes; int found = 0; /* go through all process files in directory */ DIR *dir = opendir("/proc"); if (dir != NULL) { while ((dp = readdir(dir)) != NULL) if (isdigit(dp->d_name[0])) { buffer[0] = 0; snprintf(filename, PATH_MAX, "/proc/%s/cmdline", dp->d_name); pFile = fopen(filename, "r"); if (pFile != NULL) { bytes = fread(buffer, 1, sizeof(buffer) - 1, pFile); fclose(pFile); } if ((strcmp((*popts).Name[n], "*") == 0) || (strcmp(buffer, (*popts).Name[n]) == 0)) { found = 1; snprintf(filename, PATH_MAX, "/proc/%s/%s", dp->d_name, (*popts).Filename[n]); pFile = fopen(filename, "r"); if (pFile != NULL) { bytes = fread(buffer, 1, sizeof(buffer) - 1, pFile); fclose(pFile); if (bytes > 0) { buffer[bytes] = 0; DLT_LOG(procContext, DLT_LOG_INFO, DLT_INT(atoi(dp->d_name)), DLT_STRING((*popts).Filename[n]), DLT_STRING(buffer)); } } if (strcmp((*popts).Name[n], "*") != 0) break; } } closedir(dir); } else { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("dlt-system-processes, failed to open /proc.")); } if (!found) DLT_LOG(procContext, DLT_LOG_INFO, DLT_STRING("Process"), DLT_STRING((*popts).Name[n]), DLT_STRING("not running!")); } void logprocess_init(void *v_conf) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-processes, in thread.")); DltSystemConfiguration *conf = (DltSystemConfiguration *)v_conf; DLT_REGISTER_CONTEXT(procContext, conf->LogProcesses.ContextId, "Log Processes"); for (int i = 0; i < conf->LogProcesses.Count; i++) process_delays[i] = conf->LogProcesses.TimeDelay[i]; } void logprocess_fd_handler(void *v_conf) { DltSystemConfiguration *conf = (DltSystemConfiguration *)v_conf; for (int i = 0; i < conf->LogProcesses.Count; i++) { if (conf->LogProcesses.Mode[i] == SEND_MODE_OFF) continue; if (process_delays[i] <= 0) { send_process(&(conf->LogProcesses), i); process_delays[i] = conf->LogProcesses.TimeDelay[i]; if (conf->LogProcesses.Mode[i] == SEND_MODE_ONCE) conf->LogProcesses.Mode[i] = SEND_MODE_OFF; } else { process_delays[i]--; } } } dlt-daemon-2.18.10/src/system/dlt-system-shell.c000066400000000000000000000115111446635226000214070ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-shell.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-shell.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** lm Lassi Marttala BMW ** *******************************************************************************/ #include "dlt.h" #include "dlt-system.h" #include #include #define DLT_SHELL_COMMAND_MAX_LENGTH 1024 DLT_IMPORT_CONTEXT(dltsystem) DLT_DECLARE_CONTEXT(shellContext) int dlt_shell_injection_callback(uint32_t service_id, void *data, uint32_t length) { (void)length; DLT_LOG(shellContext, DLT_LOG_DEBUG, DLT_STRING("dlt-system-shell, injection callback")); char text[DLT_SHELL_COMMAND_MAX_LENGTH]; int syserr = 0; if (length <= DLT_SHELL_COMMAND_MAX_LENGTH - 1) { strncpy(text, data, length); text[length] = 0; } else { strncpy(text, data, DLT_SHELL_COMMAND_MAX_LENGTH - 1); text[DLT_SHELL_COMMAND_MAX_LENGTH - 1] = 0; } DLT_LOG(shellContext, DLT_LOG_DEBUG, DLT_STRING("dlt-system-shell, injection injection id:"), DLT_UINT32(service_id)); DLT_LOG(shellContext, DLT_LOG_DEBUG, DLT_STRING("dlt-system-shell, injection data:"), DLT_STRING(text)); switch (service_id) { case 0x1001: if ((syserr = system(text)) != 0) DLT_LOG(shellContext, DLT_LOG_ERROR, DLT_STRING("dlt-system-shell, abnormal exit status."), DLT_STRING(text), DLT_INT(syserr)); else DLT_LOG(shellContext, DLT_LOG_INFO, DLT_STRING("Shell command executed:"), DLT_STRING(text)); break; default: DLT_LOG(shellContext, DLT_LOG_ERROR, DLT_STRING("dlt-system-shell, unknown command received."), DLT_UINT32(service_id), DLT_STRING(text)); break; } return 0; } void init_shell() { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-shell, register callback")); DLT_REGISTER_CONTEXT(shellContext, "CMD", "Execute Shell commands"); DLT_REGISTER_INJECTION_CALLBACK(shellContext, 0x1001, dlt_shell_injection_callback); } dlt-daemon-2.18.10/src/system/dlt-system-syslog.c000066400000000000000000000123741446635226000216300ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-syslog.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system-syslog.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include #include #include #include #include #include #include #include "dlt-system.h" DLT_IMPORT_CONTEXT(dltsystem) DLT_DECLARE_CONTEXT(syslogContext) #define RECV_BUF_SZ 1024 int init_socket(SyslogOptions opts) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-syslog, init socket, port: "), DLT_INT(opts.Port)); int sock = -1; #ifdef DLT_USE_IPv6 /* declare struct for IPv6 socket address*/ struct sockaddr_in6 syslog_addr; sock = socket(AF_INET6, SOCK_DGRAM, 0); #else /* declare struct for IPv4 socket address*/ struct sockaddr_in syslog_addr; sock = socket(AF_INET, SOCK_DGRAM, 0); #endif if (sock < 0) { DLT_LOG(syslogContext, DLT_LOG_FATAL, DLT_STRING("Unable to create socket for SYSLOG.")); return -1; } /* initialize struct syslog_addr */ memset(&syslog_addr, 0, sizeof(syslog_addr)); #ifdef DLT_USE_IPv6 syslog_addr.sin6_family = AF_INET6; syslog_addr.sin6_addr = in6addr_any; syslog_addr.sin6_port = htons(opts.Port); #else syslog_addr.sin_family = AF_INET; syslog_addr.sin_addr.s_addr = INADDR_ANY; syslog_addr.sin_port = htons(opts.Port); memset(&(syslog_addr.sin_zero), 0, 8); #endif /* bind the socket address to local interface */ if (bind(sock, (struct sockaddr *)&syslog_addr, sizeof(syslog_addr)) == -1) { DLT_LOG(syslogContext, DLT_LOG_FATAL, DLT_STRING("Unable to bind socket for SYSLOG, error description: "), DLT_STRING(strerror(errno))); close(sock); return -1; } return sock; } int read_socket(int sock) { DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-syslog, read socket")); char recv_data[RECV_BUF_SZ]; struct sockaddr_in client_addr; socklen_t addr_len = sizeof(struct sockaddr_in); int bytes_read = recvfrom(sock, recv_data, RECV_BUF_SZ, 0, (struct sockaddr *)&client_addr, &addr_len); if (bytes_read == -1) { if (errno == EINTR) { return 0; } else { DLT_LOG(syslogContext, DLT_LOG_FATAL, DLT_STRING("Read from socket failed in SYSLOG.")); return -1; } } recv_data[bytes_read] = '\0'; if (bytes_read != 0) { DLT_LOG(syslogContext, DLT_LOG_INFO, DLT_STRING(recv_data)); } return bytes_read; } int register_syslog_fd(struct pollfd *pollfd, int i, DltSystemConfiguration *config) { DLT_REGISTER_CONTEXT(syslogContext, config->Syslog.ContextId, "SYSLOG Adapter"); int syslogSock = init_socket(config->Syslog); if (syslogSock < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not init syslog socket\n")); return -1; } pollfd[i].fd = syslogSock; pollfd[i].events = POLLIN; return syslogSock; } void syslog_fd_handler(int syslogSock) { read_socket(syslogSock); }dlt-daemon-2.18.10/src/system/dlt-system-watchdog.c000066400000000000000000000103171446635226000221030ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Lassi Marttala * Alexander Wenzel * Markus Klein * Mikko Rapeli * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system-watchdog.c */ #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) #include #include #include #include #include "dlt.h" #include "dlt-system.h" #include #include DLT_DECLARE_CONTEXT(watchdogContext) DLT_IMPORT_CONTEXT(dltsystem) int calculate_period(struct itimerspec *itval) { unsigned int ns; unsigned int sec; char str[512]; char *watchdogUSec; unsigned int watchdogTimeoutSeconds; unsigned int notifiyPeriodNSec; watchdogUSec = getenv("WATCHDOG_USEC"); if (watchdogUSec == NULL) { DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("systemd watchdog timeout (WATCHDOG_USEC) is null\n")); return -1; } DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING("watchdogusec: "), DLT_STRING(watchdogUSec)); watchdogTimeoutSeconds = atoi(watchdogUSec); if (watchdogTimeoutSeconds <= 0) { snprintf(str, 512, "systemd watchdog timeout incorrect: %u\n", watchdogTimeoutSeconds); DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING(str)); return -1; } /* Calculate half of WATCHDOG_USEC in ns for timer tick */ notifiyPeriodNSec = watchdogTimeoutSeconds / 2; snprintf(str, 512, "systemd watchdog timeout: %u nsec - timer will be initialized: %u nsec\n", watchdogTimeoutSeconds, notifiyPeriodNSec); DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING(str)); /* Make the timer periodic */ sec = notifiyPeriodNSec / 1000000; ns = (notifiyPeriodNSec - (sec * 1000000)) * 1000; itval->it_interval.tv_sec = sec; itval->it_interval.tv_nsec = ns; itval->it_value.tv_sec = sec; itval->it_value.tv_nsec = ns; return 0; } int register_watchdog_fd(struct pollfd *pollfd, int fdcnt) { DLT_REGISTER_CONTEXT(watchdogContext, "DOG", "dlt system watchdog context."); struct itimerspec timerValue; if (calculate_period(&timerValue) != 0) return -1; int timerfd = timerfd_create(CLOCK_MONOTONIC, 0); if (timerfd < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Failed to create timer fd\n")); return -1; } pollfd[fdcnt].fd = timerfd; pollfd[fdcnt].events = POLLIN; if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Could not start timer\n")); return -1; } return 0; } #if defined(DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYSTEM) && defined(DLT_SYSTEMD_JOURNAL_ENABLE) void watchdog_fd_handler(int fd, int* received_message_since_last_watchdog_interval) #else void watchdog_fd_handler(int fd) #endif { uint64_t timersElapsed = 0ULL; int r = read(fd, &timersElapsed, 8U); // only needed to reset fd event if(r < 0) DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Could not reset systemd watchdog. Exit with: "), DLT_STRING(strerror(r))); #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYSTEM if (!*received_message_since_last_watchdog_interval) { dlt_log(LOG_WARNING, "No new messages received since last watchdog timer run\n"); return; } *received_message_since_last_watchdog_interval = 0; #endif if (sd_notify(0, "WATCHDOG=1") < 0) DLT_LOG(watchdogContext, DLT_LOG_ERROR, DLT_STRING("Could not reset systemd watchdog\n")); DLT_LOG(watchdogContext, DLT_LOG_DEBUG, DLT_STRING("systemd watchdog waited periodic\n")); } #endif dlt-daemon-2.18.10/src/system/dlt-system.c000066400000000000000000000106351446635226000203100ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include "dlt-system.h" #include #include #include #include #include #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) # include "sd-daemon.h" #endif DLT_DECLARE_CONTEXT(dltsystem) int main(int argc, char *argv[]) { DltSystemCliOptions options = {0}; DltSystemConfiguration config = {0}; #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) int ret; #endif if (read_command_line(&options, argc, argv) < 0) { fprintf(stderr, "Failed to read command line!\n"); return -1; } if (read_configuration_file(&config, options.ConfigurationFileName) < 0) { fprintf(stderr, "Failed to read configuration file!\n"); return -1; } DLT_REGISTER_APP(config.ApplicationId, "DLT System Manager"); DLT_REGISTER_CONTEXT(dltsystem, "MGR", "Context of main dlt system manager"); #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) ret = sd_booted(); if (ret == 0) { DLT_LOG(dltsystem, DLT_LOG_INFO, DLT_STRING("system not booted with systemd!\n")); } else if (ret < 0) { DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("sd_booted failed!\n")); return -1; } else { DLT_LOG(dltsystem, DLT_LOG_INFO, DLT_STRING("system booted with systemd\n")); } #endif DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("Configuration loaded.")); if (options.Daemonize > 0) { if (daemonize() < 0) { DLT_LOG(dltsystem, DLT_LOG_FATAL, DLT_STRING("Daemonization failed!")); return -1; } DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system daemonized.")); } DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("Setting signal handlers for abnormal exit")); signal(SIGTERM, dlt_system_signal_handler); signal(SIGHUP, dlt_system_signal_handler); signal(SIGQUIT, dlt_system_signal_handler); signal(SIGINT, dlt_system_signal_handler); DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("Initializing all processes and starting poll for events.")); start_dlt_system_processes(&config); cleanup_config(&config, &options); exit(0); } dlt-daemon-2.18.10/src/system/dlt-system.conf000066400000000000000000000144171446635226000210150ustar00rootroot00000000000000# Configuration file of DLT system manager # ######################################################################## # General configuration ######################################################################## # The application Id used for the System manager (Default: SYS) ApplicationId = SYS ######################################################################## # Shell configuration ######################################################################## # Be careful when you enable this feature. The user can send any kind of # shell commands. The commands are executed with the rights of the # dlt-system process. Dlt-system is started by default as user covesa. # Enable the Shell for command line injections (Default: 0) ShellEnable = 0 ######################################################################## # Syslog Adapter configuration ######################################################################## # Enable the Syslog Adapter (Default: 0) # Enable only when systemd is already running in your system otherwise # logs will not come to Client (e.g. dlt_viewer). SyslogEnable = 0 # The Context Id of the syslog adapter (Default: SYSL) SyslogContextId = SYSL # The UDP port opened by DLT system mamager to receive system logs (Default: 47111) SyslogPort = 47111 ######################################################################## # Systemd Journal Adapter configuration ######################################################################## # This feature is only available, when dlt is compiled with # the option "WITH_SYSTEMD_JOURNAL" # Dlt-system is started by default as user covesa, see dlt-system.service file. # The user covesa must be added to one of the groups 'adm', 'wheel' or # 'systemd-journal' to have access to all journal entries. # Enable Systemd Journal Adapter only when your system doesn't have systemd. # Don't enable both (SyslogEnable = 1 and JournalEnable = 1) together because # it causes bind error (can see on connected client). # Enable the Systemd Journal Adapter (Default: 0) JournalEnable = 0 # The Context Id of the journal adapter (Default: JOUR) JournalContextId = JOUR # Show only log entries of current boot and follow (Default: 1) # if not JournalCurrentBoot and not JournalFollow is set all # persistent journal entries will be logged JournalCurrentBoot = 1 # Show only the last 10 entries and follow (Default: 0) JournalFollow = 0 # Map the log levels (Default: 1) # Mapping journal log levels to DLT log levels # 0 Emergency DLT_LOG_FATAL # 1 Alert DLT_LOG_FATAL # 2 Critical DLT_LOG_FATAL # 3 Error DLT_LOG_ERROR # 4 Warning DLT_LOG_WARN # 5 Notice DLT_LOG_INFO # 6 Informational DLT_LOG_INFO # 7 Debug DLT_LOG_DEBUG JournalMapLogLevels = 1 # Use the original timestamp (uptime when the event actually occured) as DLT timestamp (Default: 1) JournalUseOriginalTimestamp = 1 ######################################################################## # Filetransfer Manager ######################################################################## # Enable the Filetransfer (Default: 0) FiletransferEnable = 0 # The Context Id of the filetransfer (Default: FILE) FiletransferContextId = FILE # Time in seconds after startup of dlt-system when first file is transfered (Default: 0) FiletransferTimeStartup = 0 # Time in ms seconds to wait between two file transfer logs of a single file to DLT. (Default: 10) FiletransferTimeoutBetweenLogs = 5 # You can define multiple file transfer directories # Define the directory to watch, whether to compress # the file with zlib and the zlib compression level # For parsing purposes, FiletransferCompressionLevel # must be the last one of three values. # For compressing and sending following subdirectories are used: .tocompress and .tosend FiletransferDirectory = /var/dlt/ft1 FiletransferCompression = 1 FiletransferCompressionLevel = 5 # Second directory to watch FiletransferDirectory = /var/dlt/ft2 FiletransferCompression = 0 FiletransferCompressionLevel = 5 # And so on... FiletransferDirectory = /var/dlt/ft3 FiletransferCompression = 0 FiletransferCompressionLevel = 5 ######################################################################## # Log short files, especially from proc filesystem ######################################################################## # Enable the logging of files (Default: 0) LogFileEnable = 0 # Log different files # Mode: 0 = off, 1 = startup only, 2 = regular # TimeDelay: If mode regular is set, time delay is the number of seconds for next sent # Log the file /etc/sysrel LogFileFilename = /etc/sysrel LogFileMode = 1 LogFileTimeDelay = 3 LogFileContextId = VER # Log the file /proc/version LogFileFilename = /proc/version LogFileMode = 1 LogFileTimeDelay = 3 LogFileContextId = VERK # Log the file /proc/meminfo # LogFileFilename = /proc/meminfo # LogFileMode = 2 # LogFileTimeDelay = 5 # LogFileContextId = MEM # Log the file /proc/cpuinfo # LogFileFilename = /proc/cpuinfo # LogFileMode = 2 # LogFileTimeDelay = 5 # LogFileContextId = CPU # Log the file /proc/stat LogFileFilename = /proc/stat LogFileMode = 2 LogFileTimeDelay = 1 LogFileContextId = STAT # Log the file /proc/modules # LogFileFilename = /proc/modules # LogFileMode = 2 # LogFileTimeDelay = 5 # LogFileContextId = MOD # Log the file /proc/ioports # LogFileFilename = /proc/ioports # LogFileMode = 1 # LogFileTimeDelay = 5 # LogFileContextId = IOP # Log the file /proc/iomem # LogFileFilename = /proc/iomem # LogFileMode = 1 # LogFileTimeDelay = 5 # LogFileContextId = IOM ######################################################################## # Log Processes ######################################################################## # Enable the logging of processes (Default: 0) LogProcessesEnable = 0 # The Context Id of the kernel version (Default: PROC) LogProcessesContextId = PROC # Log different processes # Name: * = all process, X=alternative name (must correspind to /proc/X/cmdline # Filename: the filename in the subdirectory /proc/processid/ # Mode: 0 = off, 1 = startup only, 2 = regular # TimeDelay: If mode regular is set, time delay is the number of seconds for next sent LogProcessName = * LogProcessFilename = stat LogProcessMode = 2 LogProcessTimeDelay = 5 # LogProcessName = dlt_viewer # LogProcessFilename = stat # LogProcessMode = 2 # LogProcessTimeDelay = 1 dlt-daemon-2.18.10/src/system/dlt-system.h000066400000000000000000000172501446635226000203150ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-system.h */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-system.h ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** lm Lassi Marttala BMW ** *******************************************************************************/ #ifndef DLT_SYSTEM_H_ #define DLT_SYSTEM_H_ #include #include /* DLT related includes. */ #include "dlt.h" #include "dlt_common.h" /* Constants */ #define DEFAULT_CONF_FILE (CONFIGURATION_FILES_DIR "/dlt-system.conf") #define DLT_SYSTEM_LOG_FILE_MAX 32 #define DLT_SYSTEM_LOG_DIRS_MAX 32 #define DLT_SYSTEM_LOG_PROCESSES_MAX 32 #define DLT_SYSTEM_MODE_OFF 0 #define DLT_SYSTEM_MODE_STARTUP 1 #define DLT_SYSTEM_MODE_REGULAR 2 #define MAX_LINE 1024 /** Total number of file descriptors needed for processing all features: * - Syslog file descriptor * - Timer file descriptor for processing LogFile and LogProcesses every second * - Inotify file descriptor for FileTransfer * - Timer file descriptor for Watchdog */ #define MAX_FD_NUMBER 4 /* Macros */ #define MALLOC_ASSERT(x) if (x == NULL) { \ fprintf(stderr, "Out of memory\n"); \ abort(); } /* enum for classification of FD */ enum fdType { fdType_syslog = 0, fdType_filetransfer, fdType_timer, fdType_watchdog, }; /** * Configuration structures. * Please see dlt-system.conf for explanation of all the options. */ /* Command line options */ typedef struct { char *ConfigurationFileName; int freeConfigFileName; int Daemonize; } DltSystemCliOptions; /* Configuration shell options */ typedef struct { int Enable; } ShellOptions; /* Configuration syslog options */ typedef struct { int Enable; char ContextId[DLT_ID_SIZE]; int Port; } SyslogOptions; /* Configuration journal options */ typedef struct { int Enable; char ContextId[DLT_ID_SIZE]; int CurrentBoot; int Follow; int MapLogLevels; int UseOriginalTimestamp; #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYSTEM int MessageReceived; #endif } JournalOptions; typedef struct { int Enable; char ContextId[DLT_ID_SIZE]; int TimeStartup; int TimeoutBetweenLogs; /* Variable number of file transfer dirs */ int Count; int Compression[DLT_SYSTEM_LOG_DIRS_MAX]; int CompressionLevel[DLT_SYSTEM_LOG_DIRS_MAX]; char *Directory[DLT_SYSTEM_LOG_DIRS_MAX]; } FiletransferOptions; typedef struct { int handle; int fd[DLT_SYSTEM_LOG_DIRS_MAX]; } s_ft_inotify; typedef struct { int Enable; /* Variable number of files to transfer */ int Count; char ContextId[DLT_SYSTEM_LOG_FILE_MAX][DLT_ID_SIZE]; char *Filename[DLT_SYSTEM_LOG_FILE_MAX]; int Mode[DLT_SYSTEM_LOG_FILE_MAX]; int TimeDelay[DLT_SYSTEM_LOG_FILE_MAX]; } LogFileOptions; typedef struct { int Enable; char ContextId[DLT_ID_SIZE]; /* Variable number of processes */ int Count; char *Name[DLT_SYSTEM_LOG_PROCESSES_MAX]; char *Filename[DLT_SYSTEM_LOG_PROCESSES_MAX]; int Mode[DLT_SYSTEM_LOG_PROCESSES_MAX]; int TimeDelay[DLT_SYSTEM_LOG_PROCESSES_MAX]; } LogProcessOptions; typedef struct { char ApplicationId[DLT_ID_SIZE]; ShellOptions Shell; SyslogOptions Syslog; JournalOptions Journal; FiletransferOptions Filetransfer; LogFileOptions LogFile; LogProcessOptions LogProcesses; } DltSystemConfiguration; /** * Forward declarations for the whole application */ /* In dlt-system-options.c */ int read_command_line(DltSystemCliOptions *options, int argc, char *argv[]); int read_configuration_file(DltSystemConfiguration *config, char *file_name); void cleanup_config(DltSystemConfiguration *config, DltSystemCliOptions *options); /* For dlt-process-handling.c */ int daemonize(); void init_shell(); void dlt_system_signal_handler(int sig); /* Main function for creating/registering all needed file descriptors and starting the poll for all of them. */ void start_dlt_system_processes(DltSystemConfiguration *config); /* Init process, create file descriptors and register them into main pollfd. */ int register_watchdog_fd(struct pollfd *pollfd, int fdcnt); int init_filetransfer_dirs(DltSystemConfiguration *config); void logfile_init(void *v_conf); void logprocess_init(void *v_conf); void register_journal_fd(sd_journal **j, struct pollfd *pollfd, int i, DltSystemConfiguration *config); int register_syslog_fd(struct pollfd *pollfd, int i, DltSystemConfiguration *config); /* Routines that are called, when a fd event was raised. */ void logfile_fd_handler(void *v_conf); void logprocess_fd_handler(void *v_conf); void filetransfer_fd_handler(DltSystemConfiguration *config); #if defined(DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE_DLT_SYSTEM) && defined(DLT_SYSTEMD_JOURNAL_ENABLE) void watchdog_fd_handler(int fd, int* received_message_since_last_watchdog_interval); #else void watchdog_fd_handler(int fd); #endif void journal_fd_handler(sd_journal *j, DltSystemConfiguration *config); struct journal_fd_params { volatile uint8_t* quit; struct pollfd* journalPollFd; sd_journal *j; DltSystemConfiguration *config; }; void *journal_thread(void* journalParams); void syslog_fd_handler(int syslogSock); #endif /* DLT_SYSTEM_H_ */ dlt-daemon-2.18.10/src/tests/000077500000000000000000000000001446635226000156505ustar00rootroot00000000000000dlt-daemon-2.18.10/src/tests/CMakeLists.txt000066400000000000000000000035731446635226000204200ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### set(TARGET_LIST ${TARGET_LIST} dlt-test-multi-process) set(TARGET_LIST ${TARGET_LIST} dlt-test-multi-process-client) set(TARGET_LIST ${TARGET_LIST} dlt-test-user) set(TARGET_LIST ${TARGET_LIST} dlt-test-client) set(TARGET_LIST ${TARGET_LIST} dlt-test-stress-user) set(TARGET_LIST ${TARGET_LIST} dlt-test-stress-client) set(TARGET_LIST ${TARGET_LIST} dlt-test-stress) set(TARGET_LIST ${TARGET_LIST} dlt-test-fork-handler) set(TARGET_LIST ${TARGET_LIST} dlt-test-init-free) set(TARGET_LIST ${TARGET_LIST} dlt-test-preregister-context) set(TARGET_LIST ${TARGET_LIST} dlt-test-filetransfer) install(FILES dlt-test-filetransfer-file dlt-test-filetransfer-image.png DESTINATION share/dlt-filetransfer) if(WITH_DLT_CXX11_EXT) set(TARGET_LIST ${TARGET_LIST} dlt-test-cpp-extension) endif() #TODO: Enable again once dlt-test-non-verbose is adapted to non-macro usage if (NOT WITH_DLT_DISABLE_MACRO) set(TARGET_LIST ${TARGET_LIST} dlt-test-non-verbose) if(WITH_DLT_CXX11_EXT) set(TARGET_LIST ${TARGET_LIST} dlt-test-cpp-extension) endif() endif() if(WITH_DLT_QNX_SYSTEM) set(TARGET_LIST ${TARGET_LIST} dlt-test-qnx-slogger) endif() foreach(TARGET IN LISTS TARGET_LIST) set(TARGET_SRCS ${TARGET}) add_executable(${TARGET} ${TARGET_SRCS}) target_link_libraries(${TARGET} dlt) set_target_properties(${TARGET} PROPERTIES LINKER_LANGUAGE C) install(TARGETS ${TARGET} RUNTIME DESTINATION bin COMPONENT base) endforeach() dlt-daemon-2.18.10/src/tests/dlt-test-change-ll-through-env.sh000077500000000000000000000031161446635226000240440ustar00rootroot00000000000000#!/bin/bash # check if dlt-daemon is running daemon_running=`/usr/bin/ps -C dlt-daemon | wc -l` daemon_pid=0 if [ "$daemon_running" -lt "2" ]; then echo "No daemon running, starting one myself" /usr/bin/dlt-daemon > /tmp/dlt_daemon_dlt_receiver_test.txt & daemon_pid=$! echo "daemon pid: " ${daemon_pid} else echo "dlt-daemon already running" fi # create a directory in /tmp where all logs will be stored output_dir=`mktemp -d /tmp/DLT_TESTING_XXXXXX` echo "Using directory " ${output_dir} # start dlt-receive (in background) and store PID echo "Starting dlt-receive" /usr/bin/dlt-receive -o ${output_dir}/dlt_test.dlt localhost & dlt_receive_pid=$! disown # start dlt-example-user to create some logs # sleep time: 100ms # number of messages: 10 /usr/bin/dlt-example-user -d 100 -n 10 TEST_MESSAGE_ONE # stop dlt-receive kill ${dlt_receive_pid} # show content of /tmp echo "log-file after first run" ls -l ${output_dir} # start dlt-receive (in background) and store PID echo "Starting dlt-receive" /usr/bin/dlt-receive -o ${output_dir}/dlt_test_no_log.dlt localhost & dlt_receive_pid=$! disown # start dlt-example-user to create some logs, disable logging through environment variable DLT_INITIAL_LOG_LEVEL=::-1 /usr/bin/dlt-example-user -d 100 -n 10 TEST_MESSAGE_TWO # show content of /tmp, log should not contain log messages from dlt-example-user (TEST_MESSAGE_TWO) kill ${dlt_receive_pid} echo "log-file after second run" ls -l ${output_dir} # directory will not be cleaned up echo "Used directory " ${output_dir} if [ "${daemon_pid}" -ne "0" ]; then sleep 1 kill ${daemon_pid} fi dlt-daemon-2.18.10/src/tests/dlt-test-client.c000066400000000000000000003225241446635226000210400ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-client.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-client.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include /* for isprint() */ #include /* for atoi() */ #include /* for strcmp() */ #include /* for writev() */ #include #include #include #include "dlt_client.h" #include "dlt_protocol.h" #include "dlt_user.h" #define DLT_TESTCLIENT_TEXTBUFSIZE 10024 /* Size of buffer for text output */ #define DLT_TESTCLIENT_ECU_ID "ECU1" #define DLT_TESTCLIENT_NUM_TESTS 9 static int g_testsFailed = 0; DltClient g_dltclient; /* Function prototypes */ int dlt_testclient_message_callback(DltMessage *message, void *data); bool dlt_testclient_fetch_next_message_callback(void *data); typedef struct { int aflag; int sflag; int xflag; int mflag; int vflag; int yflag; char *ovalue; char *fvalue; char *tvalue; char *evalue; int bvalue; int sendSerialHeaderFlag; int resyncSerialHeaderFlag; char ecuid[4]; int ohandle; DltFile file; DltFilter filter; int running_test; int test_counter_macro[DLT_TESTCLIENT_NUM_TESTS]; int test_counter_function[DLT_TESTCLIENT_NUM_TESTS]; int tests_passed; int tests_failed; int sock; int max_messages; } DltTestclientData; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-client [options] hostname/serial_device_name\n"); printf("Test against received data from dlt-test-user.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -a Print DLT messages; payload as ASCII\n"); printf(" -x Print DLT messages; payload as hex\n"); printf(" -m Print DLT messages; payload as hex and ASCII\n"); printf(" -s Print DLT messages; only headers\n"); printf(" -v Verbose mode\n"); printf(" -h Usage\n"); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -y Serial device mode\n"); printf(" -b baudrate Serial device baudrate (Default: 115200)\n"); printf(" -e ecuid Set ECU ID (Default: ECU1)\n"); printf(" -o filename Output messages in new DLT file\n"); printf(" -f filename Enable filtering of messages\n"); printf(" -z max msgs Print z DLT messages\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { DltTestclientData dltdata; int c, i; int index; /* Initialize dltdata */ dltdata.aflag = 0; dltdata.sflag = 0; dltdata.xflag = 0; dltdata.mflag = 0; dltdata.vflag = 0; dltdata.yflag = 0; dltdata.ovalue = 0; dltdata.fvalue = 0; dltdata.evalue = 0; dltdata.bvalue = 0; dltdata.sendSerialHeaderFlag = 0; dltdata.resyncSerialHeaderFlag = 0; dltdata.ohandle = -1; dltdata.running_test = 0; dltdata.max_messages = INT_MIN; for (i = 0; i < DLT_TESTCLIENT_NUM_TESTS; i++) { dltdata.test_counter_macro[i] = 0; dltdata.test_counter_function[i] = 0; } dltdata.tests_passed = 0; dltdata.tests_failed = 0; dltdata.sock = -1; /* Fetch command line arguments */ opterr = 0; while ((c = getopt (argc, argv, "vashSRyxmf:o:e:b:z:")) != -1) switch (c) { case 'v': { dltdata.vflag = 1; break; } case 'a': { dltdata.aflag = 1; break; } case 's': { dltdata.sflag = 1; break; } case 'x': { dltdata.xflag = 1; break; } case 'm': { dltdata.mflag = 1; break; } case 'h': { usage(); return -1; } case 'S': { dltdata.sendSerialHeaderFlag = 1; break; } case 'R': { dltdata.resyncSerialHeaderFlag = 1; break; } case 'y': { dltdata.yflag = 1; break; } case 'f': { dltdata.fvalue = optarg; break; } case 'o': { dltdata.ovalue = optarg; break; } case 'e': { dltdata.evalue = optarg; break; } case 'b': { dltdata.bvalue = atoi(optarg); break; } case 'z': { dltdata.max_messages = atoi(optarg); break; } case '?': { if ((optopt == 'o') || (optopt == 'f') || (optopt == 't')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1;/*for parasoft */ } } /* Initialize DLT Client */ dlt_client_init(&g_dltclient, dltdata.vflag); /* Register callback to be called when message was received */ dlt_client_register_message_callback(dlt_testclient_message_callback); /* Register callback to be called if next message needs to be fetched */ dlt_client_register_fetch_next_message_callback(dlt_testclient_fetch_next_message_callback); /* Setup DLT Client structure */ g_dltclient.mode = dltdata.yflag; if (g_dltclient.mode == 0) { for (index = optind; index < argc; index++) if (dlt_client_set_server_ip(&g_dltclient, argv[index]) == -1) { fprintf(stderr, "set server ip didn't succeed\n"); return -1; } if (g_dltclient.servIP == 0) { /* no hostname selected, show usage and terminate */ fprintf(stderr, "ERROR: No hostname selected\n"); usage(); dlt_client_cleanup(&g_dltclient, dltdata.vflag); return -1; } } else { for (index = optind; index < argc; index++) if (dlt_client_set_serial_device(&g_dltclient, argv[index]) == -1) { fprintf(stderr, "set serial device didn't succeed\n"); return -1; } if (g_dltclient.serialDevice == 0) { /* no serial device name selected, show usage and terminate */ fprintf(stderr, "ERROR: No serial device name specified\n"); usage(); return -1; } dlt_client_setbaudrate(&g_dltclient, dltdata.bvalue); } /* Update the send and resync serial header flags based on command line option */ g_dltclient.send_serial_header = dltdata.sendSerialHeaderFlag; g_dltclient.resync_serial_header = dltdata.resyncSerialHeaderFlag; /* initialise structure to use DLT file */ dlt_file_init(&(dltdata.file), dltdata.vflag); /* first parse filter file if filter parameter is used */ dlt_filter_init(&(dltdata.filter), dltdata.vflag); if (dltdata.fvalue) { if (dlt_filter_load(&(dltdata.filter), dltdata.fvalue, dltdata.vflag) < DLT_RETURN_OK) { dlt_file_free(&(dltdata.file), dltdata.vflag); return -1; } dlt_file_set_filter(&(dltdata.file), &(dltdata.filter), dltdata.vflag); } /* open DLT output file */ if (dltdata.ovalue) { dltdata.ohandle = open(dltdata.ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (dltdata.ohandle == -1) { dlt_file_free(&(dltdata.file), dltdata.vflag); fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", dltdata.ovalue); return -1; } } if (dltdata.evalue) dlt_set_id(dltdata.ecuid, dltdata.evalue); else dlt_set_id(dltdata.ecuid, DLT_TESTCLIENT_ECU_ID); /* Connect to TCP socket or open serial device */ if (dlt_client_connect(&g_dltclient, dltdata.vflag) != DLT_RETURN_ERROR) { dltdata.sock = g_dltclient.sock; /* Dlt Client Main Loop */ dlt_client_main_loop(&g_dltclient, &dltdata, dltdata.vflag); /* Dlt Client Cleanup */ dlt_client_cleanup(&g_dltclient, dltdata.vflag); } /* dlt-receive cleanup */ if (dltdata.ovalue) close(dltdata.ohandle); dlt_file_free(&(dltdata.file), dltdata.vflag); dlt_filter_free(&(dltdata.filter), dltdata.vflag); return g_testsFailed == 0 ? 0 : 1; } bool dlt_testclient_fetch_next_message_callback(void *data) { if (data == 0) return true; DltTestclientData *dltdata = (DltTestclientData *)data; if (dltdata->max_messages > INT_MIN) { dltdata->max_messages--; if (dltdata->max_messages <= 0) return false; } return true; } int dlt_testclient_message_callback(DltMessage *message, void *data) { static char text[DLT_TESTCLIENT_TEXTBUFSIZE]; int mtin; DltTestclientData *dltdata; uint32_t type_info, type_info_tmp; int16_t length, length_tmp; /* the macro can set this variable to -1 */ uint32_t length_tmp32 = 0; uint8_t *ptr; int32_t datalength; uint32_t id, id_tmp; int slen; int tc_old; struct iovec iov[2]; int bytes_written; if ((message == 0) || (data == 0)) return -1; dltdata = (DltTestclientData *)data; /* prepare storage header */ if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) dlt_set_storageheader(message->storageheader, message->headerextra.ecu); else dlt_set_storageheader(message->storageheader, dltdata->ecuid); if ((dltdata->fvalue == 0) || (dltdata->fvalue && (dlt_message_filter_check(message, &(dltdata->filter), dltdata->vflag) == DLT_RETURN_TRUE))) { dlt_message_header(message, text, sizeof(text), dltdata->vflag); if (dltdata->aflag) printf("%s ", text); dlt_message_payload(message, text, sizeof(text), DLT_OUTPUT_ASCII, dltdata->vflag); if (dltdata->aflag) printf("[%s]\n", text); if (strcmp(text, "Tests starting") == 0) printf("Tests starting\n"); /* check test 1m */ if (strcmp(text, "Test1: (Macro IF) Test all log levels") == 0) { printf("Test1m: (Macro IF) Test all log levels\n"); dltdata->running_test = 1; dltdata->test_counter_macro[0] = 0; } else if (strcmp(text, "Test1: (Macro IF) finished") == 0) { /* >=4, as "info" is default log level */ if (dltdata->test_counter_macro[0] >= 4) { printf("Test1m PASSED\n"); dltdata->tests_passed++; } else { printf("Test1m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 1) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_LOG_FATAL) dltdata->test_counter_macro[0]++; if (mtin == DLT_LOG_ERROR) dltdata->test_counter_macro[0]++; if (mtin == DLT_LOG_WARN) dltdata->test_counter_macro[0]++; if (mtin == DLT_LOG_INFO) dltdata->test_counter_macro[0]++; if (mtin == DLT_LOG_DEBUG) dltdata->test_counter_macro[0]++; if (mtin == DLT_LOG_VERBOSE) dltdata->test_counter_macro[0]++; } } } /* check test 2m */ if (strcmp(text, "Test2: (Macro IF) Test all variable types (verbose)") == 0) { printf("Test2m: (Macro IF) Test all variable types (verbose)\n"); dltdata->running_test = 2; dltdata->test_counter_macro[1] = 0; } else if (strcmp(text, "Test2: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[1] == 16) { printf("Test2m PASSED\n"); dltdata->tests_passed++; } else { printf("Test2m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 2) { /* Verbose */ if (!(DLT_MSG_IS_NONVERBOSE(message))) { type_info = 0; type_info_tmp = 0; length = 0; /* the macro can set this variable to -1 */ length_tmp = 0; ptr = message->databuffer; datalength = (int32_t) message->datasize; /* Log message */ if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { if (message->extendedheader->noar >= 2) { /* get type of first argument: must be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { /* skip string */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: must be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if ((type_info & DLT_TYPE_INFO_STRG) && ((type_info & DLT_TYPE_INFO_SCOD) == DLT_SCOD_ASCII)) { if (datalength == (sizeof(uint16_t) + strlen("Hello world") + 1)) dltdata->test_counter_macro[1]++; } else if ((type_info & DLT_TYPE_INFO_STRG) && ((type_info & DLT_TYPE_INFO_SCOD) == DLT_SCOD_UTF8)) { if (datalength == (sizeof(uint16_t) + strlen("Hello world") + 1)) dltdata->test_counter_macro[1]++; } else if (type_info & DLT_TYPE_INFO_BOOL) { if (datalength == sizeof(uint8_t)) dltdata->test_counter_macro[1]++; } else if (type_info & DLT_TYPE_INFO_SINT) { switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { if (datalength == sizeof(int8_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_16BIT: { if (datalength == sizeof(int16_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_32BIT: { if (datalength == sizeof(int32_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_64BIT: { if (datalength == sizeof(int64_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_128BIT: { /* Not tested here */ break; } } } else if (type_info & DLT_TYPE_INFO_UINT) { switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { if (datalength == sizeof(uint8_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_16BIT: { if (datalength == sizeof(uint16_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_32BIT: { if (datalength == sizeof(uint32_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_64BIT: { if (datalength == sizeof(uint64_t)) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_128BIT: { /* Not tested here */ break; } } } else if (type_info & DLT_TYPE_INFO_FLOA) { switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { /* Not tested here */ break; } case DLT_TYLE_16BIT: { /* Not tested here */ break; } case DLT_TYLE_32BIT: { if (datalength == (2 * sizeof(float) + sizeof(uint32_t))) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_64BIT: { if (datalength == (2 * sizeof(double) + sizeof(uint32_t))) dltdata->test_counter_macro[1]++; break; } case DLT_TYLE_128BIT: /* Not tested here */ break; } } else if (type_info & DLT_TYPE_INFO_RAWD) { /* Get length */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length == datalength) && (10 == length)) dltdata->test_counter_macro[1]++; } } } } } } } /* check test 3m */ if (strcmp(text, "Test3: (Macro IF) Test all variable types (non-verbose)") == 0) { printf("Test3m: (Macro IF) Test all variable types (non-verbose)\n"); dltdata->running_test = 3; dltdata->test_counter_macro[2] = 0; } else if (strcmp(text, "Test3: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[2] == 16) { printf("Test3m PASSED\n"); dltdata->tests_passed++; } else { printf("Test3m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 3) { /* Nonverbose */ if (DLT_MSG_IS_NONVERBOSE(message)) { id = 0; id_tmp = 0; ptr = message->databuffer; datalength = (int32_t) message->datasize; slen = -1; tc_old = dltdata->test_counter_macro[2]; /* Get message id */ DLT_MSG_READ_VALUE(id_tmp, ptr, datalength, uint32_t); id = DLT_ENDIAN_GET_32(message->standardheader->htyp, id_tmp); /* Length of string */ datalength -= (int32_t) sizeof(uint16_t); ptr += sizeof(uint16_t); switch (id) { case 1: { slen = strlen("string") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint16_t) + strlen("Hello world") + 1) dltdata->test_counter_macro[2]++; break; } case 2: { slen = strlen("utf8") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint16_t) + strlen("Hello world") + 1) dltdata->test_counter_macro[2]++; break; } case 3: { slen = strlen("bool") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint8_t)) dltdata->test_counter_macro[2]++; break; } case 4: { slen = strlen("int") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int)) dltdata->test_counter_macro[2]++; break; } case 5: { slen = strlen("int8") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int8_t)) dltdata->test_counter_macro[2]++; break; } case 6: { slen = strlen("int16") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int16_t)) dltdata->test_counter_macro[2]++; break; } case 7: { slen = strlen("int32") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int32_t)) dltdata->test_counter_macro[2]++; break; } case 8: { slen = strlen("int64") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int64_t)) dltdata->test_counter_macro[2]++; break; } case 9: { slen = strlen("uint") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(unsigned int)) dltdata->test_counter_macro[2]++; break; } case 10: { slen = strlen("uint8") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint8_t)) dltdata->test_counter_macro[2]++; break; } case 11: { slen = strlen("uint16") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint16_t)) dltdata->test_counter_macro[2]++; break; } case 12: { slen = strlen("uint32") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint32_t)) dltdata->test_counter_macro[2]++; break; } case 13: { slen = strlen("uint64") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint64_t)) dltdata->test_counter_macro[2]++; break; } case 14: { slen = strlen("float32") + 1; datalength -= slen; ptr += slen; /* 2*, as the min and the max is transfered */ if (datalength == 2 * sizeof(float)) dltdata->test_counter_macro[2]++; break; } case 15: { slen = strlen("float64") + 1; datalength -= slen; ptr += slen; /* 2*, as the min and the max is transfered */ if (datalength == 2 * sizeof(double)) dltdata->test_counter_macro[2]++; break; } case 16: { slen = strlen("raw") + 1; datalength -= slen; ptr += slen; datalength -= (int32_t) sizeof(uint16_t); ptr += sizeof(uint16_t); if (datalength == 10) dltdata->test_counter_macro[2]++; break; } } if ((slen >= 0) && (tc_old == dltdata->test_counter_macro[2])) printf("ID=%d, Datalength=%d => Failed!", id, datalength); } } /* check test 4m */ if (strcmp(text, "Test4: (Macro IF) Test different message sizes") == 0) { printf("Test4m: (Macro IF) Test different message sizes\n"); dltdata->running_test = 4; dltdata->test_counter_macro[3] = 0; } else if (strcmp(text, "Test4: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[3] == 4) { printf("Test4m PASSED\n"); dltdata->tests_passed++; } else { printf("Test4m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 4) { /* Extended header */ if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { /* Log message */ if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { /* Verbose */ if (DLT_IS_MSIN_VERB(message->extendedheader->msin)) { /* 2 arguments */ if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0; length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* first read the type info of the first argument: must be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { /* skip string */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: must be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* get length of raw data block */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length >= 0) && (length == datalength)) /*printf("Raw data found in payload, length="); */ /*printf("%d, datalength=%d \n", length, datalength); */ dltdata->test_counter_macro[3]++; } } } } } } } } /* check test 5m */ if (strcmp(text, "Test5: (Macro IF) Test high-level API") == 0) { printf("Test5m: (Macro IF) Test high-level API\n"); dltdata->running_test = 5; dltdata->test_counter_macro[4] = 0; } else if (strcmp(text, "Test5: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[4] == 12) { printf("Test5m PASSED\n"); dltdata->tests_passed++; } else { printf("Test5m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 5) { if (strcmp(text, "Next line: DLT_LOG_INT") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "-42") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "Next line: DLT_LOG_UINT") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "42") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "Next line: DLT_LOG_STRING") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "String output") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "Next line: DLT_LOG_RAW") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "00\'01\'02\'03\'04\'05\'06\'07\'08\'09\'0a\'0b\'0c\'0d\'0e\'0f") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "Next line: DLT_LOG_STRING_INT") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "String output: -42") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "Next line: DLT_LOG_STRING_UINT") == 0) dltdata->test_counter_macro[4]++; if (strcmp(text, "String output: 42") == 0) dltdata->test_counter_macro[4]++; } /* check test 6m */ if (strcmp(text, "Test 6: (Macro IF) Test local printing") == 0) { printf("Test6m: (Macro IF) Test local printing\n"); dltdata->running_test = 6; dltdata->test_counter_macro[5] = 0; } else if (strcmp(text, "Test6: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[5] == 2) { printf("Test6m PASSED\n"); dltdata->tests_passed++; } else { printf("Test6m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 6) { if (strcmp(text, "Message (visible: locally printed)") == 0) { printf("Message (visible: locally printed)\n"); dltdata->test_counter_macro[5]++; } if (strcmp(text, "Message (invisible: not locally printed)") == 0) { printf("Message (invisible: not locally printed)\n"); dltdata->test_counter_macro[5]++; } } /* check test 7m */ if (strcmp(text, "Test 7: (Macro IF) Test network trace") == 0) { printf("Test7m: (Macro IF) Test network trace\n"); dltdata->running_test = 7; dltdata->test_counter_macro[6] = 0; } else if (strcmp(text, "Test7: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[6] == 8) { printf("Test7m PASSED\n"); dltdata->tests_passed++; } else { printf("Test7m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 7) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_NW_TRACE) { /* Check message type information*/ /* Each correct message type increases the counter by 1 */ mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_NW_TRACE_IPC) dltdata->test_counter_macro[6]++; if (mtin == DLT_NW_TRACE_CAN) dltdata->test_counter_macro[6]++; if (mtin == DLT_NW_TRACE_FLEXRAY) dltdata->test_counter_macro[6]++; if (mtin == DLT_NW_TRACE_MOST) dltdata->test_counter_macro[6]++; /* Check payload, must be two arguments (2 raw data blocks) */ /* If the payload is correct, the counter is increased by 1 */ if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* first read the type info of the first argument: must be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* skip string */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: must be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* get length of raw data block */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length >= 0) && (length == datalength)) /*printf("Raw data found in payload, length="); */ /*printf("%d, datalength=%d \n", length, datalength); */ dltdata->test_counter_macro[6]++; } } } } } } } /* check test 8m */ if (strcmp(text, "Test 8: (Macro IF) Test truncated network trace") == 0) { printf("Test8m: (Macro IF) Test truncated network trace\n"); dltdata->running_test = 8; dltdata->test_counter_macro[7] = 0; } else if (strcmp(text, "Test8: (Macro IF) finished") == 0) { if (dltdata->test_counter_macro[7] == 20) { printf("Test8m PASSED\n"); dltdata->tests_passed++; } else { printf("Test8m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 8) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_NW_TRACE) { /* Check message type information*/ /* Each correct message type increases the counter by 1 */ mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_NW_TRACE_IPC) dltdata->test_counter_macro[7]++; if (mtin == DLT_NW_TRACE_CAN) dltdata->test_counter_macro[7]++; if (mtin == DLT_NW_TRACE_FLEXRAY) dltdata->test_counter_macro[7]++; if (mtin == DLT_NW_TRACE_MOST) dltdata->test_counter_macro[7]++; /* Check payload, must be two arguments (2 raw data blocks) */ /* If the payload is correct, the counter is increased by 1 */ if (message->extendedheader->noar == 4) { type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { /* Read NWTR */ char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_TRUNCATED) == 0) dltdata->test_counter_macro[7]++; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { char hdr[2048]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(hdr, ptr, datalength, (int)sizeof(hdr), length); if ((length == 16) && (hdr[15] == 15)) dltdata->test_counter_macro[7]++; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t orig_size; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); orig_size = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (orig_size == 1024 * 5) dltdata->test_counter_macro[7]++; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Size of the truncated message after headers */ if (length == DLT_USER_BUF_MAX_SIZE - 41 - sizeof(uint16_t) - sizeof(uint32_t)) dltdata->test_counter_macro[7]++; } } } } } } } } /* check test 9m */ if (strcmp(text, "Test 9: (Macro IF) Test segmented network trace") == 0) { printf("Test9m: (Macro IF) Test segmented network trace\n"); dltdata->running_test = 9; dltdata->test_counter_macro[8] = 0; } else if (strcmp(text, "Test9: (Macro IF) finished") == 0) { /* (Interface types) * (results per packet)*/ if (dltdata->test_counter_macro[8] == 4 * 35) { printf("Test9m PASSED\n"); dltdata->tests_passed++; } else { printf("Test9m FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 9) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_NW_TRACE) { /* Check message type information*/ /* Each correct message type increases the counter by 1 */ mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_NW_TRACE_IPC) dltdata->test_counter_macro[8]++; if (mtin == DLT_NW_TRACE_CAN) dltdata->test_counter_macro[8]++; if (mtin == DLT_NW_TRACE_FLEXRAY) dltdata->test_counter_macro[8]++; if (mtin == DLT_NW_TRACE_MOST) dltdata->test_counter_macro[8]++; /* Payload for first segmented message */ if (message->extendedheader->noar == 6) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* NWST */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_START) == 0) dltdata->test_counter_macro[8]++; /* Streahandle */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t handle; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); handle = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (handle > 0) dltdata->test_counter_macro[8]++; /* Header */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Test packet header size 16 */ if (length == 16) dltdata->test_counter_macro[8]++; /* Skip data */ ptr += length; datalength -= length; /* Payload size */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t pl_sz; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); pl_sz = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); /* Test packet payload size. */ if (pl_sz == 5120) dltdata->test_counter_macro[8]++; /* Segmentcount */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint16_t scount; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); scount = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Test packet segment count 5 */ if (scount == 5) dltdata->test_counter_macro[8]++; /* Segment length */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint16_t slen; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); slen = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Default segment size 1024 */ if (slen == 1024) dltdata->test_counter_macro[8]++; } } } } } } } /* Data segment */ else if (message->extendedheader->noar == 4) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* NWCH */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_SEGMENT) == 0) dltdata->test_counter_macro[8]++; /* handle */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t handle; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); handle = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (handle > 0) dltdata->test_counter_macro[8]++; /* Sequence */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { /*uint16_t seq; */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); /*seq=DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); */ dltdata->test_counter_macro[8]++; /* Data */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Segment size by default, 1024 */ if (length == 1024) dltdata->test_counter_macro[8]++; } } } } } /* End segment */ else if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* NWEN */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_END) == 0) dltdata->test_counter_macro[8]++; /* handle */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t handle; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); handle = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (handle > 0) dltdata->test_counter_macro[8]++; } } } } } } /* check test 1f */ if (strcmp(text, "Test1: (Function IF) Test all log levels") == 0) { printf("Test1f: (Function IF) Test all log levels\n"); dltdata->running_test = 10; dltdata->test_counter_function[0] = 0; } else if (strcmp(text, "Test1: (Function IF) finished") == 0) { /* >=4, as "info" is default log level */ if (dltdata->test_counter_function[0] >= 4) { printf("Test1f PASSED\n"); dltdata->tests_passed++; } else { printf("Test1f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 10) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_LOG_FATAL) dltdata->test_counter_function[0]++; if (mtin == DLT_LOG_ERROR) dltdata->test_counter_function[0]++; if (mtin == DLT_LOG_WARN) dltdata->test_counter_function[0]++; if (mtin == DLT_LOG_INFO) dltdata->test_counter_function[0]++; if (mtin == DLT_LOG_DEBUG) dltdata->test_counter_function[0]++; if (mtin == DLT_LOG_VERBOSE) dltdata->test_counter_function[0]++; } } } /* check test 2f */ if (strcmp(text, "Test2: (Function IF) Test all variable types (verbose)") == 0) { printf("Test2f: (Function IF) Test all variable types (verbose)\n"); dltdata->running_test = 11; dltdata->test_counter_function[1] = 0; } else if (strcmp(text, "Test2: (Function IF) finished") == 0) { if (dltdata->test_counter_function[1] == 14) { printf("Test2f PASSED\n"); dltdata->tests_passed++; } else { printf("Test2f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 11) { /* Verbose */ if (!(DLT_MSG_IS_NONVERBOSE(message))) { type_info = 0; type_info_tmp = 0; length = 0; length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* Log message */ if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { if (message->extendedheader->noar >= 2) { /* get type of first argument: must be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { /* skip string */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: must be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_BOOL) { if (datalength == sizeof(uint8_t)) dltdata->test_counter_function[1]++; } else if (type_info & DLT_TYPE_INFO_SINT) { switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { if (datalength == sizeof(int8_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_16BIT: { if (datalength == sizeof(int16_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_32BIT: { if (datalength == sizeof(int32_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_64BIT: { if (datalength == sizeof(int64_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_128BIT: { /* Not tested here */ break; } } } else if (type_info & DLT_TYPE_INFO_UINT) { switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { if (datalength == sizeof(uint8_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_16BIT: { if (datalength == sizeof(uint16_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_32BIT: { if (datalength == sizeof(uint32_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_64BIT: { if (datalength == sizeof(uint64_t)) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_128BIT: { /* Not tested here */ break; } } } else if (type_info & DLT_TYPE_INFO_FLOA) { switch (type_info & DLT_TYPE_INFO_TYLE) { case DLT_TYLE_8BIT: { /* Not tested here */ break; } case DLT_TYLE_16BIT: { /* Not tested here */ break; } case DLT_TYLE_32BIT: { if (datalength == (2 * sizeof(float) + sizeof(uint32_t))) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_64BIT: { if (datalength == (2 * sizeof(double) + sizeof(uint32_t))) dltdata->test_counter_function[1]++; break; } case DLT_TYLE_128BIT: { /* Not tested here */ break; } } } else if (type_info & DLT_TYPE_INFO_RAWD) { /* Get length */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length == datalength) && (length == 10)) dltdata->test_counter_function[1]++; } } } } } } } /* check test 3f */ if (strcmp(text, "Test3: (Function IF) Test all variable types (non-verbose)") == 0) { printf("Test3f: (Function IF) Test all variable types (non-verbose)\n"); dltdata->running_test = 12; dltdata->test_counter_function[2] = 0; } else if (strcmp(text, "Test3: (Function IF) finished") == 0) { if (dltdata->test_counter_function[2] == 14) { printf("Test3f PASSED\n"); dltdata->tests_passed++; } else { printf("Test3f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 12) { /* Nonverbose */ if (DLT_MSG_IS_NONVERBOSE(message)) { id = 0; id_tmp = 0; ptr = message->databuffer; datalength = (int32_t) message->datasize; slen = -1; tc_old = dltdata->test_counter_function[2]; /* Get message id */ DLT_MSG_READ_VALUE(id_tmp, ptr, datalength, uint32_t); id = DLT_ENDIAN_GET_32(message->standardheader->htyp, id_tmp); /* Length of string */ datalength -= sizeof(uint16_t); ptr += sizeof(uint16_t); switch (id) { case 1: { slen = strlen("bool") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint8_t)) dltdata->test_counter_function[2]++; break; } case 2: { slen = strlen("int") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int)) dltdata->test_counter_function[2]++; break; } case 3: { slen = strlen("int8") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int8_t)) dltdata->test_counter_function[2]++; break; } case 4: { slen = strlen("int16") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int16_t)) dltdata->test_counter_function[2]++; break; } case 5: { slen = strlen("int32") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int32_t)) dltdata->test_counter_function[2]++; break; } case 6: { slen = strlen("int64") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(int64_t)) dltdata->test_counter_function[2]++; break; } case 7: { slen = strlen("uint") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(unsigned int)) dltdata->test_counter_function[2]++; break; } case 8: { slen = strlen("uint8") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint8_t)) dltdata->test_counter_function[2]++; break; } case 9: { slen = strlen("uint16") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint16_t)) dltdata->test_counter_function[2]++; break; } case 10: { slen = strlen("uint32") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint32_t)) dltdata->test_counter_function[2]++; break; } case 11: { slen = strlen("uint64") + 1; datalength -= slen; ptr += slen; if (datalength == sizeof(uint64_t)) dltdata->test_counter_function[2]++; break; } case 12: { slen = strlen("float32") + 1; datalength -= slen; ptr += slen; /* 2*, as the min and the max is transfered */ if (datalength == 2 * sizeof(float)) dltdata->test_counter_function[2]++; break; } case 13: { slen = strlen("float64") + 1; datalength -= slen; ptr += slen; /* 2*, as the min and the max is transfered */ if (datalength == 2 * sizeof(double)) dltdata->test_counter_function[2]++; break; } case 14: { slen = strlen("raw") + 1; datalength -= slen; ptr += slen; datalength -= sizeof(uint16_t); ptr += sizeof(uint16_t); if (datalength == 10) dltdata->test_counter_function[2]++; break; } } if ((slen >= 0) && (tc_old == dltdata->test_counter_function[2])) printf("ID=%d, Datalength=%d => Failed!", id, datalength); } } /* check test 4f */ if (strcmp(text, "Test4: (Function IF) Test different message sizes") == 0) { printf("Test4f: (Function IF) Test different message sizes\n"); dltdata->running_test = 13; dltdata->test_counter_function[3] = 0; } else if (strcmp(text, "Test4: (Function IF) finished") == 0) { if (dltdata->test_counter_function[3] == 4) { printf("Test4f PASSED\n"); dltdata->tests_passed++; } else { printf("Test4f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 13) { /* Extended header */ if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { /* Log message */ if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { /* Verbose */ if (DLT_IS_MSIN_VERB(message->extendedheader->msin)) { /* 2 arguments */ if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0; length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* first read the type info of the first argument: should be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { /* skip string */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: should be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* get length of raw data block */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length >= 0) && (length == datalength)) /*printf("Raw data found in payload, length="); */ /*printf("%d, datalength=%d \n", length, datalength); */ dltdata->test_counter_function[3]++; } } } } } } } } /* check test 5f */ if (strcmp(text, "Test5: (Function IF) Test high-level API") == 0) { printf("Test5f: (Function IF) Test high-level API\n"); dltdata->running_test = 14; dltdata->test_counter_function[4] = 0; } else if (strcmp(text, "Test5: (Function IF) finished") == 0) { if (dltdata->test_counter_function[4] == 12) { printf("Test5f PASSED\n"); dltdata->tests_passed++; } else { printf("Test5f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 14) { if (strcmp(text, "Next line: dlt_log_int()") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "-42") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "Next line: dlt_log_uint()") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "42") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "Next line: dlt_log_string()") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "String output") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "Next line: dlt_log_raw()") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "00\'01\'02\'03\'04\'05\'06\'07\'08\'09\'0a\'0b\'0c\'0d\'0e\'0f") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "Next line: dlt_log_string_int()") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "String output: -42") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "Next line: dlt_log_string_uint()") == 0) dltdata->test_counter_function[4]++; if (strcmp(text, "String output: 42") == 0) dltdata->test_counter_function[4]++; } /* check test 6f */ if (strcmp(text, "Test 6: (Function IF) Test local printing") == 0) { printf("Test6f: (Function IF) Test local printing\n"); dltdata->running_test = 15; dltdata->test_counter_function[5] = 0; } else if (strcmp(text, "Test6: (Function IF) finished") == 0) { if (dltdata->test_counter_function[5] == 2) { printf("Test6f PASSED\n"); dltdata->tests_passed++; } else { printf("Test6f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 15) { if (strcmp(text, "Message (visible: locally printed)") == 0) { printf("Message (visible: locally printed)\n"); dltdata->test_counter_function[5]++; } if (strcmp(text, "Message (invisible: not locally printed)") == 0) { printf("Message (invisible: not locally printed)\n"); dltdata->test_counter_function[5]++; } } /* check test 7f */ if (strcmp(text, "Test 7: (Function IF) Test network trace") == 0) { printf("Test7f: (Function IF) Test network trace\n"); dltdata->running_test = 16; dltdata->test_counter_function[6] = 0; } else if (strcmp(text, "Test7: (Function IF) finished") == 0) { if (dltdata->test_counter_function[6] == 8) { printf("Test7f PASSED\n"); dltdata->tests_passed++; } else { printf("Test7f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 16) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_NW_TRACE) { /* Check message type information*/ /* Each correct message type increases the counter by 1 */ mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_NW_TRACE_IPC) dltdata->test_counter_function[6]++; if (mtin == DLT_NW_TRACE_CAN) dltdata->test_counter_function[6]++; if (mtin == DLT_NW_TRACE_FLEXRAY) dltdata->test_counter_function[6]++; if (mtin == DLT_NW_TRACE_MOST) dltdata->test_counter_function[6]++; /* Check payload, must be two arguments (2 raw data blocks) */ /* If the payload is correct, the counter is increased by 1 */ if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0; length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* first read the type info of the first argument: should be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* skip string */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: should be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* get length of raw data block */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length >= 0) && (length == datalength)) /*printf("Raw data found in payload, length="); */ /*printf("%d, datalength=%d \n", length, datalength); */ dltdata->test_counter_function[6]++; } } } } } } } /* check test 8f */ if (strcmp(text, "Test 8: (Function IF) Test truncated network trace") == 0) { printf("Test8f: (Function IF) Test truncated network trace\n"); dltdata->running_test = 17; dltdata->test_counter_function[7] = 0; } else if (strcmp(text, "Test8: (Function IF) finished") == 0) { if (dltdata->test_counter_function[7] == 20) { printf("Test8f PASSED\n"); dltdata->tests_passed++; } else { printf("Test8f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 17) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_NW_TRACE) { /* Check message type information*/ /* Each correct message type increases the counter by 1 */ mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_NW_TRACE_IPC) dltdata->test_counter_function[7]++; if (mtin == DLT_NW_TRACE_CAN) dltdata->test_counter_function[7]++; if (mtin == DLT_NW_TRACE_FLEXRAY) dltdata->test_counter_function[7]++; if (mtin == DLT_NW_TRACE_MOST) dltdata->test_counter_function[7]++; /* Check payload, must be two arguments (2 raw data blocks) */ /* If the payload is correct, the counter is increased by 1 */ if (message->extendedheader->noar == 4) { type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { /* Read NWTR */ char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_TRUNCATED) == 0) dltdata->test_counter_function[7]++; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { char hdr[2048]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(hdr, ptr, datalength, (int)sizeof(hdr), length); if ((length == 16) && (hdr[15] == 15)) dltdata->test_counter_function[7]++; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t orig_size; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); orig_size = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (orig_size == 1024 * 5) dltdata->test_counter_function[7]++; DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Size of the truncated message after headers */ if (length == DLT_USER_BUF_MAX_SIZE - 41 - sizeof(uint16_t) - sizeof(uint32_t)) dltdata->test_counter_function[7]++; } } } } } } } } /* check test 9f */ if (strcmp(text, "Test 9: (Function IF) Test segmented network trace") == 0) { printf("Test9f: (Function IF) Test segmented network trace\n"); dltdata->running_test = 18; dltdata->test_counter_function[8] = 0; } else if (strcmp(text, "Test9: (Function IF) finished") == 0) { /* (Interface types) * (number of messages per complete message) */ if (dltdata->test_counter_function[8] == 4 * 35) { printf("Test9f PASSED\n"); dltdata->tests_passed++; } else { printf("Test9f FAILED\n"); dltdata->tests_failed++; } dltdata->running_test = 0; } else if (dltdata->running_test == 18) { if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_NW_TRACE) { /* Check message type information*/ /* Each correct message type increases the counter by 1 */ mtin = DLT_GET_MSIN_MTIN(message->extendedheader->msin); if (mtin == DLT_NW_TRACE_IPC) dltdata->test_counter_function[8]++; if (mtin == DLT_NW_TRACE_CAN) dltdata->test_counter_function[8]++; if (mtin == DLT_NW_TRACE_FLEXRAY) dltdata->test_counter_function[8]++; if (mtin == DLT_NW_TRACE_MOST) dltdata->test_counter_function[8]++; /* Payload for first segmented message */ if (message->extendedheader->noar == 6) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* NWST */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_START) == 0) dltdata->test_counter_function[8]++; /* Streahandle */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t handle; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); handle = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (handle > 0) dltdata->test_counter_function[8]++; /* Header */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Test packet header size 16 */ if (length == 16) dltdata->test_counter_function[8]++; /* Skip data */ ptr += length; datalength -= length; /* Payload size */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t pl_sz; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); pl_sz = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); /* Test packet payload size. */ if (pl_sz == 5120) dltdata->test_counter_function[8]++; /* Segmentcount */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint16_t scount; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); scount = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Test packet segment count 5 */ if (scount == 5) dltdata->test_counter_function[8]++; /* Segment length */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint16_t slen; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); slen = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Default segment size 1024 */ if (slen == 1024) dltdata->test_counter_function[8]++; } } } } } } } /* Data segment */ else if (message->extendedheader->noar == 4) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* NWCH */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_SEGMENT) == 0) dltdata->test_counter_function[8]++; /* handle */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t handle; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); handle = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (handle > 0) dltdata->test_counter_function[8]++; /* Sequence */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { /*uint16_t seq; */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); /*seq=DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); */ dltdata->test_counter_function[8]++; /* Data */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); /* Segment size by default, 1024 */ if (length == 1024) dltdata->test_counter_function[8]++; } } } } } /* End segment */ else if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0, length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = (int32_t) message->datasize; /* NWEN */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_STRG) { char chdr[10]; DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); DLT_MSG_READ_STRING(chdr, ptr, datalength, (int)sizeof(chdr), length); if (strcmp((char *)chdr, DLT_TRACE_NW_END) == 0) dltdata->test_counter_function[8]++; /* handle */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_UINT) { uint32_t handle; DLT_MSG_READ_VALUE(length_tmp32, ptr, datalength, uint32_t); handle = DLT_ENDIAN_GET_32(message->standardheader->htyp, length_tmp32); if (handle > 0) dltdata->test_counter_function[8]++; } } } } } } if (strcmp(text, "Tests finished") == 0) { printf("Tests finished\n"); dltdata->running_test = 1; printf("%d tests passed\n", dltdata->tests_passed); printf("%d tests failed\n", dltdata->tests_failed); if (dltdata->sock != -1) close(dltdata->sock); g_testsFailed = dltdata->tests_failed; return 0; } /* if no filter set or filter is matching display message */ if (dltdata->xflag) dlt_message_print_hex(message, text, DLT_TESTCLIENT_TEXTBUFSIZE, dltdata->vflag); else if (dltdata->mflag) dlt_message_print_mixed_plain(message, text, DLT_TESTCLIENT_TEXTBUFSIZE, dltdata->vflag); else if (dltdata->sflag) dlt_message_print_header(message, text, sizeof(text), dltdata->vflag); /* if file output enabled write message */ if (dltdata->ovalue) { iov[0].iov_base = message->headerbuffer; iov[0].iov_len = message->headersize; iov[1].iov_base = message->databuffer; iov[1].iov_len = message->datasize; bytes_written = (int) writev(dltdata->ohandle, iov, 2); if (0 > bytes_written) { printf("dlt_testclient_message_callback, error in: writev(dltdata->ohandle, iov, 2)\n"); return -1; } } } return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-cpp-extension.cpp000066400000000000000000000062741446635226000227170ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Intel Corporation * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Stefan Vacek Intel Corporation * * \copyright Copyright © 2015 Intel Corporation. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-cpp-extension.cpp */ #include "dlt_cpp_extension.hpp" #include #include #include #include "dlt_user_macros.h" struct MyStruct { int64_t uuid; int32_t interfaceId; int32_t registrationState; }; template<> inline int logToDlt(DltContextData &log, MyStruct const &value) { int result = 0; result += dlt_user_log_write_string(&log, "("); result += logToDlt(log, value.uuid); result += dlt_user_log_write_string(&log, ","); result += logToDlt(log, value.interfaceId); result += dlt_user_log_write_string(&log, ","); result += logToDlt(log, value.registrationState); result += dlt_user_log_write_string(&log, ")"); if (result != 0) result = -1; return result; } /** * Sample code to show usage of the cpp-extension * mainly the variadic templates */ int main() { if (dlt_register_app("TCPP", "Test cpp extension") < 0) { printf("Failed to register application\n"); return -1; } DltContext ctx; if (dlt_register_context_ll_ts(&ctx, "TCPP", "Test cpp extension", DLT_LOG_INFO, DLT_TRACE_STATUS_OFF) < 0) { printf("Failed to register context\n"); return -1; } dlt_enable_local_print(); dlt_verbose_mode(); DLT_LOG(ctx, DLT_LOG_WARN, DLT_STRING("a message")); /* the classic way to go */ int an_int = 42; float a_float = 22.7; DLT_LOG_FCN_CXX(ctx, DLT_LOG_WARN, "Testing DLT_LOG_CXX_FCN", an_int, a_float); DLT_LOG_CXX(ctx, DLT_LOG_WARN, 1.0, 65); /* Example for logging user-defined types */ MyStruct myData = { 1u, 2u, 3u }; DLT_LOG_CXX(ctx, DLT_LOG_WARN, "MyStruct myData", myData); char *non_const_string = (char *)malloc(17); memcpy(non_const_string, "non_const_string", 16); non_const_string[16] = 0; DLT_LOG_CXX(ctx, DLT_LOG_WARN, "char *", non_const_string); std::string aString = "std::string"; DLT_LOG_CXX(ctx, DLT_LOG_WARN, "std::string", aString); std::vector intVector; intVector.push_back(0); intVector.push_back(1); intVector.push_back(2); DLT_LOG_CXX(ctx, DLT_LOG_WARN, "vector", intVector); std::vector doubleList; doubleList.push_back(10.); doubleList.push_back(11.); doubleList.push_back(12.); DLT_LOG_CXX(ctx, DLT_LOG_WARN, "list", doubleList); std::map testMap; testMap["apple"] = 100; testMap["plum"] = 200; testMap["orange"] = 300; DLT_LOG_CXX(ctx, DLT_LOG_WARN, "map", testMap); dlt_unregister_context(&ctx); dlt_unregister_app(); return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-filetransfer-file000066400000000000000000000000211446635226000227230ustar00rootroot00000000000000!!!HelloWorld!!! dlt-daemon-2.18.10/src/tests/dlt-test-filetransfer-image.png000066400000000000000000000447211446635226000236700ustar00rootroot00000000000000PNG  IHDR`sRGBgAMA a pHYsodIjIDATx^ŝ}f/s'g$;f7h&&qHԈ**"((*l(. [6mmݧ9uݵ?zWuu PPPPP c.ȸl PPPP PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPVÚux( PPPPV`l 'Sϟ7h0000lDϟZ5g<f͓/W7W<oFw@1)/|/>ԙÌyІjROY㈹jnך޽\9isffS'>9>k^9a8```o oTNJ',|U> W32n9d^]G}b`ͼN8Z5 `+`W͡7Λm@̗'7߿e9ک¼1e}/UTWAVsY غ}[7n./>6°ʬʨ}l5+vY ```&[. hN u}u 6#}Y7B`I/p3:-i3׉u$ kiTϝ;g[ɛ̽7GY@qb@ v__9Ys~]`ב35WLܶEsT: X3(>[L֑2Y=Ƿ0:`̑R00i })kyțFO'a}Wl3;_`Mkֆ4yg7U5/iÁ0000+3Ҧ5kêOVɬ\~(Y ܻ{GִfkXm۞y\|Nc s dYϘG7iO^eiXfվWgK81Lt```ϛE] kiV8qtՎ`V10000OWیGWY;fogp2ff 000P2yisѭ[ӣSYVd5w.=`a8```:f`530Z$裏Κa-_zշ}1L |f NJrϚa-swi+cV10000Gv̙3g°[}1su2c``` \d_p߶H%S~,?C7/Vr@a``6=w|MYݰ/Z=^C41{m//`:TZ~sw1޵,&pN&L```g?^e=uTC5s_1_af 000C`b X<* kuuŻ !5 GͤY:Tê~8q'O`X100000?p|mc7C3pY_&74!1pѭ;'_4.~n~5Z=溇!D 耙2oW/_ Ͱ~vfxǛV + Θ!mC1o}z֛ef```@ |g6s0*V˷3NeX8```vkW7ڿ'O>i$ pNG1pCfW}S-?C1@Mvs#k420q6_=a-?~~u7͋N42پx߯7ǎ+>o%ߖßV_GS6Oba``` p|e:s}# ԰ WBHfSÝM? Çְ;w@B`Xit000y1 z~@`+a=t֚3/%p43 /bXO:e8`$`Lb@ ```JJêOjq,2ra}0000?{cmX%D``` ?0+r2ry;@ȃ +s``` k0֬ef̖8a2auvŁ0000Va=fÁ0000V k 2A`000cÊaŰ2{Ț ðr eX_@Ȃ +5  0I1aul ```` 0V9bXm3[@``eX_Pr daXpr Ê9g0005V kր2cfK 0bX1̪a``f0Xh9Goi.\ɡu8 ?NĀ@{?wL擾7O->*C }tPa=h2GXCՠnR<>r m`}SjKwڬ5޲\0onIS?eztkwHݧ`X17ێhBxݸSlS 0S54owa 3n7Y~ϞL'ue1Q|)7 k;4Ӣ9aŰvְCV\c ACiaX'^|"1amslHP: ^+ Gs B*kXcNqBiQ_b7( ̵{bry, ``0 ~`}x~sgcGˣ{}׹~_ k?&V kgJUFԗƕvc}vEc8; t M_JӰjWkR~aŰvְ{5"@i'4aJ/O-4vUO|#0. 6Gc u4q~1}9Ot^z5 {fsMjs' ӛ1aŰv66]a՛=S:w}r]ym)\?efUYQ2*GYJ?lumY~mʧ2fJiƃv_X5F^|2Q,K\8.o41uFODfozWeu^V6<˒S4vڹI^UaX{kkq﫫U^Xվ-u_+ū~kcV+Y#lbXC[BT55^qF/P4zSnqjj1tנbe1:QHCU>z8S&,ʫCc+M2V%mbƧ4,~ӫ>a߽ ߡ1)v=aXƆo5iUM&ڻi{ekhS NǕ^F4?scK/Tޔ2&T+-vuoK#v~])M؍4Uc=*ik*gj]2omӥmkU7WEjK*ߡccCvW#v1# +Gc u5MWؿ7G8}"+F0!v_+̒#[ WS=R44 ZYZwޓChk1Yf'8 |H6 7e&'қY-(LAWQ_3xr0kKRak?vIׄRѠ *Մ:=kp 1 FѰv5.p5I⊽RjLX[SLtLJnj̠+]γԸʰbX{6UuO<&-aXu8ky]V:c+6ΧmB?lWb~1묑[QzX#-C:(PYC+&BZtjz^1^hxN+K'W\}Ծ^^2PENiy뱪P=|W,%e_1U\Ҷ+|AmWS^;fX]sxTT틕o\G4ðbX;k|mu/h_ycLzYcPbIQ3ǡ,U K=4}ɠR/ohp}>K[I-tֵO^ekId(P{t|Cb*4钋^b黷˾6~ưCW/e11#͏/ڙ%êA6Tmh0u ġU&WGB)d\FͰY%35UѦ+I=4 QYJyS/e|WT|C}Hl)@ /KU?@W_1:Q2,B(jZjNͣQ21VB؀[Om'Vm7fCήMSu]*ʑL(MeM-GJ>M|Cu }yOa[\eM4Ne{^5ð aְ4]f{ 믭aC<>^;}zM}v Z_P?WZjz-K" 0؉ZTBZj\׵oW}nSWMޱ'UrQڮƸw_aŰ&B7jU @]:?.+M@׵ 0;PCZ&z*n4HIHyS_6Z1|B܅xJ=dׯؤm}aX?6L~ ŸXumOsmԧ!aXpr4 .y!Mu>گxX15|}eB*c/ӻ6;rTc1) ա˸tUJ{8$SqY]0E]Ey_wkbhIm[jPd˾ ^6P}P4q]3aŰvf{1]vM;Pmez/>ipamA uԀ ?Mb.ֺ0ey/61I@~_{voW}aX6*=ukpm3C ÊaҁӰG`] ]>Va kZǸnÈ1վMAƷnB g9 =eu?f8_u°bXް궀b>b bX:تKgY=Bڇtu}SUYMيe| '4i۬_L 1#q 1Mau'\؊CH @;?>|otwD} =zcƚF䬥i]Ǚ]O(]%UH2Ho_]J-UԖe?]Җ.I}@0hXCn:QKEdqXa14&t2>aXu]!hAȰ.+X!MuwA[G l%PzԝR |~K#4*vuwҍ RkbZ.)ihWepW[>c5>!kW)W颼J/+6M~ Qe:30 -҅.4BV?$.xiwy*[/bq>;0ѨVǘA չUvu7QŌcȴLL+XPcki%.cEh2Pu1cur) Ym-0׶5ݫmb'fL-m=DU?_2SqŇ~ӊauփV0 &t=]!]aP)ub>ŰbX'aUG3xyu)&&05] uMr]ZdڻҪnbB:}0 ~J,u4>}&w MS؉]n^4et5mLc4.5q*'=& /aXqk08k|Յ:'v0T~rܮðbX/_#(5eŤa,5S{Q]U u<0Զ+1R[̯[ưƟ}ujY!MѾyYTs6HI匙Ui8弿? +Gc ~KKvYiDSq轱WYcIzkZ|_`VolR?+*SݯXh`OXU//h(*GϹ;ˮtt.UvGyM ה{SqHkU$(MbZs_] 迻-mnҧH}o(+z0;-T5Xa;ECF^. =c.P!{쀠Ci(st<`'fP7͚X^ĵ:(RgX#+/oݧz׵W{|JږMm5ܫCXVzժ{P׾b}Z41_o_}x廗U JCjm؏`X14"l Kڡ (3MS(+cX14a ͒ebsi``@E-~V։aZ 1V XͰfꌺ@'I: ΀aՖ>*ð: k`8Svl-}xA܉; vkоl ˰hK )ӠpAۀ27n,~ +FUhD``S ƍ9Iǜ`X14?7¿D=66000Z ,mdوcqİ: vk`8OVW5csȃ +# vV2߰:<:-@```bX1b dÚ5̢oM̉9 @ ˰`A@Ȃ ðnpr Ê9g0005V kր2cfK 0bX1̪a``f0[-h000y0aump8````ÊaD&L```| `X1Vf000Y3au-Z4<bX1LP```f2l ```` 0úɁ0000V + @ `X1Y6-q 00d2,h000Y0auMN4<bX?1wj~7|5wf#3 .O]]ut&xdBsPsÊa-Ӫ? nR}-|S7Suq6m=if>7O0V k- }kƵjCzM+gg͉~645ns|bQmVah ̸7VXun߫}^5}yk҆&.-vNO,2`qӽ-:7nzpO kEiLlƯ=NkP8}n^(u 'C50wj/4izm U+? Q>wOba kM8]ik3֌yau vuuG+~Wطԛ!@5QK;3z+>U-B[tΧ8ĦK'*^u|>w9İacWR}JC iN4B̮tfW[}i8.YŁqQm_"1yaŰFo6Jb}Cnሙq 5_*c9_Eʹ~mbp<}(aŰbXۯ_xYtua:O c /5juVa]o (n hR_ й&iMk 7պ>.Yn/f"ƃDyQeX{&AnιRc鎓lRz^_l]jݤ޺MlRe9j[. nuy1&ϽTQ 8M[W.5Q:bL52:(/~fjU#F., V3ow_Py4Pug5^ֽSVY-a&ֵ,g/JCRiC߫cQgX1 Mϔ)_D.үL?VO6^/1v!W>9%mYW#F!]i4\?,cXQ'&S}sh̨#xƴq]^\i[jVMA:v7*cX1; xyWXa9l86:>`})uDS׵wێvmcRt-9 K_ZV3u1SnD7쪣~~96,(χ5ߔr-eZOnӏ'W;8c_jw)qk0chXը%vUiǣNiPnOzٴ >񤔱nRvm;]6MX1VĮĶ< V.Wm" I̫{?PYAGSRcP^E(6۱2}W+ &*XC)m|(zP/[ieKkTbXQu*(p?۶Ƴ}] ]:LêVb]͌Uԉˠ O΃2'|m KMMB()nXTyCLwR'Ŵv6}nlQǷbuk(]aCYf)WL:`SCxtrڅawPm:^f77]6`jb~v{;v(CuQզ2064h{GJA1c3׿jF,6cSӾ:ƥO~|01&#fb׾wn{X]i~{uaTP:o}ȿJZ}$o(*xOX|ei{Qײ\V2?EE\=_ӗ71nm8*ljc>}O|K2.cZڗ b6cJb͗،]J;TPw׽@mGeQe(ԟ-kLG5&}s(ىjwmX{0#fXP:%&v̮jtj>\/wLF BvuNmz_.BWDyk&j7ՉF/: q`ޮAWHiCUDW'RRk\ӉDB'*O}2g?Mnh7qjWzlDk]`X1ŀ1PǪ.| @l.مj (:,Hk .~Ҹ#~tMmhݴMzfIWqKy k|7~M9뜈P:mM6N lIS~)fKV k1ez F+PS u|Se:*ðvD|X0R7fSS[MbS?aK_ w%v.sHdka -ФU{.m5VakWXGʿK k:LӬ:u6*+]ߣ廧NH)3&=V.nqFER.- UL׶OXئ57vШ|٧%-4l9Դ ?Wg}&Xt>\Q2辴j7Sm7֩-/ݥeðbX52ѥ> ]״5^#*g،6] æFiI`lh2&]VR J64,GF`z[YJe5Ys)VODZobIY NuB``uiyr0kl#64 VKI+J#uO1kR_Zո}k{i+Ů71u>fN|uQ6P WR%⹋xh&TGzVefg /JUcD>t}ZyJ/6vckcX1EEo3Pe2h 6U]i +m 1waTKMs5imctvKy]w>dei\(N|˔b&Lky{BEuiQ]Ӳ|=:a :m v.uݰVښ k*ޱZk#Զ/ qSLg6ՕS5~֐aaUeBIvזð vK3W_jRts)iWXmY]if]?(6-n5 ZQкm]toV|V=t^-.({v調U,ljsxXxrMb-/*X+ghLQ.ks])%*5]^ːV kѨRh ܔg:Ȑ! 6]s67>mb]gM;Lm/wȜǕ^/mhXiR[t.%@/1Hwׄʩzm]KrcY X&i4×V[Mްx"M ]~=dZ\}' Pt>4N!T___]ǩIz)ڶ~[ci=>5Va}8ft%8u>JR{XCep]hJkl9٨)釴VShqFARXVBp,ޡ?KXWӦ*v|leOk]#JGuf]1U5)e G]%f]m.Yƶ 0+`5*G^XM㻁@J#rQ?|F'gJk/'%Oe]תn9rV|$IlhB*KO^b]j٦}[ذ\b4͚_[ .74/]251Z[5fUuڤ'Bus~$"uJðaj.#צl3PihkӑNII,\[<:MaxT kJ]. y..&FMtT;H-tSd0qj&yz't45¥^1k1}0+3JGYˏ|~{Xu.EauYOlӰSLQZ֔tjL9Z-r1//ZiX}1o`?ERsH\ZGJlEu5%6_PVO۝'OM7%: & V^&lJ'kt`VU듫r\cSk1aM5AjW2.⹋@.SAPޡL_)d8^l[H tꄠ : )oG;M_KP h<Ԑ>/0MSNj>WrԵ^Xv_uE۶C[O0H^m~E<3)&QIQZho6L)Ϯkzf|0 : rFk۬ٻ>ƯeJtաO~,k4_n۱uPcWt륬mWMls[+cn˙ˮ2ht|:i]ĺMexYϲ͕Mܴ+mȥu?y"m{=i)e+~Tێ)uzMSL]/p: k,#v00eXw0000Va]f@ȃ +s``` k0֬ef̖8a2au֥vŁ0000Va} ```` 0,@d$ ```aX @ `X1s&(000Y3aŰf (3v<ݚV420{y߬1[0GꅫV퇨c1j~2eٳgOvWfXef-7ô-`Ҭ`h000e5Sf-/{Fz(C5 ;w4Ǿ6}VL; Yv;ZcoV|5 (P0=[?~Քkw=`g0092ϛv\:tZeIk+O4>3p?v\a-+}J;gdB```@ }͵V_m6Msڿ:=[{/D@ڼyM cZ10000GT[O7l`ۗݏTakh{XUm >`UCm8```ÀjЊOVWs|j[ꫬ'N(>qubv@(+ 7S4߰6m*>eofSաo Ňj~itkי{֞5Z8```:aW&7s*!/w5W!'OC;vs޲Lβr oLxzʭwr2@6{X˂{YϞ=k^bƍ͔Knag͵w/3ׯ7sSOu֙޹}@J{ 2u\2eYzuॗ^2NgXf5=Bր#G'x¬Zоucf5mh000i ?1K0;w,`j+_gSn xo9p@u[7ٴn@Hb'̷&3 -3۶m3 oꥫqg}7 Ӧ+~@Rp0{qgG̷'2.-~I ?~ط/ZVzZagUnٲ,Y֥梩{Λ̊ ```` \2Ys+̂>'DsU{X+rU>si]l{A%w?)}iVWUK\mОVզO1aŋgW[WO}(`4lĝ w\z~ū֘o.\X|^זF٬aUA˯{wÎ=ZBXa7/X`s^0N|>@ϛ_>ךo}̛7K>OWFvKWN~A/c[bElذx!KSUjԉ*cyϦ=g֚_ܲ|x^bc=Vl>گa"ߨ|g5Y~*ThjE@W-+p/V\0y+W}+,h0009o8oj+WM^i~s|yŶȵk/멳VUuR[ʗFq}%g\KӪ%n ڣ@)`d,Wm3g~\K?n}I0W6%/Z@{^ebuٳgǬY8``` s^dܹ?zREҤe*}꥗^*FuU+WL3 covҼj',{hU/kiЏ2 ```f@>C~CCC>D~D?]vnz\&UR|NiT'^ձ0e%תydDUoiO^ؒ2h000/7;?CGKOW^)kM&UO2UuD7[B/gͫ^xmҀުZdj9```_ ohTC>D~DD lz\~\IGZwڰֿZ5Z}U𵜮ي000]3Pz ҃ȏȗȟW)ԱlY ~y4U_2f5r @~ `X %B@@@(a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((a@@@@f ((((G xyIENDB`dlt-daemon-2.18.10/src/tests/dlt-test-filetransfer.c000066400000000000000000000444021446635226000222420ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-filetransfer.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-filetransfer.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include /*Needed for transferring files with the dlt protocol*/ #include /*Needed for dlt logging*/ /*!Declare some context for the main program. It's a must have to do this, when you want to log with dlt. */ DLT_DECLARE_CONTEXT(mainContext) /*!Declare some context for the file transfer. It's not a must have to do this, but later you can set a filter on this context in the dlt viewer. */ DLT_DECLARE_CONTEXT(fileContext) /*!Textfile which will be transferred. */ char *file1; /*!Image which will be transferred. */ char *file2; /*!Not existing file which will be transferred. */ char *file3_1; /*!Not existing file which will be transferred. */ char *file3_2; /*!Not existing file which will be transferred. */ char *file3_3; /*!Just some variables */ int i, countPackages, transferResult; static int g_numFailed = 0; /*!Prints the test result */ void printTestResultPositiveExpected(const char *function, int result) { if (result >= 0) { printf("%s successful\n", function); } else { printf("%s failed\n", function); g_numFailed++; } } /*!Prints the test result */ void printTestResultNegativeExpected(const char *function, int result) { if (result < 0) { printf("%s successful\n", function); } else { printf("%s failed\n", function); g_numFailed++; } } /*!Test the file transfer with the condition that the transferred file is smaller as the file transfer buffer using dlt_user_log_file_complete. */ int testFile1Run1() { /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF1P1 - dlt_user_log_file_complete"), DLT_STRING(file1)); /*Here's the line where the dlt file transfer is called. The method call needs a context, the absolute file path, will the file be deleted after transfer and the timeout between the packages */ transferResult = dlt_user_log_file_complete(&fileContext, file1, 0, 20); if (transferResult < 0) { printf("Error: dlt_user_log_file_complete\n"); return transferResult; } /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF1P1"), DLT_STRING(file1)); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } /*!Test the file transfer with the condition that the transferred file is smaller as the file transfer buffer using single package transfer */ int testFile1Run2() { int total_size, used_size; /*Get the information how many packages have the file */ countPackages = dlt_user_log_file_packagesCount(&fileContext, file1); if (countPackages < 0) { printf("Error: dlt_user_log_file_packagesCount\n"); printTestResultPositiveExpected(__FUNCTION__, countPackages); return -1; } /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF1P2 - transfer single package"), DLT_STRING(file1)); /*Logs the header of the file transfer. For more details see Mainpage.c. */ /*The header gives information about the file serial number, filename (with absolute path), filesize, packages of file, buffer size */ transferResult = dlt_user_log_file_header(&fileContext, file1); if (transferResult >= 0) { /*Loop to log all packages */ for (i = 1; i <= countPackages; i++) { dlt_user_check_buffer(&total_size, &used_size); if ((total_size - used_size) < (total_size / 2)) { printf("Error: dlt_user_log_file_data\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); break; } /*Logs one single package to the file context */ transferResult = dlt_user_log_file_data(&fileContext, file1, i, 20); if (transferResult < 0) { printf("Error: dlt_user_log_file_data\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } } /*Logs the end of the file transfer. For more details see Mainpage.c */ /*The end gives just information about the file serial number but is needed to signal that the file transfer has correctly finished and needed for the file transfer plugin of the dlt viewer. */ transferResult = dlt_user_log_file_end(&fileContext, file1, 0); if (transferResult < 0) { printf("Error: dlt_user_log_file_end\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } } else { printf("Error: dlt_user_log_file_header\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } /*Just some log to main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF1P2 - transfer single package"), DLT_STRING(file1)); printTestResultPositiveExpected(__FUNCTION__, transferResult); return 0; } /*!Test the file transfer with the condition that the transferred file is bigger as the file transfer buffer using dlt_user_log_file_complete. */ int testFile2Run1() { /*Just some log to main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF2P1 - dlt_user_log_file_complete"), DLT_STRING(file2)); /*Here's the line where the dlt file transfer is called. The method call needs a context, the absolute file path, will the file be deleted after transfer and the timeout between the packages */ transferResult = dlt_user_log_file_complete(&fileContext, file2, 0, 20); if (transferResult < 0) { printf("Error: dlt_user_log_file_complete\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } /*Just some log to main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF2P1"), DLT_STRING(file2)); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } /*!Test the file transfer with the condition that the transferred file is bigger as the file transfer buffer using single package transfer */ int testFile2Run2() { int total_size, used_size; /*Get the information how many packages have the file */ countPackages = dlt_user_log_file_packagesCount(&fileContext, file2); if (countPackages < 0) { printf("Error: dlt_user_log_file_packagesCount\n"); printTestResultPositiveExpected(__FUNCTION__, countPackages); return -1; } /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF2P2 - transfer single package"), DLT_STRING(file2)); /*Logs the header of the file transfer. For more details see Mainpage.c. */ /*The header gives information about the file serial number, filename (with absolute path), filesize, packages of file, buffer size */ transferResult = dlt_user_log_file_header(&fileContext, file2); if (transferResult >= 0) { /*Loop to log all packages */ for (i = 1; i <= countPackages; i++) { dlt_user_check_buffer(&total_size, &used_size); if ((total_size - used_size) < (total_size / 2)) { printf("Error: dlt_user_log_file_data\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); break; } /*Logs one single package to the file context */ transferResult = dlt_user_log_file_data(&fileContext, file2, i, 20); if (transferResult < 0) { printf("Error: dlt_user_log_file_data\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } } /*Logs the end of the file transfer. For more details see Mainpage.c */ /*The end gives just information about the file serial number but is needed to signal that the file transfer has correctly finished and needed for the file transfer plugin of the dlt viewer. */ transferResult = dlt_user_log_file_end(&fileContext, file2, 0); if (transferResult < 0) { printf("Error: dlt_user_log_file_end\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } } else { printf("Error: dlt_user_log_file_header\n"); printTestResultPositiveExpected(__FUNCTION__, transferResult); return transferResult; } /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF2P2"), DLT_STRING(file2)); printTestResultPositiveExpected(__FUNCTION__, transferResult); return 0; } /*!Test the file transfer with the condition that the transferred file does not exist using dlt_user_log_file_complete. */ int testFile3Run1() { /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF3P1"), DLT_STRING(file3_1)); /*Here's the line where the dlt file transfer is called. The method call needs a context, the absolute file path, will the file be deleted after transfer and the timeout between the packages */ transferResult = dlt_user_log_file_complete(&fileContext, file3_1, 0, 20); if (transferResult < 0) { /*Error expected because file doesn't exist */ /*printf("Error: dlt_user_log_file_complete\n"); */ /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF3P1"), DLT_STRING(file3_1)); printTestResultNegativeExpected(__FUNCTION__, transferResult); return transferResult; } printTestResultNegativeExpected(__FUNCTION__, transferResult); return transferResult; } /*!Test the file transfer with the condition that the transferred file does not exist using single package transfer */ int testFile3Run2() { /*Get the information how many packages have the file */ countPackages = dlt_user_log_file_packagesCount(&fileContext, file3_2); if (countPackages < 0) { /*Error expected because file doesn't exist */ /*printf("Error: dlt_user_log_file_packagesCount\n"); */ /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF3P1"), DLT_STRING(file3_2)); printTestResultNegativeExpected(__FUNCTION__, countPackages); return -1; } /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF3P1"), DLT_STRING(file3_2)); /*Logs the header of the file transfer. For more details see Mainpage.c. */ /*The header gives information about the file serial number, filename (with absolute path), filesize, packages of file, buffer size */ transferResult = dlt_user_log_file_header(&fileContext, file3_2); if (transferResult >= 0) { /*Loop to log all packages */ for (i = 1; i <= countPackages; i++) { /*Logs one single package to the file context */ transferResult = dlt_user_log_file_data(&fileContext, file3_2, i, 20); if (transferResult < 0) { printf("Error: dlt_user_log_file_data\n"); printTestResultNegativeExpected(__FUNCTION__, transferResult); return transferResult; } } /*Logs the end of the file transfer. For more details see Mainpage.c */ /*The end gives just information about the file serial number but is needed to signal that the file transfer has correctly finished and needed for the file transfer plugin of the dlt viewer. */ transferResult = dlt_user_log_file_end(&fileContext, file3_2, 0); if (transferResult < 0) { printf("Error: dlt_user_log_file_end\n"); printTestResultNegativeExpected(__FUNCTION__, transferResult); return transferResult; } } printTestResultNegativeExpected(__FUNCTION__, transferResult); return 0; } /*!Logs some information about the file. */ int testFile3Run3() { /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Started testF3P2"), DLT_STRING(file3_3)); /*Here's the line where the dlt file file info is called. The method call logs some information to dlt about the file, filesize, file serial number and number of packages */ transferResult = dlt_user_log_file_infoAbout(&fileContext, file3_3); if (transferResult < 0) { /*Error expected because file doesn't exist */ /*printf("Error: dlt_user_log_file_infoAbout\n"); */ /*Just some log to the main context */ DLT_LOG(mainContext, DLT_LOG_INFO, DLT_STRING("Finished testF3P2"), DLT_STRING(file3_3)); printTestResultNegativeExpected(__FUNCTION__, transferResult); return transferResult; } printTestResultNegativeExpected(__FUNCTION__, transferResult); return 0; } void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-filestransfer [options]\n"); printf("Test filestransfer application by transfering files.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -h display help information\n"); printf(" -t absolute path to a text file\n"); printf(" -i absolute path to an image file\n"); } /*!Main program dlt-test-filestransfer starts here */ int main(int argc, char* argv[]) { int c; /*First file contains some text */ file1 = "/usr/local/share/dlt-filetransfer/dlt-test-filetransfer-file"; /*Second file is a picture */ file2 = "/usr/local/share/dlt-filetransfer/dlt-test-filetransfer-image.png"; /*Third file doesn't exist. Just to test the reaction when the file isn't available. */ file3_1 = "dlt-test-filetransfer-doesntExist_1"; /*Third file doesn't exist. Just to test the reaction when the file isn't available. */ file3_2 = "dlt-test-filetransfer-doesntExist_2"; /*Third file doesn't exist. Just to test the reaction when the file isn't available. */ file3_3 = "dlt-test-filetransfer-doesntExist_3"; while((c = getopt(argc, argv, "ht:i:")) != -1) { switch (c) { case 't': { file1 = optarg; break; } case 'i': { file2 = optarg; break; } case 'h': { usage(); return 0; } default: { usage(); return -1; } } } /*Register the application at the dlt-daemon */ DLT_REGISTER_APP("FLTR", "Test Application filetransfer"); /*Register the context of the main program at the dlt-daemon */ DLT_REGISTER_CONTEXT(mainContext, "MAIN", "Main context for filetransfer test"); /*Register the context in which the file transfer will be logged at the dlt-daemon */ DLT_REGISTER_CONTEXT(fileContext, "FLTR", "Test Context for filetransfer"); /*More details in corresponding methods */ testFile1Run1(); testFile1Run2(); testFile2Run1(); testFile2Run2(); testFile3Run1(); testFile3Run2(); testFile3Run3(); /*Unregister the context in which the file transfer happened from the dlt-daemon */ DLT_UNREGISTER_CONTEXT(fileContext); /*Unregister the context of the main program from the dlt-daemon */ DLT_UNREGISTER_CONTEXT(mainContext); /*Unregister the app from the dlt-daemon */ DLT_UNREGISTER_APP(); return g_numFailed == 0 ? 0 : 1; } dlt-daemon-2.18.10/src/tests/dlt-test-fork-handler.c000066400000000000000000000052361446635226000221340ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Intel Corporation * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Stefan Vacek Intel Corporation * * \copyright Copyright © 2015 Intel Corporation. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-fork-handler.c */ #include /* for fork() */ #include #include #include "dlt.h" void dlt_log_message(DltContext *context, DltLogLevelType ll, char *text, int32_t num) { DltContextData contextData; if (text == NULL) return; if (dlt_user_log_write_start(context, &contextData, ll) > 0) { dlt_user_log_write_string(&contextData, text); if (num > 0) { dlt_user_log_write_int32(&contextData, num); } dlt_user_log_write_finish(&contextData); } return; } /** * @brief sample code for using at_fork-handler */ int main() { DltContext mainContext; struct timespec timeout, r; timeout.tv_sec = 0; timeout.tv_nsec = 200000000L; dlt_register_app("PRNT", "Parent application"); dlt_register_context(&mainContext, "CTXP", "Parent context"); dlt_log_message(&mainContext, DLT_LOG_WARN, "First message before fork", 0); nanosleep(&timeout, &r); pid_t pid = fork(); if (pid == 0) { /* child process */ /* this message should not be visible */ dlt_log_message(&mainContext, DLT_LOG_WARN, "Child's first message after fork, pid: ", getpid()); /* this will not register CHLD application */ dlt_register_app("CHLD", "Child application"); /* this will not register CTXC context */ dlt_register_context(&mainContext, "CTXC", "Child context"); /* this will not log a message */ dlt_log_message(&mainContext, DLT_LOG_WARN, "Child's second message after fork, pid: ", getpid()); nanosleep(&timeout, &r); if (execlp("dlt-example-user", "dlt-example-user", "-n 1", "you should see this message", NULL)) return errno; } else if (pid == -1) /* error in fork */ { return -1; } else { /* parent */ dlt_log_message(&mainContext, DLT_LOG_WARN, "Parent's first message after fork, pid: ", getpid()); nanosleep(&timeout, &r); } dlt_unregister_app(); return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-init-free.c000066400000000000000000000057761446635226000214530ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Sven Hassler * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-init-free.c */ #include #include #include #include #include "dlt_common.h" #include "dlt_user.h" void exec(const char *cmd, char *buffer, size_t length); void printMemoryUsage(); char *occupyMemory(int size); void do_example_test(); void do_dlt_test(); int num_repetitions; int main(int argc, char **argv) { if (argc > 1) num_repetitions = (int) strtol(argv[1], 0, 10); else num_repetitions = 1000; printf("Will do %d repetitions.\n", num_repetitions); /*do_example_test(); */ do_dlt_test(); printf("Done.\n"); return 0; } /* Should increase and then decrease memory amount. */ void do_example_test() { const int immediatelyFree = 0; int numBufs = 1024; int sizePerBuf = 1024 * 1024; /* 1MB */ char **bufs = (char **)malloc(numBufs * sizeof(char *)); for (int i = 0; i < numBufs; i++) { bufs[i] = occupyMemory(sizePerBuf); printf("after alloc: "); printMemoryUsage(); if (immediatelyFree) { free(bufs[i]); printf("after free: "); printMemoryUsage(); } } printf("deleting memory:\n"); if (!immediatelyFree) for (int i = 0; i < numBufs; i++) { /*for (int i = numBufs - 1; i >= 0; i--) // other way round works, too */ free(bufs[i]); printf("after free: "); printMemoryUsage(); } free(bufs); } /* Should give stable amount of memory across all iterations. */ void do_dlt_test() { for (int i = 0; i < num_repetitions; i++) { dlt_init(); dlt_free(); printf("Iteration %d) - currently used memory amount: ", i); printMemoryUsage(); } } void exec(const char *cmd, char *buffer, size_t length) { FILE *pipe = NULL; strncpy(buffer, "ERROR", length); if ((pipe = popen(cmd, "r")) == NULL) return; while (fgets(buffer, (int) length, pipe) != NULL); if (pipe != NULL) pclose(pipe); } void printMemoryUsage() { char result[128] = { 0 }; char command[128] = { 0 }; snprintf(command, sizeof(command), "pmap %d | grep total", getpid()); exec(command, result, sizeof(result)); printf("%s", result); } char *occupyMemory(int size) { char *buf = (char *)malloc(size * sizeof(char)); for (int i = 0; i < 1; i++) buf[i] = 1; return buf; } dlt-daemon-2.18.10/src/tests/dlt-test-multi-process-client.c000066400000000000000000000243631446635226000236440ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-multi-process-client.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-multi-process-client.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala ** ** ** ** PURPOSE : Receive, validate and measure data from multi process tester ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /* System includes */ #include #include #include #include #include #include #include #include /* DLT Library includes */ #include "dlt_client.h" #include "dlt_protocol.h" #include "dlt_user.h" /* PRivate includes */ #include "dlt-test-multi-process.h" /* Local data structures */ typedef struct { int max_messages; int verbose; int serial; int baudrate; char *output; int output_handle; int messages_left; int sendSerialHeaderFlag; int resyncSerialHeaderFlag; DltClient *client_ref; } s_parameters; typedef struct { int messages_received; int broken_messages_received; int bytes_received; int first_message_time; int output_bytes; } s_statistics; /* Forward declarations */ int receive(DltMessage *msg, void *data); /** * Print usage information */ void usage(char *name) { char version[255]; dlt_get_version(version, 255); printf("Usage: %s [options] \n", name); printf("Receive messages from dlt-test-multi-process.\n"); printf("%s", version); printf("Options:\n"); printf(" -m Total messages to receive. (Default: 10000)\n"); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -y Serial device mode.\n"); printf(" -b baudrate Serial device baudrate. (Default: 115200)\n"); printf(" -v Verbose. Increases the verbosity level of dlt client library.\n"); printf(" -o filename Output messages in new DLT file.\n"); } /** * Initialize reasonable default parameters. */ void init_params(s_parameters *params) { params->max_messages = 10000; params->verbose = 0; params->serial = 0; params->output = NULL; params->output_handle = -1; params->baudrate = 115200; params->sendSerialHeaderFlag = 0; params->resyncSerialHeaderFlag = 0; } /** * Read the command line parameters */ int read_params(s_parameters *params, int argc, char *argv[]) { init_params(params); int c; opterr = 0; while ((c = getopt(argc, argv, "m:yb:vo:SR")) != -1) switch (c) { case 'm': params->max_messages = atoi(optarg); break; case 'S': { params->sendSerialHeaderFlag = 1; break; } case 'R': { params->resyncSerialHeaderFlag = 1; break; } case 'y': params->serial = 1; break; case 'b': params->baudrate = atoi(optarg); break; case 'v': params->verbose = 1; break; case 'o': params->output = optarg; break; case '?': if ((optopt == 'm') || (optopt == 'b') || (optopt == 'o')) fprintf(stderr, "Option -%c requires an argument.\n", optopt); if (isprint(optopt)) fprintf(stderr, "Unknown option '-%c'.\n", optopt); else fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt); return -1; break; default: return -1; } return 0; } /** * Set the connection parameters for dlt client */ int init_dlt_connect(DltClient *client, const s_parameters *params, int argc, char *argv[]) { char id[4]; if (argc < 2) return -1; if (params->serial > 0) { client->mode = 1; if (dlt_client_set_serial_device(client, argv[argc - 1]) == -1) { fprintf(stderr, "set serial device didn't succeed\n"); return -1; } dlt_client_setbaudrate(client, params->baudrate); } else if (dlt_client_set_server_ip(client, argv[argc - 1]) == -1) { fprintf(stderr, "set serial ip didn't succeed\n"); return -1; } dlt_set_id(id, ECUID); return 0; } /** * Entry point */ int main(int argc, char *argv[]) { s_parameters params; DltClient client; params.client_ref = &client; int err = read_params(¶ms, argc, argv); if (err != 0) { usage(argv[0]); return err; } dlt_client_init(&client, params.verbose); dlt_client_register_message_callback(receive); /* Update the send and resync serial header flags based on command line option */ client.send_serial_header = params.sendSerialHeaderFlag; client.resync_serial_header = params.resyncSerialHeaderFlag; err = init_dlt_connect(&client, ¶ms, argc, argv); if (err != 0) { usage(argv[0]); return err; } err = dlt_client_connect(&client, params.verbose); if (err != DLT_RETURN_OK) { printf("Failed to connect %s.\n", client.mode > 0 ? client.serialDevice : client.servIP); return err; } if (params.output) { params.output_handle = open(params.output, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (params.output_handle == -1) { fprintf(stderr, "Failed to open %s for writing.\n", params.output); return -1; } } params.messages_left = params.max_messages; dlt_client_main_loop(&client, ¶ms, params.verbose); if (params.output_handle > 0) close(params.output_handle); return 0; } /** * Print current test statistics */ void print_stats(s_statistics stats, s_parameters params) { static int last_print_time; if ((last_print_time >= time(NULL)) && /* Only print once a second */ ((stats.messages_received + stats.broken_messages_received) % 1000 != 0) && (params.messages_left != 0)) /* Print also every 1000th message */ return; printf("\033[2J\033[1;1H"); /* Clear screen. */ printf("Statistics:\n"); printf(" Messages received : %d\n", stats.messages_received); printf(" Broken messages received : %d\n", stats.broken_messages_received); printf(" Bytes received : %d\n", stats.bytes_received); printf(" Time running (seconds) : %ld\n", time(NULL) - stats.first_message_time); printf(" Throughput (msgs/sec)/(B/sec) : %ld/%ld\n", stats.messages_received / ((time(NULL) - stats.first_message_time) + 1), (stats.bytes_received) / ((time(NULL) - stats.first_message_time) + 1)); if (params.messages_left == 0) { if (stats.broken_messages_received == 0) printf("All messages received succesfully!\n"); else printf("Test failure! There were %d broken messages.", stats.broken_messages_received); } fflush(stdout); last_print_time = (int) time(NULL); } /** * Callback for dlt client */ int receive(DltMessage *msg, void *data) { static s_statistics stats; char apid[5]; struct iovec iov[2]; s_parameters *params = (s_parameters *)data; memset(apid, 0, 5); memcpy(apid, msg->extendedheader->apid, 4); if ((apid[0] != 'M') || (apid[1] != 'T')) /* TODO: Check through the app description */ return 0; params->messages_left--; if (stats.first_message_time == 0) stats.first_message_time = time(NULL); int buflen = (int) msg->datasize + 1; char *buf = malloc((size_t) buflen); if (buf == 0) { printf("Out of memory\n"); return -1; } memset(buf, 0, (size_t) buflen); dlt_message_payload(msg, buf, buflen - 1, DLT_OUTPUT_ASCII, 0); if (strcmp(buf, PAYLOAD_DATA) == 0) stats.messages_received++; else stats.broken_messages_received++; stats.bytes_received += msg->datasize + msg->headersize - sizeof(DltStorageHeader); free(buf); print_stats(stats, *params); if (params->output_handle > 0) { iov[0].iov_base = msg->headerbuffer; iov[0].iov_len = msg->headersize; iov[1].iov_base = msg->databuffer; iov[1].iov_len = msg->datasize; stats.output_bytes += (int) writev(params->output_handle, iov, 2); } if (params->messages_left < 1) dlt_client_cleanup(params->client_ref, params->verbose); return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-multi-process.c000066400000000000000000000303161446635226000223630ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-multi-process.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-multi-process.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Lassi Marttala Lassi.LM.Marttala@partner.bmw.de ** ** ** ** PURPOSE : Stress test timing using multiple processes ** ** ** ** REMARKS : Requires POSIX fork() ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dlt.h" #include "dlt_common.h" #include "dlt-test-multi-process.h" /* Constants */ #define MAX_PROCS 100 #define MAX_THREADS 100 #define MAX_LOG_LENGTH 1024 #ifndef WAIT_ANY # define WAIT_ANY -1 #endif /* Structs */ typedef struct { int nmsgs; /* Number of messages to send */ int nprocs; /* Number of processes to start */ int nthreads; /* Number of threads to start */ int nloglength; /* Length of Log message */ int delay; /* Delay between logs messages for each process */ int delay_fudge; /* Fudge the delay by 0-n to cause desynchronization */ bool generate_ctid; /* true: To generate context Id from App Id + Thread Number */ } s_parameters; typedef struct { s_parameters params; DltContext ctx; unsigned int pidcount; unsigned int tidcount; } s_thread_data; /* Forward declarations */ void init_params(s_parameters *params); void quit_handler(int signum); void cleanup(); void do_forks(s_parameters params); void run_threads(s_parameters params); void do_logging(s_thread_data *data); int wait_for_death(); /* State information */ volatile sig_atomic_t in_handler = 0; /* Globals for cleanup from main and signal handler */ pid_t pids[MAX_PROCS]; unsigned int pidcount = 0; /** * Print instructions. */ void usage(char *prog_name) { char version[255]; dlt_get_version(version, 255); s_parameters defaults; init_params(&defaults); printf("Usage: %s [options]\n", prog_name); printf("Test application for stress testing the daemon with multiple processes and threads.\n"); printf("%s\n", version); printf("Options (Default):\n"); printf(" -m number Number of messages per thread to send. (%d)\n", defaults.nmsgs); printf(" -p number Number of processes to start. (%d), Max %d.\n", defaults.nprocs, MAX_PROCS); printf(" -t number Number of threads per process. (%d), Max %d.\n", defaults.nthreads, MAX_THREADS); printf(" -l number Length of log message. (%d)\n", defaults.nloglength); printf(" -d delay Delay in milliseconds to wait between log messages. (%d)\n", defaults.delay); printf(" -f delay Random fudge in milliseconds to add to delay. (%d)\n", defaults.delay_fudge); printf(" -g Generate Context IDs from Application ID and thread number \n"); } /** * Set nice default values for parameters */ void init_params(s_parameters *params) { params->nmsgs = 100; params->nprocs = 10; params->nthreads = 2; params->nloglength = 40; params->delay = 1000; params->delay_fudge = 100; params->generate_ctid = false; } /** * Read the command line and modify parameters */ int read_cli(s_parameters *params, int argc, char **argv) { int c; opterr = 0; while ((c = getopt (argc, argv, "m:p:t:l:d:f:g")) != -1) switch (c) { case 'm': params->nmsgs = atoi(optarg); break; case 'p': params->nprocs = atoi(optarg); if (params->nprocs > MAX_PROCS) { fprintf(stderr, "Too many processes selected.\n"); return -1; } break; case 't': params->nthreads = atoi(optarg); if (params->nthreads > MAX_THREADS) { fprintf(stderr, "Too many threads selected.\n"); return -1; } break; case 'l': params->nloglength = atoi(optarg); if(params->nloglength > MAX_LOG_LENGTH) { fprintf(stderr, "Too long log message selected.\n"); return -1; } break; case 'd': params->delay = atoi(optarg); break; case 'f': params->delay_fudge = atoi(optarg); break; case 'g': params->generate_ctid = true; break; case '?': if ((optopt == 'l') || (optopt == 'd') || (optopt == 'f')) fprintf(stderr, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option '-%c'.\n", optopt); else fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt); return -1; break; default: abort(); return -1; /*for parasoft */ } return 0; } /** * Entry point */ int main(int argc, char **argv) { /* Prepare parameters */ s_parameters params; init_params(¶ms); if (read_cli(¶ms, argc, argv) != 0) { usage(argv[0]); exit(-1); } /* Launch the child processes */ do_forks(params); /* Register signal handlers */ if (signal(SIGINT, quit_handler) == SIG_IGN) signal(SIGINT, SIG_IGN); /* C-c */ if (signal(SIGHUP, quit_handler) == SIG_IGN) signal(SIGHUP, SIG_IGN); /* Terminal closed */ if (signal(SIGTERM, quit_handler) == SIG_IGN) signal(SIGTERM, SIG_IGN); /* kill (nice) */ printf("Setup done. Listening. My pid: %d\n", getpid()); fflush(stdout); int err = wait_for_death(); cleanup(); return err; } /** * Start the child processes */ void do_forks(s_parameters params) { int i; /* Launch child processes */ for (i = 0; i < params.nprocs; i++) { pid_t pid = fork(); switch (pid) { case -1: /* An error occured */ if (errno == EAGAIN) { fprintf(stderr, "Could not allocate resources for child process.\n"); cleanup(); abort(); } if (errno == ENOMEM) { fprintf(stderr, "Could not allocate memory for child process' kernel structure.\n"); cleanup(); abort(); } break; case 0: /* Child process, start threads */ run_threads(params); break; default: /* Parent process, store the childs pid */ pids[pidcount++] = pid; break; } } } /** * Clean up the child processes. * Reraise signal to default handler. */ void quit_handler(int signum) { if (in_handler) raise(signum); in_handler = 1; cleanup(); signal(signum, SIG_DFL); raise(signum); } /** * Ask the child processes to die */ void cleanup() { unsigned int i; for (i = 0; i < pidcount; i++) kill(pids[i], SIGINT); } /** * Generate the next sleep time */ time_t mksleep_time(int delay, int fudge) { if (!fudge) return delay*1000000; else return (delay+rand()%fudge)*1000000; } /** * Open logging channel and proceed to spam messages */ void do_logging(s_thread_data *data) { DltContext mycontext; DltContextData mycontextdata; char ctid[5]; char ctid_name[256]; struct timespec ts; time_t sleep_time; int i = 0; int n = 0; char *logmsg = NULL; if(data->params.generate_ctid) snprintf(ctid, 5, "%02u%02u", data->pidcount, data->tidcount); else snprintf(ctid, 5, "CT%02u", data->tidcount); snprintf(ctid_name, 256, "Child %s in dlt-test-multi-process", ctid); dlt_register_context(&mycontext, ctid, ctid_name); int msgs_left = data->params.nmsgs; logmsg = calloc(1, (size_t) (data->params.nloglength + 1)); if (logmsg == NULL) { printf("Error allocate memory for message.\n"); dlt_unregister_context(&mycontext); abort(); } for(i = 0; i < data->params.nloglength; i++) { n = 'A' + i; if(n > 90) { n = 'A' + (n - 91) % 26; } logmsg[i] = (char) n; } while (msgs_left-- > 0) { if (dlt_user_log_write_start(&mycontext, &mycontextdata, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&mycontextdata, logmsg); dlt_user_log_write_finish(&mycontextdata); } sleep_time = mksleep_time(data->params.delay, data->params.delay_fudge); ts.tv_sec = sleep_time / 1000000000; ts.tv_nsec = sleep_time % 1000000000; nanosleep(&ts, NULL); } if (logmsg) { free(logmsg); logmsg = NULL; } dlt_unregister_context(&mycontext); } /** * Start the threads and wait for them to return. */ void run_threads(s_parameters params) { pthread_t thread[params.nthreads]; s_thread_data *thread_data = NULL; char apid[5]; char apid_name[256]; int i; srand((unsigned int) getpid()); snprintf(apid, 5, "MT%02u", pidcount); snprintf(apid_name, 256, "Apps %s.", apid); dlt_register_app(apid, apid_name); thread_data = calloc( (size_t) params.nthreads, sizeof(s_thread_data)); if (thread_data == NULL) { printf("Error allocate memory for thread data.\n"); abort(); } for (i = 0; i < params.nthreads; i++) { thread_data[i].tidcount = (unsigned int) i; thread_data[i].params = params; thread_data[i].pidcount = pidcount; if (pthread_create(&(thread[i]), NULL, (void *)&do_logging, &thread_data[i]) != 0) { printf("Error creating thread.\n"); abort(); } } for (i = 0; i < params.nthreads; i++) pthread_join(thread[i], NULL); if(thread_data) free(thread_data); dlt_unregister_app(); /* We can exit now */ exit(0); } /** * Wait for child processes to complete their work. */ int wait_for_death() { int pids_left = (int) pidcount; while (pids_left > 0) { int status; pid_t w = waitpid(WAIT_ANY, &status, 0); if (status < 0) { return -1; } else { unsigned int i; for (i = 0; i < pidcount; i++) if (pids[i] == w) { pids_left--; break; } } } return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-multi-process.h000066400000000000000000000015721446635226000223720ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Lassi Marttala * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-multi-process.h */ #ifndef DLT_TEST_MULTI_PROCESS_H_ #define DLT_TEST_MULTI_PROCESS_H_ #define DMPT_NAME "DMPT" #define PAYLOAD_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN" #define ECUID "ECU1" #endif /* DLT_TEST_MULTI_PROCESS_H_ */ dlt-daemon-2.18.10/src/tests/dlt-test-non-verbose.c000066400000000000000000000406731446635226000220210ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! *author * Onkar Palkar * *copyright Copyright © 2015 Advanced Driver Information Technology. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * *file dlt-test-non-verbose.c */ #include #include #include #include #include #include "dlt.h" /* data for real life message test */ #define DLT_COMMON_BUFFER_LENGTH 255 #define MAXSTRLEN 1024 #define DLT_MODULE_ID 0x0154 #define DLT_MSG_ID_1 0x0032 #define DLT_MSG_ID_2 0x0033 #define DLT_MSG_ID_3 0x0009 #define DLT_MSG_ID_4 0x000c #define DLT_MSG_ID_5 0x0004 #define DLT_MSG_ID_6 0x0009 #define LOG_DELAY 200 * 1000 #define NUM_LOG_MSGS 10 #define DEFAULT_WAIT_TIMEOUT 1000 DLT_DECLARE_CONTEXT(context_info) DLT_DECLARE_CONTEXT(context_log); DLT_DECLARE_CONTEXT(context_macro_test) DltContext context_function_test; DltContextData context_data; void dlt_user_log_level_changed_callback(char context_id[DLT_ID_SIZE],uint8_t log_level,uint8_t trace_status); void usage() { char version[DLT_COMMON_BUFFER_LENGTH]; dlt_get_version(version, DLT_COMMON_BUFFER_LENGTH); printf("Usage: dlt-test-non-verbose [options]\n"); printf("Test user application providing several Tests.\n"); printf("%s\n", version); printf("Options:\n"); printf(" -a run all tests \n"); printf(" -i test all types (macro interface and functional interface)\n"); printf(" -l message for log storage test\n"); printf(" -r real data\n"); printf(" -o Log level test \n"); printf(" -h this help\n"); printf("\nTests:\n"); printf(" 01: (Macro IF) Test all variable types (non-verbose)\n"); printf(" 02: (Function IF) Test all variable types (non-verbose)\n"); printf(" 03: Test Logstorage messages (non-verbose)\n"); printf(" 04: Test real life messages (non-verbose)\n"); } /******************/ /* The test cases */ /******************/ int test_logstorage() { int delay = LOG_DELAY; int i; DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test Logstorage messages")); printf("Test01: Sending log messages with level :\n"); printf(" FATAL\n"); printf(" ERROR\n"); printf(" WARN\n"); printf("Test01: Check DLT viewer\n"); printf("Test01: Log messages with FATAL," "ERROR should be seen\n"); printf("Test01: Connect USB to TARGET\n"); for(i = 1 ; i <= NUM_LOG_MSGS ; i++) { printf("Send log message %d\n", i); DLT_LOG_ID(context_log,DLT_LOG_FATAL, 1000, DLT_CSTRING("DLT Log Storage Test"), DLT_INT(i)); DLT_LOG_ID(context_log,DLT_LOG_ERROR, 1001, DLT_CSTRING("DLT Log Storage Test"), DLT_INT(i)); DLT_LOG_ID(context_log,DLT_LOG_WARN, 1002, DLT_CSTRING("DLT Log Storage Test"), DLT_INT(i)); usleep(delay); } printf("Test01: Remove USB from TARGET\n"); printf("Test01: Open log file stored in USB using DLT viewer\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test Logstorage messages finished")); return 0; } int test_loglevel(int wait_duration) { DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test log level")); sleep(wait_duration); return 0; } int test_macro_interface(void) { char buffer[10]; int num2; printf("Test02: (Macro IF) Test all variable types (non-verbose)\n"); DLT_LOG(context_info, DLT_LOG_INFO,DLT_STRING ("Test02: (Macro IF) Test all variable types (non-verbose)")); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 1, DLT_STRING("string"), DLT_STRING("Hello world")); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 2, DLT_STRING("utf8"), DLT_UTF8("Hello world")); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 3, DLT_STRING("bool"), DLT_BOOL(1)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 4, DLT_STRING("int"), DLT_INT(INT32_MIN)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 5, DLT_STRING("int8"), DLT_INT8(INT8_MIN)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 6, DLT_STRING("int16"), DLT_INT16(INT16_MIN)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 7, DLT_STRING("int32"), DLT_INT32(INT32_MIN)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 8, DLT_STRING("int64"), DLT_INT64(INT64_MIN)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 9, DLT_STRING("uint"), DLT_UINT(UINT32_MAX)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 10, DLT_STRING("uint8"), DLT_UINT8(UINT8_MAX)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 11, DLT_STRING("uint16"), DLT_UINT16(UINT16_MAX)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 12, DLT_STRING("uint32"), DLT_UINT32(UINT32_MAX)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 13, DLT_STRING("uint64"), DLT_UINT64(UINT64_MAX)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 14, DLT_STRING("float32"), DLT_FLOAT32(FLT_MIN), DLT_FLOAT32(FLT_MAX)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 15, DLT_STRING("float64"), DLT_FLOAT64(DBL_MIN), DLT_FLOAT64(DBL_MAX)); for(num2 = 0 ; num2 < 10 ; num2++) { buffer[num2] = (char) num2; } DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, 14, DLT_STRING("raw"), DLT_RAW(buffer, 10)); sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test02: (Macro IF) finished")); return 0; } int test_function_interface(void) { char buffer[10]; int num2; printf("Test03: (Function IF) Test all variable types (non-verbose)\n"); if (dlt_user_log_write_start(&context_info, &context_data,DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test03: (Function IF) Test all variable types (non-verbose)"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data,DLT_LOG_INFO, 1) > 0) { dlt_user_log_write_string(&context_data, "bool"); dlt_user_log_write_bool(&context_data, 1); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 2) > 0) { dlt_user_log_write_string(&context_data, "int"); dlt_user_log_write_int(&context_data, INT32_MIN);/* (-2147483647-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 3) > 0) { dlt_user_log_write_string(&context_data, "int8"); dlt_user_log_write_int8(&context_data, INT8_MIN); /* (-128) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO,4) > 0) { dlt_user_log_write_string(&context_data, "int16"); dlt_user_log_write_int16(&context_data, INT16_MIN);/* (-32767-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 5) > 0) { dlt_user_log_write_string(&context_data, "int32"); dlt_user_log_write_int32(&context_data, INT32_MIN);/*(-2147483647-1)*/ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 6) > 0) { dlt_user_log_write_string(&context_data, "int64"); dlt_user_log_write_int64(&context_data, INT64_MIN); /* (-__INT64_C(9223372036854775807)-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 7) > 0) { dlt_user_log_write_string(&context_data, "uint"); dlt_user_log_write_uint(&context_data, UINT32_MAX);/* (4294967295U)*/ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 8) > 0) { dlt_user_log_write_string(&context_data, "uint8"); dlt_user_log_write_uint8(&context_data, UINT8_MAX);/* (255) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 9) > 0) { dlt_user_log_write_string(&context_data, "uint16"); dlt_user_log_write_uint16(&context_data, UINT16_MAX);/* (65535) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 10) > 0) { dlt_user_log_write_string(&context_data,"uint32"); dlt_user_log_write_uint32(&context_data,UINT32_MAX);/* (4294967295U)*/ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 11) > 0) { dlt_user_log_write_string(&context_data,"uint64"); dlt_user_log_write_uint64(&context_data,UINT64_MAX); /* (__UINT64_C(18446744073709551615)) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 12) > 0) { dlt_user_log_write_string(&context_data,"float32"); dlt_user_log_write_float32(&context_data,FLT_MIN); dlt_user_log_write_float32(&context_data,FLT_MAX); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 13) > 0) { dlt_user_log_write_string(&context_data,"float64"); dlt_user_log_write_float64(&context_data,DBL_MIN); dlt_user_log_write_float64(&context_data,DBL_MAX); dlt_user_log_write_finish(&context_data); } for(num2 = 0 ; num2 < 10 ; num2++) { buffer[num2] = (char) num2; } if (dlt_user_log_write_start_id(&(context_function_test), &context_data, DLT_LOG_INFO, 14) > 0) { dlt_user_log_write_string(&context_data, "raw"); dlt_user_log_write_raw(&context_data,buffer, 10); dlt_user_log_write_finish(&context_data); } sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test03: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test_real_data(void) { printf("Test04: Real data test (non-verbose)\n"); DLT_LOG(context_info, DLT_LOG_INFO,DLT_STRING("Test04: real life mesages" " (non-verbose)")); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, DLT_MSG_ID_1, DLT_UINT16(DLT_MODULE_ID), DLT_UINT8(0x98), DLT_UINT8(0x01)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, DLT_MSG_ID_2, DLT_UINT16(DLT_MODULE_ID), DLT_UINT8(0x64), DLT_UINT8(0x0)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, DLT_MSG_ID_3, DLT_UINT16(DLT_MODULE_ID), DLT_UINT8(0x31), DLT_UINT8(0x28)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, DLT_MSG_ID_4, DLT_UINT16(DLT_MODULE_ID), DLT_UINT8(0x30)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, DLT_MSG_ID_5, DLT_UINT16(DLT_MODULE_ID), DLT_UINT8(0x31), DLT_UINT8(0x02), DLT_UINT8(0x2c), DLT_UINT8(0x0f), DLT_UINT8(0x08), DLT_UINT8(0x01), DLT_UINT8(0x11)); DLT_LOG_ID(context_macro_test, DLT_LOG_INFO, DLT_MSG_ID_6, DLT_UINT16(DLT_MODULE_ID), DLT_UINT8(0x31), DLT_UINT8(0x28)); sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING (" Test04: real life mesages (non-verbose) finished")); return 0; } void dlt_user_log_level_changed_callback(char context_id[DLT_ID_SIZE],uint8_t log_level,uint8_t trace_status) { char text[5]; text[4]=0; memcpy(text,context_id,DLT_ID_SIZE); printf("Log level changed of context %s, LogLevel=%u, TraceState=%u \n",text,log_level,trace_status); } /** * Main function of tool. */ int main(int argc, char* argv[]) { int avalue = 0; int ivalue = 0; int lvalue = 0; int rvalue = 0; int ovalue = 0; int wait_timeout = DEFAULT_WAIT_TIMEOUT; int c; if(argc < 2) { printf("\nPlease enter valid option\n\n"); usage(); return -1; } while ((c = getopt (argc, argv, "ailrho:")) != -1) { switch (c) { case 'a': { avalue = 1; break; } case 'i': { ivalue = 1; break; } case 'l': { lvalue = 1; break; } case 'r': { rvalue = 1; break; } case 'h': { usage(); return 0; } case 'o': { ovalue = 1; wait_timeout = atoi(optarg); break; } case '?': { if (isprint (optopt)) { fprintf (stderr, "\nUnknown option `-%c'.\n\n", optopt); } else { fprintf (stderr, "\nUnknown option character `\\x%x'.\n\n", optopt); } usage(); return -1; } default: { abort (); return -1; } } } DLT_REGISTER_APP("DINT", "DLT Non-Verbose Interface Test"); DLT_REGISTER_CONTEXT(context_info, "INFO","Information context"); DLT_REGISTER_CONTEXT(context_log, "LOG", "Log Context"); DLT_REGISTER_CONTEXT(context_macro_test, "MACR", "Macro Test Context"); dlt_register_context(&(context_function_test), "FUNC", "Function Test Context"); DLT_REGISTER_LOG_LEVEL_CHANGED_CALLBACK(context_log, dlt_user_log_level_changed_callback); DLT_REGISTER_LOG_LEVEL_CHANGED_CALLBACK(context_macro_test, dlt_user_log_level_changed_callback); DLT_NONVERBOSE_MODE(); printf("Tests starting\n"); DLT_LOG(context_info, DLT_LOG_INFO,DLT_STRING("Tests starting")); if(avalue) { printf("Execute all tests\n"); test_logstorage(); sleep(1); test_macro_interface(); sleep(1); test_function_interface(); sleep(1); test_real_data(); } else if(ivalue) { printf("Test all different log interface types\n"); test_macro_interface(); sleep(1); test_function_interface(); } else if(lvalue) { printf("Log storage test\n"); test_logstorage(); } else if(rvalue) { printf("Real data test\n"); test_real_data(); } else if(ovalue) { printf("Log level test\n"); test_loglevel(wait_timeout); } printf("Tests finished\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Tests finished")); DLT_UNREGISTER_CONTEXT(context_info); DLT_UNREGISTER_CONTEXT(context_log); DLT_UNREGISTER_CONTEXT(context_macro_test); dlt_unregister_context(&(context_function_test)); DLT_UNREGISTER_APP(); return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-preregister-context.c000066400000000000000000000027241446635226000235740ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Intel Corporation * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Stefan Vacek Intel Corporation * * \copyright Copyright © 2015 Intel Corporation. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-preregister-context.c */ #include /* for fork() */ #include "dlt.h" #include "dlt_user_macros.h" /** * @brief sample code for using pre-registered contexts */ int main() { DltContext mainContext; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 200000 * 1000; DLT_REGISTER_CONTEXT(mainContext, "CTXP", "main context"); DLT_LOG(mainContext, DLT_LOG_WARN, DLT_STRING("First message before app registered")); nanosleep(&ts, NULL); DLT_LOG(mainContext, DLT_LOG_WARN, DLT_STRING("Second message before app registered")); nanosleep(&ts, NULL); DLT_REGISTER_APP("PRNT", "Sample pre-register application"); DLT_LOG(mainContext, DLT_LOG_WARN, DLT_STRING("First message after app registered")); nanosleep(&ts, NULL); DLT_UNREGISTER_APP() ; return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-qnx-slogger.c000066400000000000000000000063441446635226000220270ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2021 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ #include #include #include #include #include #include "dlt.h" #include "dlt_common.h" /* for dlt_get_version() */ #define COUNT 10 #define DELAY 500 #define LENGTH 100 void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-qnx-slogger [options]\n"); printf("Generate messages and send them to slogger2\n"); printf("%s\n", version); printf("Options:\n"); printf(" -h Usage\n"); printf(" -n count Number of messages to be generated (Default: %d)\n", COUNT); printf(" -d delay Milliseconds to wait between sending messages (Default: %d)\n", DELAY); printf(" -l length Message payload length (Default: %d bytes)\n", LENGTH); } int main(int argc, char *argv[]) { int i = 0; int count = COUNT; int delay = DELAY; int length = LENGTH; char *str = NULL; struct timespec ts; int c; while ((c = getopt(argc, argv, "hn:d:l:")) != -1) { switch(c) { case 'n': { count = atoi(optarg); break; } case 'd': { delay = atoi(optarg); break; } case 'l': { length = atoi(optarg); break; } case 'h': { usage(); return -1; } case '?': { if ((optopt == 'n') || (optopt == 'd') || (optopt == 'l')) fprintf(stderr, "Option -%c requires an argument\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c`\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x`\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { usage(); return -1; } } } /* Generate string */ if (length > 0) { str = (char *) malloc((size_t) length + 1); if (str == NULL) { fprintf(stderr, "Cannot allocate memory\n"); return -1; } memset(str, 'X', (size_t) length); str[length] = '\n'; } /* Calculate delay */ if (delay > 0) { ts.tv_sec = delay / 1000; ts.tv_nsec = (delay % 1000) * 1000000; } for (i = 0; i < count; i++) { slogf(_SLOG_SETCODE(_SLOGC_TEST, 0), _SLOG_INFO, "%s", str); nanosleep(&ts, NULL); } if (str != NULL) { free(str); str = NULL; } return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-receiver-multiple-files.sh000077500000000000000000000037731446635226000245140ustar00rootroot00000000000000#!/bin/bash # check if dlt-daemon is running daemon_running=`/usr/bin/ps -C dlt-daemon | wc -l` daemon_pid=0 if [ "$daemon_running" -lt "2" ]; then echo "No daemon running, starting one myself" /usr/bin/dlt-daemon > /tmp/dlt_daemon_dlt_receiver_test.txt & daemon_pid=$! echo "daemon pid: " ${daemon_pid} else echo "dlt-daemon already running" fi # create a directory in /tmp where all logs will be stored output_dir=`mktemp -d /tmp/DLT_TESTING_XXXXXX` echo "Using directory " ${output_dir} # start dlt-receive (in background) and store PID echo "Starting dlt-receive" /usr/bin/dlt-receive -o ${output_dir}/dlt_test.dlt localhost & dlt_receive_pid=$! disown # start dlt-example-user to create some logs # sleep time: 100ms # number of messages: 10 /usr/bin/dlt-example-user -g -d 100 -n 10 TEST_MESSAGE_ONE # stop dlt-receive kill ${dlt_receive_pid} # show content of /tmp echo "log-file after first run" ls -l ${output_dir} # start dlt-receive (in background) and store PID echo "Starting dlt-receive" /usr/bin/dlt-receive -o ${output_dir}/dlt_test.dlt localhost & dlt_receive_pid=$! disown # start dlt-example-user to create some logs (use different number of messages) /usr/bin/dlt-example-user -d 100 -n 20 TEST_MESSAGE_TWO # show content of /tmp --> original file was overwritten kill ${dlt_receive_pid} echo "log-file after second run" ls -l ${output_dir} # start dlt-receive with small maximum file size (in background) and store PID echo "Starting dlt-receive" /usr/bin/dlt-receive -o ${output_dir}/dlt_test.dlt -c 3K localhost & dlt_receive_pid=$! disown # start dlt-example-user to create some logs (use even more messages then before) /usr/bin/dlt-example-user -d 20 -n 500 TEST_MESSAGE_THREE # show content of /tmp --> multiple files were created, the original file was preserved echo "log-file after third run (should show multiple files)" ls -l ${output_dir} # directory will not be cleaned up echo "Used directory " ${output_dir} if [ "${daemon_pid}" -ne "0" ]; then sleep 1 kill ${daemon_pid} fi dlt-daemon-2.18.10/src/tests/dlt-test-stress-client.c000066400000000000000000000453761446635226000223700ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-stress-client.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-stress-client.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include /* for isprint() */ #include /* for atoi() */ #include /* for strcmp() */ #include #include /* for writev() */ #include "dlt_client.h" #include "dlt_protocol.h" #include "dlt_user.h" #define DLT_TESTCLIENT_TEXTBUFSIZE 10024 /* Size of buffer for text output */ #define DLT_TESTCLIENT_ECU_ID "ECU1" #define DLT_TESTCLIENT_NUM_TESTS 7 /* Function prototypes */ int dlt_testclient_message_callback(DltMessage *message, void *data); typedef struct { int aflag; int sflag; int xflag; int mflag; int vflag; int yflag; char *ovalue; char *fvalue; char *tvalue; char *evalue; int nvalue; int bvalue; int sendSerialHeaderFlag; int resyncSerialHeaderFlag; char ecuid[4]; int ohandle; DltFile file; DltFilter filter; int running_test; int test_counter_macro[DLT_TESTCLIENT_NUM_TESTS]; int test_counter_function[DLT_TESTCLIENT_NUM_TESTS]; int tests_passed; int tests_failed; int sock; /* test values */ unsigned long bytes_received; unsigned long time_elapsed; int last_value; int count_received_messages; int count_not_received_messages; } DltTestclientData; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-stress-client [options] hostname/serial_device_name\n"); printf("Test against received data from dlt-test-stress-user.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -a Print DLT messages; payload as ASCII\n"); printf(" -x Print DLT messages; payload as hex\n"); printf(" -m Print DLT messages; payload as hex and ASCII\n"); printf(" -s Print DLT messages; only headers\n"); printf(" -v Verbose mode\n"); printf(" -h Usage\n"); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -y Serial device mode\n"); printf(" -b baudrate Serial device baudrate (Default: 115200)\n"); printf(" -e ecuid Set ECU ID (Default: ECU1)\n"); printf(" -o filename Output messages in new DLT file\n"); printf(" -f filename Enable filtering of messages\n"); printf(" -n messages Number of messages to be received per test(Default: 10000)\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { DltClient dltclient; DltTestclientData dltdata; int c, i; int index; /* Initialize dltclient */ memset(&dltclient, 0x0, sizeof(DltClient)); /* Initialize dltdata */ dltdata.aflag = 0; dltdata.sflag = 0; dltdata.xflag = 0; dltdata.mflag = 0; dltdata.vflag = 0; dltdata.yflag = 0; dltdata.ovalue = 0; dltdata.fvalue = 0; dltdata.evalue = 0; dltdata.bvalue = 0; dltdata.sendSerialHeaderFlag = 0; dltdata.resyncSerialHeaderFlag = 0; dltdata.nvalue = 10000; dltdata.ohandle = -1; dltdata.running_test = 0; for (i = 0; i < DLT_TESTCLIENT_NUM_TESTS; i++) { dltdata.test_counter_macro[i] = 0; dltdata.test_counter_function[i] = 0; } dltdata.tests_passed = 0; dltdata.tests_failed = 0; dltdata.bytes_received = 0; dltdata.time_elapsed = dlt_uptime(); dltdata.last_value = 0; dltdata.count_received_messages = 0; dltdata.count_not_received_messages = 0; dltdata.sock = -1; /* Fetch command line arguments */ opterr = 0; while ((c = getopt (argc, argv, "vashSRyxmf:o:e:b:n:")) != -1) switch (c) { case 'v': { dltdata.vflag = 1; break; } case 'a': { dltdata.aflag = 1; break; } case 's': { dltdata.sflag = 1; break; } case 'x': { dltdata.xflag = 1; break; } case 'm': { dltdata.mflag = 1; break; } case 'h': { usage(); return -1; } case 'S': { dltdata.sendSerialHeaderFlag = 1; break; } case 'R': { dltdata.resyncSerialHeaderFlag = 1; break; } case 'y': { dltdata.yflag = 1; break; } case 'f': { dltdata.fvalue = optarg; break; } case 'o': { dltdata.ovalue = optarg; break; } case 'e': { dltdata.evalue = optarg; break; } case 'b': { dltdata.bvalue = atoi(optarg); break; } case 'n': { dltdata.nvalue = atoi(optarg); break; } case '?': { if ((optopt == 'o') || (optopt == 'f') || (optopt == 't')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1;/*for parasoft */ } } /* Initialize DLT Client */ dlt_client_init(&dltclient, dltdata.vflag); /* Register callback to be called when message was received */ dlt_client_register_message_callback(dlt_testclient_message_callback); /* Setup DLT Client structure */ dltclient.mode = dltdata.yflag; if (dltclient.mode == 0) { for (index = optind; index < argc; index++) if (dlt_client_set_server_ip(&dltclient, argv[index]) == -1) { fprintf(stderr, "set server ip didn't succeed\n"); return -1; } if (dltclient.servIP == 0) { /* no hostname selected, show usage and terminate */ fprintf(stderr, "ERROR: No hostname selected\n"); usage(); dlt_client_cleanup(&dltclient, dltdata.vflag); return -1; } } else { for (index = optind; index < argc; index++) if (dlt_client_set_serial_device(&dltclient, argv[index]) == -1) { fprintf(stderr, "set serial device didn't succeed\n"); return -1; } if (dltclient.serialDevice == 0) { /* no serial device name selected, show usage and terminate */ fprintf(stderr, "ERROR: No serial device name specified\n"); usage(); return -1; } dlt_client_setbaudrate(&dltclient, dltdata.bvalue); } /* Update the send and resync serial header flags based on command line option */ dltclient.send_serial_header = dltdata.sendSerialHeaderFlag; dltclient.resync_serial_header = dltdata.resyncSerialHeaderFlag; /* initialise structure to use DLT file */ dlt_file_init(&(dltdata.file), dltdata.vflag); /* first parse filter file if filter parameter is used */ dlt_filter_init(&(dltdata.filter), dltdata.vflag); if (dltdata.fvalue) { if (dlt_filter_load(&(dltdata.filter), dltdata.fvalue, dltdata.vflag) < DLT_RETURN_OK) { dlt_file_free(&(dltdata.file), dltdata.vflag); return -1; } dlt_file_set_filter(&(dltdata.file), &(dltdata.filter), dltdata.vflag); } /* open DLT output file */ if (dltdata.ovalue) { dltdata.ohandle = open(dltdata.ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (dltdata.ohandle == -1) { dlt_file_free(&(dltdata.file), dltdata.vflag); fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", dltdata.ovalue); return -1; } } if (dltdata.evalue) dlt_set_id(dltdata.ecuid, dltdata.evalue); else dlt_set_id(dltdata.ecuid, DLT_TESTCLIENT_ECU_ID); /* Connect to TCP socket or open serial device */ if (dlt_client_connect(&dltclient, dltdata.vflag) != DLT_RETURN_ERROR) { dltdata.sock = dltclient.sock; /* Dlt Client Main Loop */ dlt_client_main_loop(&dltclient, &dltdata, dltdata.vflag); /* Dlt Client Cleanup */ dlt_client_cleanup(&dltclient, dltdata.vflag); } /* dlt-receive cleanup */ if (dltdata.ovalue) close(dltdata.ohandle); dlt_file_free(&(dltdata.file), dltdata.vflag); dlt_filter_free(&(dltdata.filter), dltdata.vflag); return 0; } int dlt_testclient_message_callback(DltMessage *message, void *data) { static char text[DLT_TESTCLIENT_TEXTBUFSIZE]; DltTestclientData *dltdata; uint32_t type_info, type_info_tmp; int16_t length, length_tmp; /* the macro can set this variable to -1 */ uint8_t *ptr; int32_t datalength; int32_t value; uint32_t value_tmp = 0; struct iovec iov[2]; int bytes_written; if ((message == 0) || (data == 0)) return -1; dltdata = (DltTestclientData *)data; /* prepare storage header */ if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) dlt_set_storageheader(message->storageheader, message->headerextra.ecu); else dlt_set_storageheader(message->storageheader, dltdata->ecuid); if ((dltdata->fvalue == 0) || (dltdata->fvalue && (dlt_message_filter_check(message, &(dltdata->filter), dltdata->vflag) == DLT_RETURN_TRUE))) { /*dlt_message_header(message,text,sizeof(text),dltdata->vflag); */ if (dltdata->aflag) { /*printf("%s ",text); */ } /*dlt_message_payload(message,text,sizeof(text),DLT_OUTPUT_ASCII,dltdata->vflag); */ if (dltdata->aflag) { /*printf("[%s]\n",text); */ } /* do something here */ /* Count number of received bytes */ dltdata->bytes_received += message->datasize + message->headersize - sizeof(DltStorageHeader); /* print number of received bytes */ if ((dlt_uptime() - dltdata->time_elapsed) > 10000) { printf("Received %lu Bytes/s\n", dltdata->bytes_received /**10000/(dlt_uptime()-dltdata->time_elapsed)*/); /*printf("Received %lu Bytes received\n",dltdata->bytes_received); */ dltdata->time_elapsed = dlt_uptime(); dltdata->bytes_received = 0; } /* Extended header */ if (DLT_IS_HTYP_UEH(message->standardheader->htyp)) { /* Log message */ if ((DLT_GET_MSIN_MSTP(message->extendedheader->msin)) == DLT_TYPE_LOG) { /* Verbose */ if (DLT_IS_MSIN_VERB(message->extendedheader->msin)) { /* 2 arguments */ if (message->extendedheader->noar == 2) { /* verbose mode */ type_info = 0; type_info_tmp = 0; length = 0; length_tmp = 0; /* the macro can set this variable to -1 */ ptr = message->databuffer; datalength = message->datasize; /* first read the type info of the first argument: must be string */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_SINT) { /* read value */ DLT_MSG_READ_VALUE(value_tmp, ptr, datalength, int32_t); value = DLT_ENDIAN_GET_32(message->standardheader->htyp, value_tmp); /*printf("%d\n",value); */ if (value < dltdata->last_value) { if (dltdata->nvalue == dltdata->count_received_messages) printf("PASSED: %d Msg received, %d not received\n", dltdata->count_received_messages, dltdata->count_not_received_messages); else printf("FAILED: %d Msg received, %d not received\n", dltdata->count_received_messages, dltdata->count_not_received_messages); dltdata->last_value = 0; dltdata->count_received_messages = 0; dltdata->count_not_received_messages = value - 1; } else { dltdata->count_not_received_messages += value - dltdata->last_value - 1; } dltdata->last_value = value; dltdata->count_received_messages++; if (length >= 0) { ptr += length; datalength -= length; /* read type of second argument: must be raw */ DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t); type_info = DLT_ENDIAN_GET_32(message->standardheader->htyp, type_info_tmp); if (type_info & DLT_TYPE_INFO_RAWD) { /* get length of raw data block */ DLT_MSG_READ_VALUE(length_tmp, ptr, datalength, uint16_t); length = DLT_ENDIAN_GET_16(message->standardheader->htyp, length_tmp); if ((length >= 0) && (length == datalength)) /*printf("Raw data found in payload, length="); */ /*printf("%d, datalength=%d \n", length, datalength); */ dltdata->test_counter_macro[3]++; } } } } } } } /* if no filter set or filter is matching display message */ if (dltdata->xflag) dlt_message_print_hex(message, text, DLT_TESTCLIENT_TEXTBUFSIZE, dltdata->vflag); else if (dltdata->mflag) dlt_message_print_mixed_plain(message, text, DLT_TESTCLIENT_TEXTBUFSIZE, dltdata->vflag); else if (dltdata->sflag) dlt_message_print_header(message, text, sizeof(text), dltdata->vflag); /* if file output enabled write message */ if (dltdata->ovalue) { iov[0].iov_base = message->headerbuffer; iov[0].iov_len = message->headersize; iov[1].iov_base = message->databuffer; iov[1].iov_len = message->datasize; bytes_written = (int) writev(dltdata->ohandle, iov, 2); if (0 > bytes_written) { printf("dlt_testclient_message_callback, error when: writev(dltdata->ohandle, iov, 2) \n"); return -1; } } } return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-stress-user.c000066400000000000000000000200741446635226000220540ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-stress-user.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-stress-user.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include /* for printf() and fprintf() */ #include #include /* for atoi(), abort() */ #include /* for memset() */ #include /* for isprint() */ #include "dlt.h" #define DLT_TEST_NUM_CONTEXT 7 /* Test functions... */ int testall(int count, int repeat, int delay, int size); /* Context declaration.. */ DltContext context_info; DltContextData context_data; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-stress-user [options]\n"); printf("Test user application providing Test messages.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -v Verbose mode\n"); printf(" -f filename Use local log file instead of sending to daemon\n"); printf(" -n count Number of messages to be sent per test (Default: 10000)\n"); printf(" -r repeat How often test is repeated (Default: 100)\n"); printf(" -d delay Delay between sent messages in uSec (Default: 1000)\n"); printf(" -s size Size of extra message data in bytes (Default: 100)\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { /*int vflag = 0; */ char *fvalue = 0; int nvalue = 10000; int rvalue = 100; int dvalue = 1000; int svalue = 100; int c; opterr = 0; while ((c = getopt (argc, argv, "vf:n:r:d:s:")) != -1) switch (c) { case 'v': { /*vflag = 1; */ break; } case 'f': { fvalue = optarg; break; } case 'n': { nvalue = atoi(optarg); break; } case 'r': { rvalue = atoi(optarg); break; } case 'd': { dvalue = atoi(optarg); break; } case 's': { svalue = atoi(optarg); break; } case '?': { if ((optopt == 'f') || (optopt == 'n') || (optopt == 'r') || (optopt == 'd') || (optopt == 's')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1;/*for parasoft */ } } if (fvalue) { /* DLT is intialised automatically, except another output target will be used */ if (dlt_init_file(fvalue) < 0) /* log to file */ return -1; } /* Register APP */ dlt_register_app("DIFT", "DLT Interface Test"); /* Register CONTEXTS... */ dlt_register_context(&context_info, "INFO", "Information context"); /* Tests starting */ printf("Tests starting\n"); /*DLT_LOG(context_info,DLT_LOG_INFO,DLT_STRING("Tests starting")); */ /* wait 3 seconds before starting */ /*sleep(3); */ testall(nvalue, rvalue, dvalue, svalue); /* Tests finished */ printf("Tests finished\n"); /*DLT_LOG(context_info,DLT_LOG_INFO,DLT_STRING("Tests finished")); */ /* wait 3 seconds before terminating application */ /*sleep(3); */ /* Unregister CONTEXTS... */ dlt_unregister_context(&context_info); /* Unregister APP */ dlt_unregister_app(); return 0; } /******************/ /* The test cases */ /******************/ int testall(int count, int repeat, int delay, int size) { char buffer[size]; int num, rnum; struct timespec ts; for (num = 0; num < size; num++) buffer[num] = (char) num; /* Test All: Test all start */ /*printf("Test1: Test all\n"); */ /*DLT_LOG(context_info,DLT_LOG_INFO,DLT_STRING("Test1: Test all")); */ for (rnum = 0; rnum < repeat; rnum++) for (num = 1; num <= count; num++) { if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_int(&context_data, num); dlt_user_log_write_raw(&context_data, buffer, size); dlt_user_log_write_finish(&context_data); } ts.tv_sec = (delay * 1000) / 1000000000; ts.tv_nsec = (delay * 1000) % 1000000000; nanosleep(&ts, NULL); } /* wait 5 seconds after test */ /*sleep(5); */ /*DLT_LOG(context_info,DLT_LOG_INFO,DLT_STRING("Test1: finished")); */ return 0; } dlt-daemon-2.18.10/src/tests/dlt-test-stress.c000066400000000000000000000253501446635226000211020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-stress.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-stress.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include #include /* for isprint() */ #include #include /* for printf() and fprintf() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include /* POSIX Threads */ #include "dlt.h" #include "dlt_common.h" /* for dlt_get_version() */ DltContext mycontext[9999]; typedef struct { int num; } thread_data_t; #define STRESS1_NUM_CONTEXTS 3000 #define STRESS2_MAX_NUM_THREADS 64 #define STRESS3_MAX_NUM_MESSAGES 512 #define MAX_TESTS 3 void stress1(void); void stress2(void); void thread_function(void); void stress3(void); /* * This environment variable is used when developer wants to interrupt program manually */ char *env_manual_interruption = 0; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-stress [options]\n"); printf("Test application executing several stress tests.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -v Verbose mode\n"); printf(" -f filename Use local log file instead of sending to daemon\n"); printf(" -1 Execute test 1 (register/unregister many contexts)\n"); printf(" In order to interrupt test manually (e.g: wait for ENTER key),\n"); printf(" set environment variable DLT_TEST_MANUAL_INTERRUPTION=1\n"); printf(" -2 Execute test 2 (multiple threads logging data)\n"); printf(" -3 Execute test 3 (logging much data)\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { /*int vflag = 0; */ char *fvalue = 0; int test[MAX_TESTS]; int i, c, help; for (i = 0; i < MAX_TESTS; i++) test[i] = 0; opterr = 0; while ((c = getopt (argc, argv, "vf:123")) != -1) switch (c) { case 'v': { /*vflag = 1; */ break; } case 'f': { fvalue = optarg; break; } case '1': { test[0] = 1; env_manual_interruption = getenv("DLT_TEST_MANUAL_INTERRUPTION"); break; } case '2': { test[1] = 1; break; } case '3': { test[2] = 1; break; } case '?': { if (optopt == 'f') fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1;/*for parasoft */ } } if (fvalue) { /* DLT is intialised automatically, except another output target will be used */ if (dlt_init_file(fvalue) < 0) /* log to file */ return -1; } help = 0; for (i = 0; i < MAX_TESTS; i++) if (test[i] == 1) { help = 1; break; } if (help == 0) { usage(); return -1; } dlt_register_app("DSTS", "DLT daemon stress tests"); if (test[0]) stress1(); if (test[1]) stress2(); if (test[2]) stress3(); dlt_unregister_app(); sleep(1); return 0; } void stress1(void) { int i, c; char ctid[5]; struct timespec ts; printf("Starting stress test1...\n"); printf("* Register %d contexts...\n", STRESS1_NUM_CONTEXTS); for (i = 0; i < STRESS1_NUM_CONTEXTS; i++) { /* Generate id */ memset(ctid, 0, 5); snprintf(ctid, 5, "%d", i); /*printf("%i: '%s' \n",i,ctid); */ dlt_register_context(&(mycontext[i]), ctid, ctid); ts.tv_sec = 0; ts.tv_nsec = 500 * 1000; nanosleep(&ts, NULL); } if (env_manual_interruption && (strcmp(env_manual_interruption, "1") == 0)) { printf("press \"Enter\" to terminate test"); while (1) { c=getchar(); /* if "Return" is pressed, exit loop; */ if (c==10) { break; } } } printf("* Unregister %d contexts...\n", STRESS1_NUM_CONTEXTS); for (i = 0; i < STRESS1_NUM_CONTEXTS; i++) { dlt_unregister_context(&(mycontext[i])); ts.tv_sec = 0; ts.tv_nsec = 500 * 1000; nanosleep(&ts, NULL); } printf("Finished stress test1 \n\n"); } void stress2(void) { int ret, index; struct timespec ts; pthread_t thread[STRESS2_MAX_NUM_THREADS]; thread_data_t thread_data[STRESS2_MAX_NUM_THREADS]; printf("Starting stress test2... \n"); srand((unsigned int) time(NULL)); printf("* Creating %d Threads, each of them registers one context,\n", STRESS2_MAX_NUM_THREADS); printf(" sending one log message, then unregisters the context\n"); for (index = 0; index < STRESS2_MAX_NUM_THREADS; index++) { thread_data[index].num = index; ret = pthread_create(&(thread[index]), NULL, (void *)&thread_function, (void *)&(thread_data[index])); if (ret != 0) printf("Error creating thread %d: %s \n", index, strerror(errno)); ts.tv_sec = 0; ts.tv_nsec = 1000 * 1000; nanosleep(&ts, NULL); } for (index = 0; index < STRESS2_MAX_NUM_THREADS; index++) pthread_join(thread[index], NULL); printf("Finished stress test2 \n\n"); } void thread_function(void) { /*thread_data_t *data; */ DltContext context_thread1; DltContextData context_thread1_data; char ctid[5]; struct timespec ts; /*data = (thread_data_t *) ptr; */ memset(ctid, 0, 5); /* Create random context id */ snprintf(ctid, 5, "%.2x", rand() & 0x0000ffff); ts.tv_sec = 0; ts.tv_nsec = rand(); nanosleep(&ts, NULL); dlt_register_context(&context_thread1, ctid, ctid); if (dlt_user_log_write_start(&context_thread1, &context_thread1_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_thread1_data, ctid); dlt_user_log_write_finish(&context_thread1_data); } dlt_unregister_context(&context_thread1); } void stress3(void) { DltContext context_stress3; DltContextData context_stress3_data; char buffer[STRESS3_MAX_NUM_MESSAGES]; int num; struct timespec ts; /* Performance test */ dlt_register_context(&context_stress3, "TST3", "Stress Test 3 - Performance"); printf("Starting stress test3... \n"); printf("* Logging raw data, up to a size of %d\n", STRESS3_MAX_NUM_MESSAGES); for (num = 0; num < STRESS3_MAX_NUM_MESSAGES; num++) { buffer[num] = (char) num; if (dlt_user_log_write_start(&context_stress3, &context_stress3_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_int(&context_stress3_data, num); dlt_user_log_write_raw(&context_stress3_data, buffer, (uint16_t) num); dlt_user_log_write_finish(&context_stress3_data); } ts.tv_sec = 0; ts.tv_nsec = 10000 * 1000; nanosleep(&ts, NULL); } printf("Finished stress test3 \n\n"); } dlt-daemon-2.18.10/src/tests/dlt-test-user.c000066400000000000000000001670101446635226000205350ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt-test-user.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-test-user.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include /* for printf() and fprintf() */ #include #include /* for atoi(), abort() */ #include /* for memset() */ #include /* for isprint() */ #include "dlt.h" #define DLT_TEST_NUM_CONTEXT 11 #define DLT_MAX_TIMESTAMP 0xFFFFFFFF /* LogLevel string representation */ static const char *loglevelstr[DLT_LOG_MAX] = { "DLT_LOG_OFF", "DLT_LOG_FATAL", "DLT_LOG_ERROR", "DLT_LOG_WARN", "DLT_LOG_INFO", "DLT_LOG_DEBUG", "DLT_LOG_VERBOSE" }; /* Test functions... */ #if !DLT_DISABLE_MACRO /* for macro interface */ int test1m(void); int test2m(void); int test3m(void); int test4m(void); int test5m(void); int test6m(void); int test7m(void); int test8m(void); int test9m(void); int test10m(void); int test11m(void); #endif /* for function interface */ int test1f(void); int test2f(void); int test3f(void); int test4f(void); int test5f(void); int test6f(void); int test7f(void); int test8f(void); int test9f(void); int test10f(void); int test11f(void); /* Declaration of callback functions */ int test_injection_macro_callback(uint32_t service_id, void *data, uint32_t length); int test_injection_function_callback(uint32_t service_id, void *data, uint32_t length); /* Message copying for test11f() */ void test11f_internal(DltContext context, DltContextData contextData, uint32_t type_info, void *data, size_t data_size); /* Context declaration.. */ DltContext context_info; #if !DLT_DISABLE_MACRO /* for macro interface */ DLT_DECLARE_CONTEXT(context_macro_callback) DLT_DECLARE_CONTEXT(context_macro_test[DLT_TEST_NUM_CONTEXT]) #endif /* for function interface */ DltContext context_function_callback; DltContext context_function_test[DLT_TEST_NUM_CONTEXT]; DltContextData context_data; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-test-user [options]\n"); printf("Test user application providing several Tests.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -v Verbose mode\n"); printf(" -f filename Use local log file instead of sending to daemon\n"); printf(" -n count Repeats of tests (Default: 1)\n"); printf(" -t test num Test number to be executed (Default: all)\n"); printf("Tests:\n"); #if !DLT_DISABLE_MACRO printf(" 1m: (Macro IF) Test all log levels\n"); printf(" 2m: (Macro IF) Test all variable types (verbose) \n"); printf(" 3m: (Macro IF) Test all variable types (non-verbose) \n"); printf(" 4m: (Macro IF) Test different message sizes\n"); printf(" 5m: (Macro IF) Test high-level API\n"); printf(" 6m: (Macro IF) Test local printing\n"); printf(" 7m: (Macro IF) Test network trace\n"); printf(" 8m: (Macro IF) Test truncated network trace\n"); printf(" 9m: (Macro IF) Test segmented network trace\n"); printf(" 10m: (Macro IF) Test user-specified timestamps\n"); printf(" 11m: (Macro IF) Test log buffer input interface\n"); #endif printf(" 1f: (Function IF) Test all log levels\n"); printf(" 2f: (Function IF) Test all variable types (verbose) \n"); printf(" 3f: (Function IF) Test all variable types (non-verbose) \n"); printf(" 4f: (Function IF) Test different message sizes\n"); printf(" 5f: (Function IF) Test high-level API\n"); printf(" 6f: (Function IF) Test local printing\n"); printf(" 7f: (Function IF) Test network trace\n"); printf(" 8f: (Function IF) Test truncated network trace\n"); printf(" 9f: (Function IF) Test segmented network trace\n"); printf(" 10f: (Function IF) Test user-specified timestamps\n"); printf(" 11f: (Function IF) Test log buffer input interface\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { /*int vflag = 0; */ char *fvalue = 0; char *nvalue = 0; int tvalue = 0; int c; int i; char ctid[5], ctdesc[255]; int num, maxnum; opterr = 0; while ((c = getopt (argc, argv, "vf:n:t:")) != -1) switch (c) { case 'v': { /*vflag = 1; */ break; } case 'f': { fvalue = optarg; break; } case 'n': { nvalue = optarg; break; } case 't': { tvalue = atoi(optarg); break; } case '?': { if ((optopt == 'd') || (optopt == 'f') || (optopt == 'n')) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1;/*for parasoft */ } } if (fvalue) { /* DLT is intialised automatically, except another output target will be used */ if (dlt_init_file(fvalue) < 0) /* log to file */ return -1; } if (nvalue) maxnum = atoi(nvalue); else maxnum = 1; /* Register APP */ dlt_register_app("DIFT", "DLT Interface Test"); /* Register CONTEXTS... */ dlt_register_context(&context_info, "INFO", "Information context"); #if !DLT_DISABLE_MACRO /* used for macro interface tests */ DLT_REGISTER_CONTEXT(context_macro_callback, "CBM", "Callback Test context for macro interface"); for (i = 0; i < DLT_TEST_NUM_CONTEXT; i++) { snprintf(ctid, 5, "TM%02d", i + 1); snprintf(ctdesc, 255, "Test %d context for macro interface", i + 1); DLT_REGISTER_CONTEXT(context_macro_test[i], ctid, ctdesc); } #endif /* used for function interface tests */ dlt_register_context(&context_function_callback, "CBF", "Callback Test context for function interface"); for (i = 0; i < DLT_TEST_NUM_CONTEXT; i++) { snprintf(ctid, 5, "TF%02d", i + 1); snprintf(ctdesc, 255, "Test %d context for function interface", i + 1); dlt_register_context(&(context_function_test[i]), ctid, ctdesc); } /* Register callbacks... */ #if !DLT_DISABLE_MACRO /* with macro interface */ DLT_LOG(context_macro_callback, DLT_LOG_INFO, DLT_STRING("Register callback (Macro Interface) for Injection ID: 0xFFF")); DLT_REGISTER_INJECTION_CALLBACK(context_macro_callback, 0xFFF, test_injection_macro_callback); #endif /* with function interface */ if (dlt_user_log_write_start(&context_function_callback, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Register callback (Function Interface) for Injection ID: 0xFFF"); dlt_user_log_write_finish(&context_data); } dlt_register_injection_callback(&context_function_callback, 0xFFF, test_injection_function_callback); /* Tests starting */ printf("Tests starting\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Tests starting"); dlt_user_log_write_finish(&context_data); } /* wait 3 seconds before starting */ sleep(3); for (num = 0; num < maxnum; num++) { /* Execute tests... */ switch(tvalue) { case 1: { #if !DLT_DISABLE_MACRO test1m(); #endif test1f(); break; } case 2: { #if !DLT_DISABLE_MACRO test2m(); #endif test2f(); break; } case 3: { #if !DLT_DISABLE_MACRO test3m(); #endif test3f(); break; } case 4: { #if !DLT_DISABLE_MACRO test4m(); #endif test4f(); break; } case 5: { #if !DLT_DISABLE_MACRO test5m(); #endif test5f(); break; } case 6: { #if !DLT_DISABLE_MACRO test6m(); #endif test6f(); break; } case 7: { #if !DLT_DISABLE_MACRO test7m(); #endif test7f(); break; } case 8: { #if !DLT_DISABLE_MACRO test8m(); #endif test8f(); break; } case 9: { #if !DLT_DISABLE_MACRO test9m(); #endif test9f(); break; } case 10: { #if !DLT_DISABLE_MACRO test10m(); #endif test10f(); break; } case 11: { #if !DLT_DISABLE_MACRO test11m(); #endif test11f(); break; } default: #if !DLT_DISABLE_MACRO /* with macro interface */ test1m(); test2m(); test3m(); test4m(); test5m(); test6m(); test7m(); test8m(); test9m(); test10m(); test11m(); #endif /* with function interface */ test1f(); test2f(); test3f(); test4f(); test5f(); test6f(); test7f(); test8f(); test9f(); test10f(); test11f(); break; } /* wait 1 second before next repeat of tests */ sleep(1); } /* Tests finished */ printf("Tests finished\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Tests finished"); dlt_user_log_write_finish(&context_data); } /* wait 3 seconds before terminating application */ sleep(3); /* Unregister CONTEXTS... */ dlt_unregister_context(&context_info); #if !DLT_DISABLE_MACRO /* used for macro interface tests */ for (i = 0; i < DLT_TEST_NUM_CONTEXT; i++) DLT_UNREGISTER_CONTEXT(context_macro_test[i]); DLT_UNREGISTER_CONTEXT(context_macro_callback); #endif /* used for function interface tests */ for (i = 0; i < DLT_TEST_NUM_CONTEXT; i++) dlt_unregister_context(&(context_function_test[i])); dlt_unregister_context(&context_function_callback); /* Unregister APP */ dlt_unregister_app(); return 0; } /******************/ /* The test cases */ /******************/ #if !DLT_DISABLE_MACRO int test1m(void) { /* Test 1: (Macro IF) Test all log levels */ printf("Test1m: (Macro IF) Test all log levels\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test1: (Macro IF) Test all log levels")); DLT_LOG(context_macro_test[0], DLT_LOG_FATAL, DLT_STRING("fatal")); DLT_LOG(context_macro_test[0], DLT_LOG_ERROR, DLT_STRING("error")); DLT_LOG(context_macro_test[0], DLT_LOG_WARN, DLT_STRING("warn")); DLT_LOG(context_macro_test[0], DLT_LOG_INFO, DLT_STRING("info")); DLT_LOG(context_macro_test[0], DLT_LOG_DEBUG, DLT_STRING("debug")); DLT_LOG(context_macro_test[0], DLT_LOG_VERBOSE, DLT_STRING("verbose")); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test1: (Macro IF) finished")); return 0; } int test2m(void) { char buffer[10]; int num2; /* Test 2: (Macro IF) Test all variable types (verbose) */ printf("Test2m: (Macro IF) Test all variable types (verbose)\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test2: (Macro IF) Test all variable types (verbose)")); DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("string"), DLT_STRING("Hello world")); DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("utf8"), DLT_UTF8("Hello world")); DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("bool"), DLT_BOOL(1)); DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("int"), DLT_INT(INT32_MIN)); /* (-2147483647-1) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("int8"), DLT_INT8(INT8_MIN)); /* (-128) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("int16"), DLT_INT16(INT16_MIN)); /* (-32767-1) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("int32"), DLT_INT32(INT32_MIN)); /* (-2147483647-1) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("int64"), DLT_INT64(INT64_MIN)); /* (-__INT64_C(9223372036854775807)-1) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("uint"), DLT_UINT(UINT32_MAX)); /* (4294967295U) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("uint8"), DLT_UINT8(UINT8_MAX)); /* (255) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("uint16"), DLT_UINT16(UINT16_MAX)); /* (65535) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("uint32"), DLT_UINT32(UINT32_MAX)); /* (4294967295U) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("uint64"), DLT_UINT64(UINT64_MAX)); /* (__UINT64_C(18446744073709551615)) */ DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("float32"), DLT_FLOAT32(FLT_MIN), DLT_FLOAT32(FLT_MAX)); DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("float64"), DLT_FLOAT64(DBL_MIN), DLT_FLOAT64(DBL_MAX)); for (num2 = 0; num2 < 10; num2++) buffer[num2] = (char) num2; DLT_LOG(context_macro_test[1], DLT_LOG_INFO, DLT_STRING("raw"), DLT_RAW(buffer, 10)); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test2: (Macro IF) finished")); return 0; } int test3m(void) { char buffer[10]; int num2; /* Test 3: (Macro IF) Test all variable types (non-verbose) */ printf("Test3m: (Macro IF) Test all variable types (non-verbose)\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test3: (Macro IF) Test all variable types (non-verbose)")); DLT_NONVERBOSE_MODE(); DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 1, DLT_STRING("string"), DLT_STRING("Hello world")); DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 2, DLT_STRING("utf8"), DLT_UTF8("Hello world")); DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 3, DLT_STRING("bool"), DLT_BOOL(1)); DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 4, DLT_STRING("int"), DLT_INT(INT32_MIN)); /* (-2147483647-1) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 5, DLT_STRING("int8"), DLT_INT8(INT8_MIN)); /* (-128) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 6, DLT_STRING("int16"), DLT_INT16(INT16_MIN)); /* (-32767-1) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 7, DLT_STRING("int32"), DLT_INT32(INT32_MIN)); /* (-2147483647-1) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 8, DLT_STRING("int64"), DLT_INT64(INT64_MIN)); /* (-__INT64_C(9223372036854775807)-1) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 9, DLT_STRING("uint"), DLT_UINT(UINT32_MAX)); /* (4294967295U) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 10, DLT_STRING("uint8"), DLT_UINT8(UINT8_MAX)); /* (255) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 11, DLT_STRING("uint16"), DLT_UINT16(UINT16_MAX)); /* (65535) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 12, DLT_STRING("uint32"), DLT_UINT32(UINT32_MAX)); /* (4294967295U) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 13, DLT_STRING("uint64"), DLT_UINT64(UINT64_MAX)); /* (__UINT64_C(18446744073709551615)) */ DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 14, DLT_STRING("float32"), DLT_FLOAT32(FLT_MIN), DLT_FLOAT32(FLT_MAX)); DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 15, DLT_STRING("float64"), DLT_FLOAT64(DBL_MIN), DLT_FLOAT64(DBL_MAX)); for (num2 = 0; num2 < 10; num2++) buffer[num2] = (char) num2; DLT_LOG_ID(context_macro_test[2], DLT_LOG_INFO, 14, DLT_STRING("raw"), DLT_RAW(buffer, 10)); DLT_VERBOSE_MODE(); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test3: (Macro IF) finished")); return 0; } int test4m(void) { char buffer[1024]; int num; for (num = 0; num < 1024; num++) buffer[num] = (char) num; /* Test 4: (Macro IF) Message size test */ printf("Test4m: (Macro IF) Test different message sizes\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test4: (Macro IF) Test different message sizes")); DLT_LOG(context_macro_test[3], DLT_LOG_INFO, DLT_STRING("1"), DLT_RAW(buffer, 1)); DLT_LOG(context_macro_test[3], DLT_LOG_INFO, DLT_STRING("16"), DLT_RAW(buffer, 16)); DLT_LOG(context_macro_test[3], DLT_LOG_INFO, DLT_STRING("256"), DLT_RAW(buffer, 256)); DLT_LOG(context_macro_test[3], DLT_LOG_INFO, DLT_STRING("1024"), DLT_RAW(buffer, 1024)); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test4: (Macro IF) finished")); return 0; } int test5m(void) { char buffer[32]; int num; int i; void *ptr = malloc(sizeof(int)); for (num = 0; num < 32; num++) buffer[num] = (char) num; /* Test 5: (Macro IF) Test high-level API */ printf("Test5m: (Macro IF) Test high-level API\n"); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test5: (Macro IF) Test high-level API")); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_INT")); DLT_LOG_INT(context_macro_test[4], DLT_LOG_INFO, -42); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_UINT")); DLT_LOG_UINT(context_macro_test[4], DLT_LOG_INFO, 42); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_STRING")); DLT_LOG_STRING(context_macro_test[4], DLT_LOG_INFO, "String output"); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_RAW")); DLT_LOG_RAW(context_macro_test[4], DLT_LOG_INFO, buffer, 16); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_STRING_INT")); DLT_LOG_STRING_INT(context_macro_test[4], DLT_LOG_INFO, "String output: ", -42); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_STRING_UINT")); DLT_LOG_STRING_UINT(context_macro_test[4], DLT_LOG_INFO, "String output: ", 42); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next line: DLT_LOG_PTR")); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_PTR(ptr)); DLT_LOG(context_macro_test[4], DLT_LOG_INFO, DLT_STRING("Next lines: DLT_IS_LOG_LEVEL_ENABLED")); for (i = DLT_LOG_FATAL; i < DLT_LOG_MAX; i++) { if (DLT_IS_LOG_LEVEL_ENABLED(context_macro_test[4], i)) DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Loglevel is enabled: "), DLT_STRING(loglevelstr[i])); else DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Loglevel is disabled: "), DLT_STRING(loglevelstr[i])); } /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test5: (Macro IF) finished")); free(ptr); return 0; } int test6m(void) { /* Test 6: (Macro IF) Test local printing */ printf("Test6m: (Macro IF) Test local printing\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 6: (Macro IF) Test local printing"); DLT_ENABLE_LOCAL_PRINT(); DLT_LOG_STRING(context_macro_test[5], DLT_LOG_INFO, "Message (visible: locally printed)"); DLT_DISABLE_LOCAL_PRINT(); DLT_LOG_STRING(context_macro_test[5], DLT_LOG_INFO, "Message (invisible: not locally printed)"); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test6: (Macro IF) finished")); return 0; } int test7m(void) { #ifdef DLT_NETWORK_TRACE_ENABLE char buffer[32]; int num; for (num = 0; num < 32; num++) buffer[num] = (char) num; /* Show all log messages and traces */ DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON); /* Test 7: (Macro IF) Test network trace */ printf("Test7m: (Macro IF) Test network trace\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 7: (Macro IF) Test network trace"); /* Dummy messages: 16 byte header, 32 byte payload */ DLT_TRACE_NETWORK(context_macro_test[6], DLT_NW_TRACE_IPC, 16, buffer, 32, buffer); DLT_TRACE_NETWORK(context_macro_test[6], DLT_NW_TRACE_CAN, 16, buffer, 32, buffer); DLT_TRACE_NETWORK(context_macro_test[6], DLT_NW_TRACE_FLEXRAY, 16, buffer, 32, buffer); DLT_TRACE_NETWORK(context_macro_test[6], DLT_NW_TRACE_MOST, 16, buffer, 32, buffer); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test7: (Macro IF) finished")); DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT); sleep(2); #else /* Test 7: (Macro IF) Test network trace */ printf("Test7m: (Macro IF) Test network trace: Network trace interface is not supported, skipping\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 7: (Macro IF) Test network trace: Network trace interface is not supported, skipping"); #endif return 0; } int test8m(void) { #ifdef DLT_NETWORK_TRACE_ENABLE char buffer[1024 * 5]; int num; for (num = 0; num < 1024 * 5; num++) buffer[num] = (char) num; /* Show all log messages and traces */ DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON); /* Test 8: (Macro IF) Test truncated network trace*/ printf("Test8m: (Macro IF) Test truncated network trace\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 8: (Macro IF) Test truncated network trace"); /* Dummy messages: 16 byte header, 5k payload */ DLT_TRACE_NETWORK_TRUNCATED(context_macro_test[7], DLT_NW_TRACE_IPC, 16, buffer, 1024 * 5, buffer); DLT_TRACE_NETWORK_TRUNCATED(context_macro_test[7], DLT_NW_TRACE_CAN, 16, buffer, 1024 * 5, buffer); DLT_TRACE_NETWORK_TRUNCATED(context_macro_test[7], DLT_NW_TRACE_FLEXRAY, 16, buffer, 1024 * 5, buffer); DLT_TRACE_NETWORK_TRUNCATED(context_macro_test[7], DLT_NW_TRACE_MOST, 16, buffer, 1024 * 5, buffer); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test8: (Macro IF) finished")); DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT); sleep(2); #else /* Test 8: (Macro IF) Test truncated network trace*/ printf("Test8m: (Macro IF) Test truncated network trace: Network trace interface is not supported, skipping\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 8: (Macro IF) Test truncated network trace: Network trace interface is not supported, skipping"); #endif return 0; } int test9m(void) { #ifdef DLT_NETWORK_TRACE_ENABLE char buffer[1024 * 5]; int num; for (num = 0; num < 1024 * 5; num++) buffer[num] = (char) num; /* Show all log messages and traces */ DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON); /* Test 9: (Macro IF) Test segmented network trace*/ printf("Test9m: (Macro IF) Test segmented network trace\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 9: (Macro IF) Test segmented network trace"); /* Dummy messages: 16 byte header, 5k payload */ DLT_TRACE_NETWORK_SEGMENTED(context_macro_test[8], DLT_NW_TRACE_IPC, 16, buffer, 1024 * 5, buffer); DLT_TRACE_NETWORK_SEGMENTED(context_macro_test[8], DLT_NW_TRACE_CAN, 16, buffer, 1024 * 5, buffer); DLT_TRACE_NETWORK_SEGMENTED(context_macro_test[8], DLT_NW_TRACE_FLEXRAY, 16, buffer, 1024 * 5, buffer); DLT_TRACE_NETWORK_SEGMENTED(context_macro_test[8], DLT_NW_TRACE_MOST, 16, buffer, 1024 * 5, buffer); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test9: (Macro IF) finished")); DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT); sleep(2); #else /* Test 9: (Macro IF) Test segmented network trace*/ printf("Test9m: (Macro IF) Test segmented network trace: Network trace interface is not supported, skipping\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test 9: (Macro IF) Test segmented network trace: Network trace interface is not supported, skipping"); #endif return 0; } int test10m(void) { unsigned long timestamp[] = { 0, 100000, DLT_MAX_TIMESTAMP }; /* Test 10: test minimum, regular and maximum timestamp for both verbose and non verbose mode*/ printf("Test10m: (Macro IF) Test user-supplied time stamps\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test10: (Macro IF) Test user-supplied timestamps"); for (int i = 0; i < 3; i++) { char s[12]; snprintf(s, 12, "%d.%04d", (int)(timestamp[i] / 10000), (int)(timestamp[i] % 10000)); DLT_VERBOSE_MODE(); DLT_LOG_TS(context_macro_test[9], DLT_LOG_INFO, timestamp[i], DLT_STRING("Tested Timestamp:"), DLT_STRING(s)); DLT_NONVERBOSE_MODE(); DLT_LOG_ID_TS(context_macro_test[9], DLT_LOG_INFO, 16, timestamp[i], DLT_STRING(s)); } DLT_VERBOSE_MODE(); /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test10: (Macro IF) finished")); return 0; } int test11m(void) { printf("Test11m: (Macro IF) Test log buffer input interface\n"); DLT_LOG_STRING(context_info, DLT_LOG_INFO, "Test11m: (Macro IF) Test log buffer input interface"); /* Test11m: (Macro IF) Test log buffer input interface */ /* Do nothing as there is no macro interface implemented as of now */ /* wait 2 second before next test */ sleep(2); DLT_LOG(context_info, DLT_LOG_INFO, DLT_STRING("Test11: (Macro IF) finished")); return 0; } #endif int test1f(void) { /* Test 1: (Function IF) Test all log levels */ printf("Test1f: (Function IF) Test all log levels\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test1: (Function IF) Test all log levels"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[0]), &context_data, DLT_LOG_FATAL) > 0) { dlt_user_log_write_string(&context_data, "fatal"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[0]), &context_data, DLT_LOG_ERROR) > 0) { dlt_user_log_write_string(&context_data, "error"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[0]), &context_data, DLT_LOG_WARN) > 0) { dlt_user_log_write_string(&context_data, "warn"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[0]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "info"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[0]), &context_data, DLT_LOG_DEBUG) > 0) { dlt_user_log_write_string(&context_data, "debug"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[0]), &context_data, DLT_LOG_VERBOSE) > 0) { dlt_user_log_write_string(&context_data, "verbose"); dlt_user_log_write_finish(&context_data); } /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test1: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test2f(void) { char buffer[10]; int num2; /* Test 2: (Function IF) Test all variable types (verbose) */ printf("Test2f: (Function IF) Test all variable types (verbose)\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test2: (Function IF) Test all variable types (verbose)"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "bool"); dlt_user_log_write_bool(&context_data, 1); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "int"); dlt_user_log_write_int(&context_data, INT32_MIN); /* (-2147483647-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "int8"); dlt_user_log_write_int8(&context_data, INT8_MIN); /* (-128) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "int16"); dlt_user_log_write_int16(&context_data, INT16_MIN); /* (-32767-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "int32"); dlt_user_log_write_int32(&context_data, INT32_MIN); /* (-2147483647-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "int64"); dlt_user_log_write_int64(&context_data, INT64_MIN); /* (-__INT64_C(9223372036854775807)-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "uint"); dlt_user_log_write_uint(&context_data, UINT32_MAX); /* (4294967295U) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "uint8"); dlt_user_log_write_uint8(&context_data, UINT8_MAX); /* (255) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "uint16"); dlt_user_log_write_uint16(&context_data, UINT16_MAX); /* (65535) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "uint32"); dlt_user_log_write_uint32(&context_data, UINT32_MAX); /* (4294967295U) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "uint64"); dlt_user_log_write_uint64(&context_data, UINT64_MAX); /* (__UINT64_C(18446744073709551615)) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "float32"); dlt_user_log_write_float32(&context_data, FLT_MIN); dlt_user_log_write_float32(&context_data, FLT_MAX); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "float64"); dlt_user_log_write_float64(&context_data, DBL_MIN); dlt_user_log_write_float64(&context_data, DBL_MAX); dlt_user_log_write_finish(&context_data); } for (num2 = 0; num2 < 10; num2++) buffer[num2] = (char) num2; if (dlt_user_log_write_start(&(context_function_test[1]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "raw"); dlt_user_log_write_raw(&context_data, buffer, 10); dlt_user_log_write_finish(&context_data); } /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test2: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test3f(void) { char buffer[10]; int num2; /* Test 3: (Function IF) Test all variable types (non-verbose) */ printf("Test3f: (Function IF) Test all variable types (non-verbose)\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test3: (Function IF) Test all variable types (non-verbose)"); dlt_user_log_write_finish(&context_data); } dlt_nonverbose_mode(); if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 1) > 0) { /* bug mb: we have to compare against >0. in case of error -1 is returned! */ dlt_user_log_write_string(&context_data, "bool"); dlt_user_log_write_bool(&context_data, 1); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 2) > 0) { dlt_user_log_write_string(&context_data, "int"); dlt_user_log_write_int(&context_data, INT32_MIN); /* (-2147483647-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 3) > 0) { dlt_user_log_write_string(&context_data, "int8"); dlt_user_log_write_int8(&context_data, INT8_MIN); /* (-128) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 4) > 0) { dlt_user_log_write_string(&context_data, "int16"); dlt_user_log_write_int16(&context_data, INT16_MIN); /* (-32767-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 5) > 0) { dlt_user_log_write_string(&context_data, "int32"); dlt_user_log_write_int32(&context_data, INT32_MIN); /* (-2147483647-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 6) > 0) { dlt_user_log_write_string(&context_data, "int64"); dlt_user_log_write_int64(&context_data, INT64_MIN); /* (-__INT64_C(9223372036854775807)-1) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 7) > 0) { dlt_user_log_write_string(&context_data, "uint"); dlt_user_log_write_uint(&context_data, UINT32_MAX); /* (4294967295U) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 8) > 0) { dlt_user_log_write_string(&context_data, "uint8"); dlt_user_log_write_uint8(&context_data, UINT8_MAX); /* (255) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 9) > 0) { dlt_user_log_write_string(&context_data, "uint16"); dlt_user_log_write_uint16(&context_data, UINT16_MAX); /* (65535) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 10) > 0) { dlt_user_log_write_string(&context_data, "uint32"); dlt_user_log_write_uint32(&context_data, UINT32_MAX); /* (4294967295U) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 11) > 0) { dlt_user_log_write_string(&context_data, "uint64"); dlt_user_log_write_uint64(&context_data, UINT64_MAX); /* (__UINT64_C(18446744073709551615)) */ dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 12) > 0) { dlt_user_log_write_string(&context_data, "float32"); dlt_user_log_write_float32(&context_data, FLT_MIN); dlt_user_log_write_float32(&context_data, FLT_MAX); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 13) > 0) { dlt_user_log_write_string(&context_data, "float64"); dlt_user_log_write_float64(&context_data, DBL_MIN); dlt_user_log_write_float64(&context_data, DBL_MAX); dlt_user_log_write_finish(&context_data); } for (num2 = 0; num2 < 10; num2++) buffer[num2] = (char) num2; if (dlt_user_log_write_start_id(&(context_function_test[2]), &context_data, DLT_LOG_INFO, 14) > 0) { dlt_user_log_write_string(&context_data, "raw"); dlt_user_log_write_raw(&context_data, buffer, 10); dlt_user_log_write_finish(&context_data); } dlt_verbose_mode(); /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test3: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test4f(void) { char buffer[1024]; int num; for (num = 0; num < 1024; num++) buffer[num] = (char) num; /* Test 4: (Function IF) Message size test */ printf("Test4f: (Function IF) Test different message sizes\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test4: (Function IF) Test different message sizes"); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[3]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "1"); dlt_user_log_write_raw(&context_data, buffer, 1); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[3]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "16"); dlt_user_log_write_raw(&context_data, buffer, 16); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[3]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "256"); dlt_user_log_write_raw(&context_data, buffer, 256); dlt_user_log_write_finish(&context_data); } if (dlt_user_log_write_start(&(context_function_test[3]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "1024"); dlt_user_log_write_raw(&context_data, buffer, 1024); dlt_user_log_write_finish(&context_data); } /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test4: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test5f(void) { char buffer[32]; int num; int i; char log[DLT_USER_BUF_MAX_SIZE]; for (num = 0; num < 32; num++) buffer[num] = (char) num; /* Test 5: (Function IF) Test high-level API */ printf("Test5f: (Function IF) Test high-level API\n"); dlt_log_string(&context_info, DLT_LOG_INFO, "Test5: (Function IF) Test high-level API"); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next line: dlt_log_int()"); dlt_log_int(&(context_function_test[4]), DLT_LOG_INFO, -42); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next line: dlt_log_uint()"); dlt_log_uint(&(context_function_test[4]), DLT_LOG_INFO, 42); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next line: dlt_log_string()"); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "String output"); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next line: dlt_log_raw()"); dlt_log_raw(&(context_function_test[4]), DLT_LOG_INFO, buffer, 16); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next line: dlt_log_string_int()"); dlt_log_string_int(&(context_function_test[4]), DLT_LOG_INFO, "String output: ", -42); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next line: dlt_log_string_uint()"); dlt_log_string_uint(&(context_function_test[4]), DLT_LOG_INFO, "String output: ", 42); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, "Next lines: dlt_user_is_logLevel_enabled"); for (i = DLT_LOG_FATAL; i < DLT_LOG_MAX; i++) { if (dlt_user_is_logLevel_enabled(&(context_function_test[4]), i) == DLT_RETURN_TRUE) { snprintf(log, DLT_USER_BUF_MAX_SIZE, "Loglevel is enabled: %s", loglevelstr[i]); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, log); } else { snprintf(log, DLT_USER_BUF_MAX_SIZE, "Loglevel is disabled: %s", loglevelstr[i]); dlt_log_string(&(context_function_test[4]), DLT_LOG_INFO, log); } } /* wait 2 second before next test */ sleep(2); dlt_log_string(&context_info, DLT_LOG_INFO, "Test5: (Function IF) finished"); return 0; } int test6f(void) { /* Test 6: (Function IF) Test local printing */ printf("Test6f: (Function IF) Test local printing\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 6: (Function IF) Test local printing"); dlt_user_log_write_finish(&context_data); } dlt_enable_local_print(); if (dlt_user_log_write_start(&(context_function_test[5]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Message (visible: locally printed)"); dlt_user_log_write_finish(&context_data); } dlt_disable_local_print(); if (dlt_user_log_write_start(&(context_function_test[5]), &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Message (invisible: not locally printed)"); dlt_user_log_write_finish(&context_data); } /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test6: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test7f(void) { #ifdef DLT_NETWORK_TRACE_ENABLE char buffer[32]; int num; for (num = 0; num < 32; num++) buffer[num] = (char) num; /* Show all log messages and traces */ dlt_set_application_ll_ts_limit(DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON); /* Test 7: (Function IF) Test network trace */ printf("Test7f: (Function IF) Test network trace\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 7: (Function IF) Test network trace"); dlt_user_log_write_finish(&context_data); } /* Dummy message: 16 byte header, 32 byte payload */ dlt_user_trace_network(&(context_function_test[6]), DLT_NW_TRACE_IPC, 16, buffer, 32, buffer); dlt_user_trace_network(&(context_function_test[6]), DLT_NW_TRACE_CAN, 16, buffer, 32, buffer); dlt_user_trace_network(&(context_function_test[6]), DLT_NW_TRACE_FLEXRAY, 16, buffer, 32, buffer); dlt_user_trace_network(&(context_function_test[6]), DLT_NW_TRACE_MOST, 16, buffer, 32, buffer); /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test7: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } dlt_set_application_ll_ts_limit(DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT); sleep(2); #else /* Test 7: (Function IF) Test network trace */ printf("Test7f: (Function IF) Test network trace: Network trace interface is not supported, skipping\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 7: (Function IF) Test network trace: Network trace interface is not supported, skipping"); dlt_user_log_write_finish(&context_data); } #endif return 0; } int test8f(void) { #ifdef DLT_NETWORK_TRACE_ENABLE char buffer[1024 * 5]; int num; for (num = 0; num < 1024 * 5; num++) buffer[num] = (char) num; /* Show all log messages and traces */ dlt_set_application_ll_ts_limit(DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON); /* Test 8: (Function IF) Test truncated network trace */ printf("Test8f: (Function IF) Test truncated network trace\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 8: (Function IF) Test truncated network trace"); dlt_user_log_write_finish(&context_data); } /* Dummy message: 16 byte header, 32 byte payload */ dlt_user_trace_network_truncated(&(context_function_test[7]), DLT_NW_TRACE_IPC, 16, buffer, 1024 * 5, buffer, 1); dlt_user_trace_network_truncated(&(context_function_test[7]), DLT_NW_TRACE_CAN, 16, buffer, 1024 * 5, buffer, 1); dlt_user_trace_network_truncated(&(context_function_test[7]), DLT_NW_TRACE_FLEXRAY, 16, buffer, 1024 * 5, buffer, 1); dlt_user_trace_network_truncated(&(context_function_test[7]), DLT_NW_TRACE_MOST, 16, buffer, 1024 * 5, buffer, 1); /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test8: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } dlt_set_application_ll_ts_limit(DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT); sleep(2); #else /* Test 8: (Function IF) Test truncated network trace */ printf("Test8f: (Function IF) Test truncated network trace: Network trace interface is not supported, skipping\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 8: (Function IF) Test truncated network trace: Network trace interface is not supported, skipping"); dlt_user_log_write_finish(&context_data); } #endif return 0; } int test9f(void) { #ifdef DLT_NETWORK_TRACE_ENABLE char buffer[1024 * 5]; int num; for (num = 0; num < 1024 * 5; num++) buffer[num] = (char) num; /* Show all log messages and traces */ dlt_set_application_ll_ts_limit(DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON); /* Test 9: (Function IF) Test segmented network trace */ printf("Test9f: (Function IF) Test segmented network trace\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 9: (Function IF) Test segmented network trace"); dlt_user_log_write_finish(&context_data); } /* Dummy message: 16 byte header, 5k payload */ dlt_user_trace_network_segmented(&(context_function_test[8]), DLT_NW_TRACE_IPC, 16, buffer, 1024 * 5, buffer); dlt_user_trace_network_segmented(&(context_function_test[8]), DLT_NW_TRACE_CAN, 16, buffer, 1024 * 5, buffer); dlt_user_trace_network_segmented(&(context_function_test[8]), DLT_NW_TRACE_FLEXRAY, 16, buffer, 1024 * 5, buffer); dlt_user_trace_network_segmented(&(context_function_test[8]), DLT_NW_TRACE_MOST, 16, buffer, 1024 * 5, buffer); /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test9: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } dlt_set_application_ll_ts_limit(DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT); sleep(2); #else /* Test 9: (Function IF) Test segmented network trace */ printf("Test9f: (Function IF) Test segmented network trace: Network trace interface is not supported, skipping\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test 9: (Function IF) Test segmented network trace: Network trace interface is not supported, skipping"); dlt_user_log_write_finish(&context_data); } #endif return 0; } int test10f(void) { unsigned long timestamp[] = { 0, 100000, DLT_MAX_TIMESTAMP }; /* Test 10: test minimum, regular and maximum timestamp for both verbose and non verbose mode*/ printf("Test10f: (Function IF) Test user-supplied timestamps\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test10: (Function IF) Test user-supplied time stamps"); dlt_user_log_write_finish(&context_data); } for (int i = 0; i < 3; i++) { char s[12]; snprintf(s, 12, "%d.%04d", (int)(timestamp[i] / 10000), (int)(timestamp[i] % 10000)); dlt_verbose_mode(); if (dlt_user_log_write_start(&context_function_test[9], &context_data, DLT_LOG_INFO) > 0) { context_data.use_timestamp = DLT_USER_TIMESTAMP; context_data.user_timestamp = (uint32_t) timestamp[i]; dlt_user_log_write_string(&context_data, "Tested Timestamp:"); dlt_user_log_write_string(&context_data, s); dlt_user_log_write_finish(&context_data); } dlt_nonverbose_mode(); if (dlt_user_log_write_start_id(&(context_function_test[9]), &context_data, DLT_LOG_INFO, 16) > 0) { context_data.use_timestamp = DLT_USER_TIMESTAMP; context_data.user_timestamp = (uint32_t) timestamp[i]; dlt_user_log_write_string(&context_data, s); dlt_user_log_write_finish(&context_data); } } dlt_verbose_mode(); /* wait 2 second before next test */ sleep(2); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test10: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } int test11f(void) { uint32_t type_info; printf("Test11f: (Function IF) Test log buffer input interface\n"); if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test11: (Function IF) Test log buffer input interface"); dlt_user_log_write_finish(&context_data); } uint8_t data_bool = 1; /* true */ type_info = DLT_TYPE_INFO_BOOL; test11f_internal(context_function_test[10], context_data, type_info, &data_bool, sizeof(uint8_t)); int8_t data_int8 = INT8_MIN; /* (-128) */ type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_int8, sizeof(int8_t)); int16_t data_int16 = INT16_MIN; /* (-32768) */ type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_int16, sizeof(int16_t)); int32_t data_int32 = INT32_MIN; /* (-2147483648) */ type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_int32, sizeof(int32_t)); int64_t data_int64 = INT64_MIN; /* (-9223372036854775808) */ type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_int64, sizeof(int64_t)); uint8_t data_uint8 = UINT8_MAX; /* (255) */ type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_uint8, sizeof(uint8_t)); uint16_t data_uint16 = UINT16_MAX; /* (65535) */ type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_uint16, sizeof(uint16_t)); uint32_t data_uint32 = UINT32_MAX; /* (4294967295) */ type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_uint32, sizeof(uint32_t)); uint64_t data_uint64 = UINT64_MAX; /* (18446744073709551615) */ type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_uint64, sizeof(uint64_t)); float32_t data_float32 = FLT_MIN; /* (1.17549e-38) */ type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_float32, sizeof(float32_t)); data_float32 = FLT_MAX; /* (3.40282e+38) */ type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_float32, sizeof(float32_t)); float64_t data_float64 = DBL_MIN; /* (2.22507e-308) */ type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_float64, sizeof(float64_t)); data_float64 = DBL_MAX; /* (1.79769e+308) */ type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT; test11f_internal(context_function_test[10], context_data, type_info, &data_float64, sizeof(float64_t)); /* wait 2 second before next test */ sleep(2); /* Test11f: (Function IF) Test log buffer input interface */ if (dlt_user_log_write_start(&context_info, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Test11: (Function IF) finished"); dlt_user_log_write_finish(&context_data); } return 0; } #if !DLT_DISABLE_MACRO int test_injection_macro_callback(uint32_t service_id, void *data, uint32_t length) { char text[1024]; memset(text, 0, 1024); snprintf(text, 1024, "Injection received (macro IF). ID: 0x%.4x, Length: %d", service_id, length); printf("%s \n", text); DLT_LOG(context_macro_callback, DLT_LOG_INFO, DLT_STRING("Injection received (macro IF). ID: "), DLT_UINT32(service_id), DLT_STRING("Data:"), DLT_STRING(text)); memset(text, 0, 1024); if (length > 0) { dlt_print_mixed_string(text, 1024, data, (int) length, 0); printf("%s \n", text); } return 0; } #endif int test_injection_function_callback(uint32_t service_id, void *data, uint32_t length) { char text[1024]; memset(text, 0, 1024); snprintf(text, 1024, "Injection received (function IF). ID: 0x%.4x, Length: %d", service_id, length); printf("%s \n", text); if (dlt_user_log_write_start(&context_function_callback, &context_data, DLT_LOG_INFO) > 0) { dlt_user_log_write_string(&context_data, "Injection received (function IF). ID: "); dlt_user_log_write_uint32(&context_data, service_id); dlt_user_log_write_string(&context_data, "Data:"); dlt_user_log_write_string(&context_data, text); } memset(text, 0, 1024); if (length > 0) { dlt_print_mixed_string(text, 1024, data, (int) length, 0); printf("%s \n", text); } return 0; } void test11f_internal(DltContext context, DltContextData contextData, uint32_t type_info, void *data, size_t data_size) { char buffer[DLT_USER_BUF_MAX_SIZE] = {0}; size_t size = 0; int32_t args_num = 0; memcpy(buffer + size, &(type_info), sizeof(uint32_t)); size += sizeof(uint32_t); memcpy(buffer + size, data, data_size); size += data_size; args_num++; if (dlt_user_log_write_start_w_given_buffer(&context, &contextData, DLT_LOG_WARN, buffer, size, args_num) > 0) { dlt_user_log_write_finish_w_given_buffer(&contextData); } } dlt-daemon-2.18.10/systemd/000077500000000000000000000000001446635226000154075ustar00rootroot00000000000000dlt-daemon-2.18.10/systemd/3rdparty/000077500000000000000000000000001446635226000171575ustar00rootroot00000000000000dlt-daemon-2.18.10/systemd/3rdparty/sd-daemon.c000066400000000000000000000330561446635226000212010ustar00rootroot00000000000000/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*** Copyright 2010 Lennart Poettering Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #ifdef __BIONIC__ #include #else #include #endif #include #include #include #include #include #include #include #include #include #if defined(__linux__) #include #endif #include "sd-daemon.h" #if (__GNUC__ >= 4) #ifdef SD_EXPORT_SYMBOLS /* Export symbols */ #define _sd_export_ __attribute__ ((visibility("default"))) #else /* Don't export the symbols */ #define _sd_export_ __attribute__ ((visibility("hidden"))) #endif #else #define _sd_export_ #endif _sd_export_ int sd_listen_fds(int unset_environment) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else int r, fd; const char *e; char *p = NULL; unsigned long l; if (!(e = getenv("LISTEN_PID"))) { r = 0; goto finish; } errno = 0; l = strtoul(e, &p, 10); if (errno != 0) { r = -errno; goto finish; } if (!p || *p || l <= 0) { r = -EINVAL; goto finish; } /* Is this for us? */ if (getpid() != (pid_t) l) { r = 0; goto finish; } if (!(e = getenv("LISTEN_FDS"))) { r = 0; goto finish; } errno = 0; l = strtoul(e, &p, 10); if (errno != 0) { r = -errno; goto finish; } if (!p || *p) { r = -EINVAL; goto finish; } for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { int flags; if ((flags = fcntl(fd, F_GETFD)) < 0) { r = -errno; goto finish; } if (flags & FD_CLOEXEC) continue; if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { r = -errno; goto finish; } } r = (int) l; finish: if (unset_environment) { unsetenv("LISTEN_PID"); unsetenv("LISTEN_FDS"); } return r; #endif } _sd_export_ int sd_is_fifo(int fd, const char *path) { struct stat st_fd; if (fd < 0) return -EINVAL; memset(&st_fd, 0, sizeof(st_fd)); if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISFIFO(st_fd.st_mode)) return 0; if (path) { struct stat st_path; memset(&st_path, 0, sizeof(st_path)); if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) return 0; return -errno; } return st_path.st_dev == st_fd.st_dev && st_path.st_ino == st_fd.st_ino; } return 1; } _sd_export_ int sd_is_special(int fd, const char *path) { struct stat st_fd; if (fd < 0) return -EINVAL; if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) return 0; if (path) { struct stat st_path; if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) return 0; return -errno; } if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) return st_path.st_dev == st_fd.st_dev && st_path.st_ino == st_fd.st_ino; else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) return st_path.st_rdev == st_fd.st_rdev; else return 0; } return 1; } static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; if (fd < 0 || type < 0) return -EINVAL; if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISSOCK(st_fd.st_mode)) return 0; if (type != 0) { int other_type = 0; socklen_t l = sizeof(other_type); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) return -errno; if (l != sizeof(other_type)) return -EINVAL; if (other_type != type) return 0; } if (listening >= 0) { int accepting = 0; socklen_t l = sizeof(accepting); if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) return -errno; if (l != sizeof(accepting)) return -EINVAL; if (!accepting != !listening) return 0; } return 1; } union sockaddr_union { struct sockaddr sa; struct sockaddr_in in4; struct sockaddr_in6 in6; struct sockaddr_un un; struct sockaddr_storage storage; }; _sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { int r; if (family < 0) return -EINVAL; if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) return r; if (family > 0) { union sockaddr_union sockaddr; socklen_t l; memset(&sockaddr, 0, sizeof(sockaddr)); l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if (l < sizeof(sa_family_t)) return -EINVAL; return sockaddr.sa.sa_family == family; } return 1; } _sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { union sockaddr_union sockaddr; socklen_t l; int r; if (family != 0 && family != AF_INET && family != AF_INET6) return -EINVAL; if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) return r; memset(&sockaddr, 0, sizeof(sockaddr)); l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if (l < sizeof(sa_family_t)) return -EINVAL; if (sockaddr.sa.sa_family != AF_INET && sockaddr.sa.sa_family != AF_INET6) return 0; if (family > 0) if (sockaddr.sa.sa_family != family) return 0; if (port > 0) { if (sockaddr.sa.sa_family == AF_INET) { if (l < sizeof(struct sockaddr_in)) return -EINVAL; return htons(port) == sockaddr.in4.sin_port; } else { if (l < sizeof(struct sockaddr_in6)) return -EINVAL; return htons(port) == sockaddr.in6.sin6_port; } } return 1; } _sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { union sockaddr_union sockaddr; socklen_t l; int r; if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) return r; memset(&sockaddr, 0, sizeof(sockaddr)); l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if (l < sizeof(sa_family_t)) return -EINVAL; if (sockaddr.sa.sa_family != AF_UNIX) return 0; if (path) { if (length <= 0) length = strlen(path); if (length <= 0) /* Unnamed socket */ return l == offsetof(struct sockaddr_un, sun_path); if (path[0]) /* Normal path socket */ return (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && memcmp(path, sockaddr.un.sun_path, length+1) == 0; else /* Abstract namespace socket */ return (l == offsetof(struct sockaddr_un, sun_path) + length) && memcmp(path, sockaddr.un.sun_path, length) == 0; } return 1; } _sd_export_ int sd_is_mq(int fd, const char *path) { #if !defined(__linux__) return 0; #else struct mq_attr attr; if (fd < 0) return -EINVAL; if (mq_getattr(fd, &attr) < 0) return -errno; if (path) { char fpath[PATH_MAX]; struct stat a, b; if (path[0] != '/') return -EINVAL; if (fstat(fd, &a) < 0) return -errno; strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); fpath[sizeof(fpath)-1] = 0; if (stat(fpath, &b) < 0) return -errno; if (a.st_dev != b.st_dev || a.st_ino != b.st_ino) return 0; } return 1; #endif } _sd_export_ int sd_notify(int unset_environment, const char *state) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) return 0; #else int fd = -1, r; struct msghdr msghdr; struct iovec iovec; union sockaddr_union sockaddr; const char *e; if (!state) { r = -EINVAL; goto finish; } if (!(e = getenv("NOTIFY_SOCKET"))) return 0; /* Must be an abstract socket, or an absolute path */ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { r = -EINVAL; goto finish; } if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { r = -errno; goto finish; } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sa.sa_family = AF_UNIX; strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)-1); if (sockaddr.un.sun_path[0] == '@') sockaddr.un.sun_path[0] = 0; memset(&iovec, 0, sizeof(iovec)); iovec.iov_base = (char*) state; iovec.iov_len = strlen(state); memset(&msghdr, 0, sizeof(msghdr)); msghdr.msg_name = &sockaddr; msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) msghdr.msg_namelen = sizeof(struct sockaddr_un); msghdr.msg_iov = &iovec; msghdr.msg_iovlen = 1; if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { r = -errno; goto finish; } r = 1; finish: if (unset_environment) unsetenv("NOTIFY_SOCKET"); if (fd >= 0) close(fd); return r; #endif } _sd_export_ int sd_notifyf(int unset_environment, const char *format, ...) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else va_list ap; char *p = NULL; int r; va_start(ap, format); r = vasprintf(&p, format, ap); va_end(ap); if (r < 0 || !p) return -ENOMEM; r = sd_notify(unset_environment, p); free(p); return r; #endif } _sd_export_ int sd_booted(void) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else struct stat a, b; /* We simply test whether the systemd cgroup hierarchy is * mounted */ if (lstat("/sys/fs/cgroup", &a) < 0) return 0; if (lstat("/sys/fs/cgroup/systemd", &b) < 0) return 0; return a.st_dev != b.st_dev; #endif } dlt-daemon-2.18.10/systemd/3rdparty/sd-daemon.h000066400000000000000000000255641446635226000212130ustar00rootroot00000000000000/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ #ifndef foosddaemonhfoo #define foosddaemonhfoo /*** Copyright 2010 Lennart Poettering Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ #include #include #ifdef __cplusplus extern "C" { #endif /* Reference implementation of a few systemd related interfaces for writing daemons. These interfaces are trivial to implement. To simplify porting we provide this reference implementation. Applications are welcome to reimplement the algorithms described here if they do not want to include these two source files. The following functionality is provided: - Support for logging with log levels on stderr - File descriptor passing for socket-based activation - Daemon startup and status notification - Detection of systemd boots You may compile this with -DDISABLE_SYSTEMD to disable systemd support. This makes all those calls NOPs that are directly related to systemd (i.e. only sd_is_xxx() will stay useful). Since this is drop-in code we don't want any of our symbols to be exported in any case. Hence we declare hidden visibility for all of them. You may find an up-to-date version of these source files online: http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h http://cgit.freedesktop.org/systemd/systemd/plain/src/sd-daemon.c This should compile on non-Linux systems, too, but with the exception of the sd_is_xxx() calls all functions will become NOPs. See sd-daemon(7) for more information. */ #ifndef _sd_printf_attr_ #if __GNUC__ >= 4 #define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) #else #define _sd_printf_attr_(a,b) #endif #endif /* Log levels for usage on stderr: fprintf(stderr, SD_NOTICE "Hello World!\n"); This is similar to printk() usage in the kernel. */ #define SD_EMERG "<0>" /* system is unusable */ #define SD_ALERT "<1>" /* action must be taken immediately */ #define SD_CRIT "<2>" /* critical conditions */ #define SD_ERR "<3>" /* error conditions */ #define SD_WARNING "<4>" /* warning conditions */ #define SD_NOTICE "<5>" /* normal but significant condition */ #define SD_INFO "<6>" /* informational */ #define SD_DEBUG "<7>" /* debug-level messages */ /* The first passed file descriptor is fd 3 */ #define SD_LISTEN_FDS_START 3 /* Returns how many file descriptors have been passed, or a negative errno code on failure. Optionally, removes the $LISTEN_FDS and $LISTEN_PID file descriptors from the environment (recommended, but problematic in threaded environments). If r is the return value of this function you'll find the file descriptors passed as fds SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative errno style error code on failure. This function call ensures that the FD_CLOEXEC flag is set for the passed file descriptors, to make sure they are not passed on to child processes. If FD_CLOEXEC shall not be set, the caller needs to unset it after this call for all file descriptors that are used. See sd_listen_fds(3) for more information. */ int sd_listen_fds(int unset_environment); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a FIFO in the file system stored under the specified path, 0 otherwise. If path is NULL a path name check will not be done and the call only verifies if the file descriptor refers to a FIFO. Returns a negative errno style error code on failure. See sd_is_fifo(3) for more information. */ int sd_is_fifo(int fd, const char *path); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a special character device on the file system stored under the specified path, 0 otherwise. If path is NULL a path name check will not be done and the call only verifies if the file descriptor refers to a special character. Returns a negative errno style error code on failure. See sd_is_special(3) for more information. */ int sd_is_special(int fd, const char *path); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a socket of the specified family (AF_INET, ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If family is 0 a socket family check will not be done. If type is 0 a socket type check will not be done and the call only verifies if the file descriptor refers to a socket. If listening is > 0 it is verified that the socket is in listening mode. (i.e. listen() has been called) If listening is == 0 it is verified that the socket is not in listening mode. If listening is < 0 no listening mode check is done. Returns a negative errno style error code on failure. See sd_is_socket(3) for more information. */ int sd_is_socket(int fd, int family, int type, int listening); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is an Internet socket, of the specified family (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version check is not done. If type is 0 a socket type check will not be done. If port is 0 a socket port check will not be done. The listening flag is used the same way as in sd_is_socket(). Returns a negative errno style error code on failure. See sd_is_socket_inet(3) for more information. */ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is an AF_UNIX socket of the specified type (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 a socket type check will not be done. If path is NULL a socket path check will not be done. For normal AF_UNIX sockets set length to 0. For abstract namespace sockets set length to the length of the socket name (including the initial 0 byte), and pass the full socket path in path (including the initial 0 byte). The listening flag is used the same way as in sd_is_socket(). Returns a negative errno style error code on failure. See sd_is_socket_unix(3) for more information. */ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a POSIX Message Queue of the specified name, 0 otherwise. If path is NULL a message queue name check is not done. Returns a negative errno style error code on failure. */ int sd_is_mq(int fd, const char *path); /* Informs systemd about changed daemon state. This takes a number of newline separated environment-style variable assignments in a string. The following variables are known: READY=1 Tells systemd that daemon startup is finished (only relevant for services of Type=notify). The passed argument is a boolean "1" or "0". Since there is little value in signaling non-readiness the only value daemons should send is "READY=1". STATUS=... Passes a single-line status string back to systemd that describes the daemon state. This is free-from and can be used for various purposes: general state feedback, fsck-like programs could pass completion percentages and failing programs could pass a human readable error message. Example: "STATUS=Completed 66% of file system check..." ERRNO=... If a daemon fails, the errno-style error code, formatted as string. Example: "ERRNO=2" for ENOENT. BUSERROR=... If a daemon fails, the D-Bus error-style error code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" MAINPID=... The main pid of a daemon, in case systemd did not fork off the process itself. Example: "MAINPID=4711" WATCHDOG=1 Tells systemd to update the watchdog timestamp. Services using this feature should do this in regular intervals. A watchdog framework can use the timestamps to detect failed services. Daemons can choose to send additional variables. However, it is recommended to prefix variable names not listed above with X_. Returns a negative errno-style error code on failure. Returns > 0 if systemd could be notified, 0 if it couldn't possibly because systemd is not running. Example: When a daemon finished starting up, it could issue this call to notify systemd about it: sd_notify(0, "READY=1"); See sd_notifyf() for more complete examples. See sd_notify(3) for more information. */ int sd_notify(int unset_environment, const char *state); /* Similar to sd_notify() but takes a format string. Example 1: A daemon could send the following after initialization: sd_notifyf(0, "READY=1\n" "STATUS=Processing requests...\n" "MAINPID=%lu", (unsigned long) getpid()); Example 2: A daemon could send the following shortly before exiting, on failure: sd_notifyf(0, "STATUS=Failed to start up: %s\n" "ERRNO=%i", strerror(errno), errno); See sd_notifyf(3) for more information. */ int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); /* Returns > 0 if the system was booted with systemd. Returns < 0 on error. Returns 0 if the system was not booted with systemd. Note that all of the functions above handle non-systemd boots just fine. You should NOT protect them with a call to this function. Also note that this function checks whether the system, not the user session is controlled by systemd. However the functions above work for both user and system services. See sd_booted(3) for more information. */ int sd_booted(void); #ifdef __cplusplus } #endif #endif dlt-daemon-2.18.10/systemd/CMakeLists.txt000066400000000000000000000074431446635226000201570ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### if(WITH_SYSTEMD) set(SYSTEMD_CONFIGURATIONS_FILES_DIR ${SYSTEMD_UNITDIR} ) if(WITH_SYSTEMD_WATCHDOG) set( DLT_WatchdogSec 2 ) message( STATUS "The systemd watchdog is enabled - timeout is set to ${DLT_WatchdogSec} seconds") else(WITH_SYSTEMD_WATCHDOG) set( DLT_WatchdogSec 0 ) message( STATUS "The systemd watchdog is disabled") endif(WITH_SYSTEMD_WATCHDOG) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt.service.cmake ${PROJECT_BINARY_DIR}/systemd/dlt.service) message( STATUS "Configured systemd unit file:dlt.service" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) if(WITH_DLT_SYSTEM) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt-system.service.cmake ${PROJECT_BINARY_DIR}/systemd/dlt-system.service) message( STATUS "Configured systemd unit file:dlt-system.service" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt-system.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif(WITH_DLT_SYSTEM) if(WITH_DLT_DBUS) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt-dbus.service.cmake ${PROJECT_BINARY_DIR}/systemd/dlt-dbus.service) message( STATUS "Configured systemd unit file:dlt-dbus.service" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt-dbus.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif(WITH_DLT_DBUS) if(WITH_DLT_CONSOLE AND WITH_DLT_EXAMPLES) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt-receive.service.cmake ${PROJECT_BINARY_DIR}/systemd/dlt-receive.service) message( STATUS "Configured systemd unit file:dlt-receive.service" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt-receive.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif(WITH_DLT_CONSOLE AND WITH_DLT_EXAMPLES) if(WITH_DLT_EXAMPLES) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt-example-user.service.cmake ${PROJECT_BINARY_DIR}/systemd/dlt-example-user.service) message( STATUS "Configured systemd unit file:dlt-example-user.service" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt-example-user.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif(WITH_DLT_EXAMPLES) if(WITH_DLT_ADAPTOR_UDP OR WITH_DLT_ADAPTOR) set( DLT_ADAPTOR_UDP_APPID "DUDP" ) set( DLT_ADAPTOR_UDP_CTID "DCTI" ) set( DLT_ADAPTOR_UDP_PORT 4712 ) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt-adaptor-udp.service.cmake ${PROJECT_BINARY_DIR}/systemd/dlt-adaptor-udp.service) message( STATUS "Configured systemd unit file:dlt-adaptor-udp.service" ) message(STATUS "DLT adaptor udp configuration: APPID=${DLT_ADAPTOR_UDP_APPID} CTID=${DLT_ADAPTOR_UDP_CTID} PORT=${DLT_ADAPTOR_UDP_PORT}" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt-adaptor-udp.service DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif(WITH_DLT_ADAPTOR_UDP) if (WITH_SYSTEMD_SOCKET_ACTIVATION) configure_file(${PROJECT_SOURCE_DIR}/systemd/dlt.socket.cmake ${PROJECT_BINARY_DIR}/systemd/dlt.socket) message( STATUS "Configured systemd socket file:dlt.socket" ) install(FILES ${PROJECT_BINARY_DIR}/systemd/dlt.socket DESTINATION ${SYSTEMD_CONFIGURATIONS_FILES_DIR} ) endif() message(STATUS "Unit files will be installed to ${SYSTEMD_CONFIGURATIONS_FILES_DIR} after make install" ) endif(WITH_SYSTEMD) dlt-daemon-2.18.10/systemd/dlt-adaptor-udp.service.cmake000066400000000000000000000014071446635226000230530ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### [Unit] Description=COVESA DLT adaptor stdin. Adaptor for forwarding received UDP messages to DLT daemon. Wants=dlt.service [Service] Type=simple User=@DLT_USER@ ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-adaptor-udp -a @DLT_ADAPTOR_UDP_APPID@ -c @DLT_ADAPTOR_UDP_CTID@ -p @DLT_ADAPTOR_UDP_PORT@ LimitCORE=infinity [Install] WantedBy=multi-user.targetdlt-daemon-2.18.10/systemd/dlt-dbus.service.cmake000066400000000000000000000013711446635226000215700ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### [Unit] Description=COVESA DLT DBus. Application to forward DBus messages to DLT. Documentation=man:dlt-dbus(1) man:dlt-dbus.conf(5) Wants=dlt.service [Service] Type=simple User=@DLT_USER@ ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-dbus WatchdogSec=@DLT_WatchdogSec@ NotifyAccess=main LimitCORE=infinity [Install] WantedBy=basic.target dlt-daemon-2.18.10/systemd/dlt-example-user.service.cmake000066400000000000000000000013141446635226000232370ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### [Unit] Description=COVESA DLT example user. Generate DLT messages and store them to file or send them to daemon. Wants=dlt.service [Service] Type=simple User=@DLT_USER@ ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-example-user "Hallo from COVESA DLT example user application" LimitCORE=infinitydlt-daemon-2.18.10/systemd/dlt-receive.service.cmake000066400000000000000000000013311446635226000222510ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### [Unit] Description=COVESA DLT receive. Receive DLT messages from DLT daemon and print or store the messages. Documentation=man:dlt-receive(1) Wants=dlt.service [Service] Type=simple User=@DLT_USER@ ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-receive -o /tmp/dlt_receive_log.dlt localhost LimitCORE=infinitydlt-daemon-2.18.10/systemd/dlt-system.service.cmake000077500000000000000000000014601446635226000221610ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### [Unit] Description=COVESA DLT system. Application to forward syslog messages to DLT, transfer system information, logs and files. Documentation=man:dlt-system(1) man:dlt-system.conf(5) Wants=dlt.service [Service] Type=simple User=@DLT_USER@ ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-system WatchdogSec=@DLT_WatchdogSec@ NotifyAccess=main LimitCORE=infinity [Install] WantedBy=basic.target dlt-daemon-2.18.10/systemd/dlt.service.cmake000077500000000000000000000013011446635226000206310ustar00rootroot00000000000000####### # SPDX license identifier: MPL-2.0 # # Copyright (C) 2011-2015, BMW AG # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ####### [Unit] Description=COVESA DLT logging daemon Documentation=man:dlt-daemon(1) man:dlt.conf(5) [Service] Type=simple User=@DLT_USER@ ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-daemon WatchdogSec=@DLT_WatchdogSec@ NotifyAccess=main LimitCORE=infinity [Install] WantedBy=basic.target dlt-daemon-2.18.10/systemd/dlt.socket.cmake000077500000000000000000000002331446635226000204640ustar00rootroot00000000000000[Socket] ListenStream=@DLT_USER_IPC_PATH@/dlt FileDescriptorName=@DLT_USER_IPC_PATH@/dlt SocketGroup=dlt SocketMode=0666 [Install] WantedBy=sockets.targetdlt-daemon-2.18.10/tests/000077500000000000000000000000001446635226000150615ustar00rootroot00000000000000dlt-daemon-2.18.10/tests/CMakeLists.txt000066400000000000000000000076061446635226000176320ustar00rootroot00000000000000# Setup testing enable_testing() SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isystem ${gtest_SOURCE_DIR}/include") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${gtest_SOURCE_DIR}/include -std=gnu++0x") configure_file(${PROJECT_SOURCE_DIR}/tests/testfile.dlt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/testfilter.txt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/testfile_filetransfer.txt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) if("${GTEST_BOTH_LIBRARIES}" STREQUAL "") set(GTEST_LIBS gtest gtest_main) set(GTEST_LIBS ${GTEST_LIBS} CACHE STRING "Gtest libraries") else() set(GTEST_LIBS ${GTEST_BOTH_LIBRARIES}) endif() if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux|CYGWIN") set(LIBRARIES "") else() set(LIBRARIES socket) endif() if(WITH_SYSTEMD) set(SYSTEMD_LIBS systemd) endif(WITH_SYSTEMD) set(DLT_LIBRARIES dlt ${GTEST_LIBS} ${LIBRARIES}) set(DLT_DAEMON_LIBRARIES dlt_daemon ${GTEST_LIBS} ${LIBRARIES} ${SYSTEMD_LIBS}) set(DLT_CONTROL_LIBRARIES dlt dlt_control_common_lib ${GTEST_LIBS}) #Receiver used for QTs. add_test() is not required add_executable(dlt_test_receiver dlt_test_receiver.c) target_link_libraries(dlt_test_receiver ${DLT_LIBRARIES}) #################### # DLT library tests #################### set(TARGET_LIST gtest_dlt_common gtest_dlt_user gtest_dlt_daemon_common dlt_env_ll_unit_test ) foreach(target IN LISTS TARGET_LIST) set(target_SRCS ${target}) if(${target} STREQUAL "gtest_dlt_daemon_common") set(target_SRCS ${target_SRCS} ${PROJECT_SOURCE_DIR}/src/daemon/dlt_daemon_common.c) endif() add_executable(${target} ${target_SRCS}) target_link_libraries(${target} ${DLT_LIBRARIES}) add_test(NAME ${target} COMMAND ${target}) endforeach() ################### # DLT daemon tests ################### set(TARGET_LIST gtest_dlt_daemon_gateway gtest_dlt_daemon_offline_log gtest_dlt_daemon_event_handler gtest_dlt_daemon_multiple_files_logging ) if(WITH_DLT_SHM_ENABLE) list(APPEND TARGET_LIST gtest_dlt_shm) endif() foreach(target IN LISTS TARGET_LIST) set(target_SRCS ${target}) add_executable(${target} ${target_SRCS} ${systemd_SRCS}) target_link_libraries(${target} ${DLT_DAEMON_LIBRARIES} ${ZLIB_LIBRARY}) if(EXISTS ${PROJECT_SOURCE_DIR}/tests/${target}.sh) configure_file(${PROJECT_SOURCE_DIR}/tests/${target}.sh ${PROJECT_BINARY_DIR}/tests COPYONLY) add_test(NAME ${target} COMMAND /bin/sh -e -c "\ sh $.sh ; \ $ || TESTS_FAILED=1 && TESTS_FAILED=0 \ sleep 0.5 ; \ killall -v dlt-daemon || echo 'Could not find any daemon to kill' ; exit $TESTS_FAILED") set_tests_properties(${target} PROPERTIES ENVIRONMENT "PATH=$:$ENV{PATH}; \ DLT_UT_DAEMON_PATH=$") else() add_test(NAME ${target} COMMAND ${target}) endif() set_tests_properties(${target} PROPERTIES TIMEOUT "${seconds}") endforeach() ##################### # DLT control tests ##################### if(WITH_EXTENDED_FILTERING) configure_file(${PROJECT_SOURCE_DIR}/tests/testfile_extended.dlt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/testfilter.json ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) add_executable(gtest_dlt_json_filter gtest_dlt_json_filter.cpp) target_link_libraries(gtest_dlt_json_filter ${DLT_CONTROL_LIBRARIES}) add_test(NAME gtest_dlt_json_filter COMMAND gtest_dlt_json_filter) set_tests_properties(${target} PROPERTIES TIMEOUT "${seconds}") endif() dlt-daemon-2.18.10/tests/component/000077500000000000000000000000001446635226000170635ustar00rootroot00000000000000dlt-daemon-2.18.10/tests/component/dlt-logd-converter/000077500000000000000000000000001446635226000225765ustar00rootroot00000000000000dlt-daemon-2.18.10/tests/component/dlt-logd-converter/CMakeLists.txt000066400000000000000000000016521446635226000253420ustar00rootroot00000000000000########################## # DLT logd-converter test ########################## configure_file(${PROJECT_SOURCE_DIR}/tests/component/dlt-logd-converter/dlt-logd-converter.conf ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/component/dlt-logd-converter/dlt-logdctxt.json ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/component/dlt-logd-converter/abnormal-dlt-logd-converter.conf ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) set(dlt_logd_converter_SRC ${PROJECT_SOURCE_DIR}/src/android/dlt-logd-converter.cpp) set(gtest_dlt_logd_converter_SRC ${PROJECT_SOURCE_DIR}/tests/component/dlt-logd-converter/gtest_dlt_logd_converter.cpp) add_executable(gtest_dlt_logd_converter ${dlt_logd_converter_SRC} ${gtest_dlt_logd_converter_SRC}) target_link_libraries(gtest_dlt_logd_converter ${DLT_LIBRARIES}) add_test(NAME gtest_dlt_logd_converter COMMAND gtest_dlt_logd_converter) dlt-daemon-2.18.10/tests/component/dlt-logd-converter/abnormal-dlt-logd-converter.conf000066400000000000000000000001531446635226000307500ustar00rootroot00000000000000ApplicationID=DLOGCONV ContextID=DLT AndroidLogdJSONpath= # AndroidLogdContextID=CCCCC dlt-daemon-2.18.10/tests/component/dlt-logd-converter/dlt-logd-converter.conf000066400000000000000000000013231446635226000271570ustar00rootroot00000000000000# Configuration file of dlt-logd-converter ######################################################################## # General configuration ######################################################################## # The common application ID for Android native applications to appear on DLT client (Default: LOGD) ApplicationID = LOGD # The common context ID for Android native applications to appear on DLT client (Default: LOGF) ContextID = LOGF # Path for JSON file (Default: /vendor/etc/dlt-logdctxt.json) AndroidLogdJSONpath = /vendor/etc/dlt-logdctxt.json # The common context ID for the case where the JSON path is found, # but applications are not listed in JSON file (Default: OTHE) AndroidLogdContextID = OTHE dlt-daemon-2.18.10/tests/component/dlt-logd-converter/dlt-logdctxt.json000066400000000000000000000004611446635226000261030ustar00rootroot00000000000000{ "QTIV": { "tag": "QtiVehicleHal", "description": "" }, "NETW": { "tag": "NetworkSecurityConfig", "description": "" }, "PROC": { "tag": "ProcessState", "description": "" }, "ZYGO": { "tag": "Zygote", "description": "" } } dlt-daemon-2.18.10/tests/component/dlt-logd-converter/gtest_dlt_logd_converter.cpp000066400000000000000000000602561446635226000304000ustar00rootroot00000000000000/** * Copyright (C) 2019-2022 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * dlt-logd-converter : Retrieve log entries from logd and forward them to DLT. * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * \Author Luu Quang Minh ADIT 2022 * * \file: gtest_dlt_logd_converter.cpp * For further information see http://www.covesa.org/. **/ /******************************************************************************* ** ** ** SRC-MODULE: gtest_dlt_logd_converter.cpp ** ** ** ** TARGET : ANDROID ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Minh.LuuQuang@vn.bosch.com ** ** ** ** PURPOSE : Retrieve log entries from logd and forward them to DLT. ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ #include "gtest/gtest.h" #include "dlt-logd-converter.hpp" /* MACRO */ #undef CONFIGURATION_FILE_DIR #undef JSON_FILE_DIR #define CONFIGURATION_FILE_DIR "dlt-logd-converter.conf" #define JSON_FILE_DIR "dlt-logdctxt.json" #define ABNORMAL_CONFIGURATION_FILE_DIR "abnormal-dlt-logd-converter.conf" extern dlt_logd_configuration *logd_conf; extern unordered_map map_ctx_json; extern bool json_is_available; extern volatile sig_atomic_t exit_parser_loop; DLT_IMPORT_CONTEXT(dlt_ctx_self); DLT_IMPORT_CONTEXT(dlt_ctx_main); DLT_IMPORT_CONTEXT(dlt_ctx_rdio); DLT_IMPORT_CONTEXT(dlt_ctx_evnt); DLT_IMPORT_CONTEXT(dlt_ctx_syst); DLT_IMPORT_CONTEXT(dlt_ctx_crsh); DLT_IMPORT_CONTEXT(dlt_ctx_stat); DLT_IMPORT_CONTEXT(dlt_ctx_secu); DLT_IMPORT_CONTEXT(dlt_ctx_krnl); DLT_IMPORT_CONTEXT(dlt_ctx_othe); struct logger_list *t_logger_list = nullptr; struct dlt_log_container *dlt_log_data = nullptr; struct log_msg t_log_msg; string t_load_json_file() { ifstream file(JSON_FILE_DIR); char *token; string pattern; string json_sequence; file.is_open(); while (!file.eof()) { getline(file, pattern); if (pattern.size() == 0) { continue; } if (pattern[0] != '#') { token = strtok(&pattern[0], " {\":,}"); while( token != NULL ) { if(strcmp(token, "tag") != 0 && strcmp(token, "description") != 0) { json_sequence = json_sequence + strdup(token) + " "; } else { if(pattern.find("\"\"") != string::npos) { json_sequence = json_sequence + strdup("null") + " "; } } token = strtok(NULL, " {\":,}"); } } } file.close(); return json_sequence; } struct logger *t_android_logger_open(struct logger_list *logger_list, log_id_t log_id) { if (logger_list ==nullptr || (log_id >= LOG_ID_MAX)) { return nullptr; } logger_list->log_mask |= 1 << log_id; uintptr_t t_logger = log_id | LOGGER_LOGD; return reinterpret_cast(t_logger); } struct logger_list *t_android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) { t_logger_list = new logger_list; t_logger_list->mode = mode; t_logger_list->tail = tail; t_logger_list->pid = pid; t_logger_list->log_mask = 0; return t_logger_list; } int t_android_logger_list_read(logger_list *logger_list, struct log_msg *t_log_msg) { if (!t_log_msg->entry.len) { t_log_msg->entry.len = LOGGER_ENTRY_MAX_LEN; } if (!t_log_msg->entry.hdr_size) { t_log_msg->entry.hdr_size = 100; } if (!t_log_msg->entry.sec) { t_log_msg->entry.sec = 1/10000; } if (!t_log_msg->entry.nsec) { t_log_msg->entry.nsec = 100000; } if (!t_log_msg->entry.lid) { t_log_msg->entry.lid = LOG_ID_MAIN; } if (!t_log_msg->buf[t_log_msg->entry.hdr_size]) { t_log_msg->buf[t_log_msg->entry.hdr_size] = (unsigned char)ANDROID_LOG_INFO; } if (logger_list->signal == -EINVAL) { return -EINVAL; } if (logger_list->signal == -EAGAIN) { return -EAGAIN; } if (logger_list->signal == -EINTR) { return -EINTR; } if (logger_list->signal == -ENOMEM) { return -ENOMEM; } if (logger_list->signal == -ENODEV) { return -ENODEV; } if (logger_list->signal == -EIO) { return -EIO; } return logger_list->signal; } TEST(t_usage, normal) { char version[255]; dlt_get_version(version, 255); stringstream buffer; streambuf *prev_cout_buf = cout.rdbuf(buffer.rdbuf()); usage(strdup("dlt-logd-converter")); EXPECT_NE(buffer.str().find("Usage: dlt-logd-converter [-h] [-c FILENAME]"), string::npos); EXPECT_NE(buffer.str().find("Application to manage Android logs."), string::npos); EXPECT_NE(buffer.str().find("Format and forward Android messages from ANDROID to DLT."), string::npos); EXPECT_NE(buffer.str().find(string(version)), string::npos); EXPECT_NE(buffer.str().find("Options:"), string::npos); EXPECT_NE(buffer.str().find(" -h Display a short help text."), string::npos); EXPECT_NE(buffer.str().find(" -c filename Use an alternative configuration file."), string::npos); EXPECT_NE(buffer.str().find(" Default: "), string::npos); EXPECT_NE(buffer.str().find("/vendor/etc/dlt-logd-converter.conf"), string::npos); cout.rdbuf(prev_cout_buf); } TEST(t_init_configuration, normal) { int ret = init_configuration(); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_STREQ("LOGD", logd_conf->appID); EXPECT_STREQ("LOGF", logd_conf->ctxID); EXPECT_STREQ("/vendor/etc/dlt-logdctxt.json", logd_conf->json_file_dir); EXPECT_STREQ("OTHE", logd_conf->default_ctxID); EXPECT_STREQ("/vendor/etc/dlt-logd-converter.conf", logd_conf->conf_file_dir); } TEST(t_read_command_line, normal) { char *arg[2]; arg[0] = strdup("dlt-logd-converter"); arg[1] = strdup("h"); EXPECT_EQ(DLT_RETURN_OK, read_command_line(2, arg)); char *t_arg[3]; t_arg[0] = strdup("dlt-logd-converter"); t_arg[1] = strdup("c"); t_arg[2] = strdup("custom.conf"); EXPECT_EQ(DLT_RETURN_OK, read_command_line(3, t_arg)); } TEST(t_load_configuration_file, normal) { logd_conf->appID = strdup("LOGD"); logd_conf->ctxID = strdup("LOGF"); logd_conf->json_file_dir = strdup(JSON_FILE_DIR); logd_conf->default_ctxID = strdup("OTHE"); logd_conf->conf_file_dir = strdup(CONFIGURATION_FILE_DIR); int ret = load_configuration_file(CONFIGURATION_FILE_DIR); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_STREQ("LOGD", logd_conf->appID); EXPECT_STREQ("LOGF", logd_conf->ctxID); EXPECT_STREQ("/vendor/etc/dlt-logdctxt.json", logd_conf->json_file_dir); EXPECT_STREQ("OTHE", logd_conf->default_ctxID); } TEST(t_load_configuration_file, abnormal) { logd_conf->appID = strdup("LOGD"); logd_conf->ctxID = strdup("LOGF"); logd_conf->json_file_dir = strdup(JSON_FILE_DIR); logd_conf->default_ctxID = strdup("OTHE"); logd_conf->conf_file_dir = strdup(CONFIGURATION_FILE_DIR); int ret = load_configuration_file(ABNORMAL_CONFIGURATION_FILE_DIR); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_STREQ("DLOG", logd_conf->appID); EXPECT_STREQ("DLT", logd_conf->ctxID); EXPECT_STREQ("dlt-logdctxt.json", logd_conf->json_file_dir); EXPECT_STREQ("OTHE", logd_conf->default_ctxID); } TEST(t_load_configuration_file, nullpointer) { EXPECT_EQ(DLT_RETURN_ERROR, load_configuration_file(nullptr)); } TEST(t_clean_mem, normal) { logd_conf->appID = strdup("LOGD"); logd_conf->ctxID = strdup("LOGF"); logd_conf->json_file_dir = strdup(JSON_FILE_DIR); logd_conf->default_ctxID = strdup("OTHE"); logd_conf->conf_file_dir = strdup(CONFIGURATION_FILE_DIR); json_is_available = true; string json_ctxID; string json_tag; string json_description; string str = t_load_json_file(); char *token = strtok(&str[0], " "); while(token != nullptr) { json_ctxID = string(token); token = strtok(nullptr, " "); json_tag = string(token); token = strtok(nullptr, " "); json_description = string(token); if (json_description == "null") { json_description = ""; } token = strtok(nullptr, " "); DltContext *ctx = new DltContext(); auto ret = map_ctx_json.emplace(json_tag, ctx); if (!ret.second) { delete ctx; ctx = nullptr; } } clean_mem(); EXPECT_TRUE(logd_conf == nullptr); EXPECT_TRUE(map_ctx_json.find("QtiVehicleHal") == map_ctx_json.end()); EXPECT_TRUE(map_ctx_json.find("NetworkSecurityConfig") == map_ctx_json.end()); EXPECT_TRUE(map_ctx_json.find("ProcessState") == map_ctx_json.end()); EXPECT_TRUE(map_ctx_json.find("Zygote") == map_ctx_json.end()); } TEST(t_json_parser, normal) { EXPECT_EQ(DLT_RETURN_OK, system("dlt-daemon -d > /dev/null")); EXPECT_EQ(DLT_RETURN_OK, system("sleep 0.2")); DLT_REGISTER_APP("LOGD", "logd -> dlt adapter"); DLT_REGISTER_CONTEXT(dlt_ctx_self, "LOGF", "logd retriever"); json_is_available = true; json_parser(); EXPECT_TRUE(map_ctx_json.find("QtiVehicleHal") != map_ctx_json.end()); EXPECT_TRUE(map_ctx_json.find("NetworkSecurityConfig") != map_ctx_json.end()); EXPECT_TRUE(map_ctx_json.find("ProcessState") != map_ctx_json.end()); EXPECT_TRUE(map_ctx_json.find("Zygote") != map_ctx_json.end()); DLT_UNREGISTER_CONTEXT(dlt_ctx_self); for (auto &map_malloc: map_ctx_json) { DLT_UNREGISTER_CONTEXT(*(map_malloc.second)); delete map_malloc.second; map_malloc.second = nullptr; } map_ctx_json.clear(); DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); EXPECT_LT(DLT_RETURN_OK, system("kill -9 $(pgrep -f \"dlt-daemon -d\") > /dev/null")); } TEST(t_find_tag_in_json, normal) { EXPECT_EQ(DLT_RETURN_OK, system("dlt-daemon -d > /dev/null")); EXPECT_EQ(DLT_RETURN_OK, system("sleep 0.2")); string json_ctxID; string json_tag; string json_description; string str = t_load_json_file(); char *token = strtok(&str[0], " "); while(token != nullptr) { json_ctxID = string(token); token = strtok(nullptr, " "); json_tag = string(token); token = strtok(nullptr, " "); json_description = string(token); if (json_description == "null") { json_description = ""; } token = strtok(nullptr, " "); DltContext *ctx = new DltContext(); auto ret = map_ctx_json.emplace(json_tag, ctx); if (!ret.second) { delete ctx; ctx = nullptr; } } EXPECT_EQ(find_tag_in_json("QtiVehicleHal"), (map_ctx_json.find("QtiVehicleHal")->second)); EXPECT_EQ(find_tag_in_json("NetworkSecurityConfig"), (map_ctx_json.find("NetworkSecurityConfig")->second)); EXPECT_EQ(find_tag_in_json("ProcessState"), (map_ctx_json.find("ProcessState")->second)); EXPECT_EQ(find_tag_in_json("Zygote"), (map_ctx_json.find("Zygote")->second)); EXPECT_EQ(find_tag_in_json("Other tags"), &(dlt_ctx_othe)); for (auto &map_malloc: map_ctx_json) { delete map_malloc.second; map_malloc.second = nullptr; } map_ctx_json.clear(); EXPECT_LT(DLT_RETURN_OK, system("kill -9 $(pgrep -f \"dlt-daemon -d\") > /dev/null")); } TEST(t_find_tag_in_json, nullpointer) { (void)(::testing::GTEST_FLAG(death_test_style) = "threadsafe"); ASSERT_ANY_THROW(find_tag_in_json(nullptr)); } TEST(t_init_logger, normal) { t_logger_list = new logger_list; t_logger_list->mode = READ_ONLY; t_logger_list->tail = 0; t_logger_list->pid = 0; struct logger *logger_ptr = reinterpret_cast(LOG_ID_MAIN | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_MAIN)); logger_ptr = reinterpret_cast(LOG_ID_RADIO | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_RADIO)); logger_ptr = reinterpret_cast(LOG_ID_EVENTS | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_EVENTS)); logger_ptr = reinterpret_cast(LOG_ID_SYSTEM | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_SYSTEM)); logger_ptr = reinterpret_cast(LOG_ID_CRASH | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_CRASH)); logger_ptr = reinterpret_cast(LOG_ID_STATS | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_STATS)); logger_ptr = reinterpret_cast(LOG_ID_SECURITY | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_SECURITY)); logger_ptr = reinterpret_cast(LOG_ID_KERNEL | LOGGER_LOGD); EXPECT_EQ(logger_ptr, init_logger(t_logger_list, LOG_ID_KERNEL)); delete t_logger_list; t_logger_list = nullptr; } TEST(t_init_logger, nullpointer) { EXPECT_EQ(nullptr, t_logger_list); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_MAIN)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_RADIO)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_EVENTS)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_SYSTEM)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_CRASH)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_STATS)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_SECURITY)); EXPECT_EQ(nullptr, init_logger(t_logger_list, LOG_ID_KERNEL)); } TEST(t_init_logger_list, normal) { EXPECT_EQ(0x009B, (init_logger_list(true)->log_mask) & 0x00FF); EXPECT_EQ(0x00FF, (init_logger_list(false)->log_mask) & 0x00FF); delete t_logger_list; t_logger_list = nullptr; } TEST(t_get_log_context_from_log_msg, normal) { struct log_msg *t_log_msg = nullptr; t_log_msg = new log_msg; t_log_msg->entry.lid = LOG_ID_MAIN; EXPECT_EQ(&dlt_ctx_main, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_RADIO; EXPECT_EQ(&dlt_ctx_rdio, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_EVENTS; EXPECT_EQ(&dlt_ctx_evnt, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_SYSTEM; EXPECT_EQ(&dlt_ctx_syst, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_CRASH; EXPECT_EQ(&dlt_ctx_crsh, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_STATS; EXPECT_EQ(&dlt_ctx_stat, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_SECURITY; EXPECT_EQ(&dlt_ctx_secu, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = LOG_ID_KERNEL; EXPECT_EQ(&dlt_ctx_krnl, get_log_context_from_log_msg(t_log_msg)); t_log_msg->entry.lid = 1024; EXPECT_EQ(&dlt_ctx_self, get_log_context_from_log_msg(t_log_msg)); delete t_log_msg; t_log_msg = nullptr; } TEST(t_get_log_context_from_log_msg, nullpointer) { struct log_msg *t_log_msg = nullptr; EXPECT_EQ(&dlt_ctx_self, get_log_context_from_log_msg(t_log_msg)); } TEST(t_get_timestamp_from_log_msg, normal) { struct log_msg *t_log_msg = nullptr; t_log_msg = new log_msg; t_log_msg->entry.sec = 0; t_log_msg->entry.nsec = 0; EXPECT_EQ(0, get_timestamp_from_log_msg(t_log_msg)); t_log_msg->entry.sec = 1/10000; t_log_msg->entry.nsec = 100000; EXPECT_EQ(1, get_timestamp_from_log_msg(t_log_msg)); t_log_msg->entry.sec = 100; t_log_msg->entry.nsec = 1000000; EXPECT_EQ(1000010, get_timestamp_from_log_msg(t_log_msg)); } TEST(t_get_timestamp_from_log_msg, nullpointer) { struct log_msg *t_log_msg = nullptr; EXPECT_EQ(DLT_FAIL_TO_GET_LOG_MSG, get_timestamp_from_log_msg(t_log_msg)); } TEST(t_get_log_level_from_log_msg, normal) { struct log_msg *t_log_msg = nullptr; t_log_msg = new log_msg; t_log_msg->entry.hdr_size = 0; t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_VERBOSE; EXPECT_EQ(DLT_LOG_VERBOSE, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_DEBUG; EXPECT_EQ(DLT_LOG_DEBUG, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_INFO; EXPECT_EQ(DLT_LOG_INFO, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_WARN; EXPECT_EQ(DLT_LOG_WARN, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_ERROR; EXPECT_EQ(DLT_LOG_ERROR, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_FATAL; EXPECT_EQ(DLT_LOG_FATAL, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_SILENT; EXPECT_EQ(DLT_LOG_OFF, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_UNKNOWN; EXPECT_EQ(DLT_LOG_DEFAULT, get_log_level_from_log_msg(t_log_msg)); t_log_msg->buf[0] = (unsigned char)ANDROID_LOG_DEFAULT; EXPECT_EQ(DLT_LOG_DEFAULT, get_log_level_from_log_msg(t_log_msg)); delete t_log_msg; t_log_msg = nullptr; } TEST(t_get_log_level_from_log_msg, nullpointer) { struct log_msg *t_log_msg = nullptr; EXPECT_EQ(DLT_LOG_DEFAULT, get_log_level_from_log_msg(t_log_msg)); } TEST(t_signal_handler, normal) { exit_parser_loop = false; signal_handler(SIGTERM); EXPECT_TRUE(exit_parser_loop == true); exit_parser_loop = false; signal_handler(SIGSEGV); EXPECT_TRUE(exit_parser_loop == false); } TEST(t_logd_parser_loop, normal) { EXPECT_EQ(DLT_RETURN_OK, system("dlt-daemon -d > /dev/null")); EXPECT_EQ(DLT_RETURN_OK, system("sleep 0.2")); struct logger_list *t_list = nullptr; t_list = new logger_list; t_list->mode = READ_ONLY; t_list->tail = 0; t_list->pid = 0; t_list->signal = -EINVAL; EXPECT_TRUE(logd_parser_loop(t_list) == -EINVAL); t_list->signal = -EAGAIN; EXPECT_TRUE(logd_parser_loop(t_list) == -EAGAIN); t_list->signal = -EINTR; EXPECT_TRUE(logd_parser_loop(t_list) == -EINTR); t_list->signal = -ENOMEM; EXPECT_TRUE(logd_parser_loop(t_list) == -ENOMEM); t_list->signal = -ENODEV; EXPECT_TRUE(logd_parser_loop(t_list) == -ENODEV); t_list->signal = -EIO; EXPECT_TRUE(logd_parser_loop(t_list) == -EIO); delete t_list; t_list = nullptr; t_logger_list = new logger_list; t_logger_list->mode = READ_ONLY; t_logger_list->tail = 0; t_logger_list->pid = 0; t_logger_list->signal = 0; json_is_available = true; string json_ctxID; string json_tag; string json_description; string str = t_load_json_file(); char *token = strtok(&str[0], " "); while(token != nullptr) { json_ctxID = string(token); token = strtok(nullptr, " "); json_tag = string(token); token = strtok(nullptr, " "); json_description = string(token); if (json_description == "null") { json_description = ""; } token = strtok(nullptr, " "); DltContext *ctx = new DltContext(); auto ret = map_ctx_json.emplace(json_tag, ctx); if (!ret.second) { delete ctx; ctx = nullptr; } } dlt_log_data = new dlt_log_container; json_is_available = true; /* TEST with available tag in JSON file */ unsigned char tag[sizeof("QtiVehicleHal")] = "QtiVehicleHal"; unsigned char message[sizeof("dlt-logd-converter")] = "dlt-logd-converter"; for (uint idx = 0; idx < sizeof(tag); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + 1] = tag[idx]; } for (uint idx = 0; idx < sizeof(message); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + sizeof(tag) + 1] = message[idx]; } auto search = map_ctx_json.find("QtiVehicleHal"); int ret = logd_parser_loop(t_logger_list); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(search->second, dlt_log_data->ctx); EXPECT_EQ(DLT_LOG_INFO, dlt_log_data->log_level); EXPECT_EQ(1, dlt_log_data->ts); EXPECT_STREQ("QtiVehicleHal", dlt_log_data->tag); EXPECT_STREQ("dlt-logd-converter", dlt_log_data->message); /* TEST with other tags not listed JSON file */ unsigned char othe_tag[sizeof("OtherTags")] = "OtherTags"; unsigned char othe_message[sizeof("No tag found")] = "No tag found"; for (uint idx = 0; idx < sizeof(othe_tag); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + 1] = othe_tag[idx]; } for (uint idx = 0; idx < sizeof(othe_message); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + sizeof(othe_tag) + 1] = othe_message[idx]; } search = map_ctx_json.find("OtherTags"); ret = logd_parser_loop(t_logger_list); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(&(dlt_ctx_othe), dlt_log_data->ctx); EXPECT_EQ(DLT_LOG_INFO, dlt_log_data->log_level); EXPECT_EQ(1, dlt_log_data->ts); EXPECT_STREQ("OtherTags", dlt_log_data->tag); EXPECT_STREQ("No tag found", dlt_log_data->message); /* TEST with another buffer */ t_log_msg.entry.lid = LOG_ID_RADIO; unsigned char radio_tag[sizeof("RadioTag")] = "RadioTag"; unsigned char radio_message[sizeof("It is from radio buffer")] = "It is from radio buffer"; for (uint idx = 0; idx < sizeof(radio_tag); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + 1] = radio_tag[idx]; } for (uint idx = 0; idx < sizeof(radio_message); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + sizeof(radio_tag) + 1] = radio_message[idx]; } ret = logd_parser_loop(t_logger_list); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(&(dlt_ctx_rdio), dlt_log_data->ctx); EXPECT_EQ(DLT_LOG_INFO, dlt_log_data->log_level); EXPECT_EQ(1, dlt_log_data->ts); EXPECT_STREQ("RadioTag", dlt_log_data->tag); EXPECT_STREQ("It is from radio buffer", dlt_log_data->message); /* TEST with no JSON file */ t_log_msg.entry.lid = LOG_ID_KERNEL; json_is_available = false; unsigned char no_json_tag[sizeof("Kernel")] = "Kernel"; unsigned char no_json_message[sizeof("It is from kernel")] = "It is from kernel"; for (uint idx = 0; idx < sizeof(no_json_tag); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + 1] = no_json_tag[idx]; } for (uint idx = 0; idx < sizeof(no_json_message); idx++) { t_log_msg.buf[idx + t_log_msg.entry.hdr_size + sizeof(no_json_tag) + 1] = no_json_message[idx]; } ret = logd_parser_loop(t_logger_list); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(&(dlt_ctx_krnl), dlt_log_data->ctx); EXPECT_EQ(DLT_LOG_INFO, dlt_log_data->log_level); EXPECT_EQ(1, dlt_log_data->ts); EXPECT_STREQ("Kernel", dlt_log_data->tag); EXPECT_STREQ("It is from kernel", dlt_log_data->message); delete dlt_log_data; dlt_log_data = nullptr; delete t_logger_list; t_logger_list = nullptr; EXPECT_LT(DLT_RETURN_OK, system("kill -9 $(pgrep -f \"dlt-daemon -d\") > /dev/null")); } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/dlt_env_ll_unit_test.cpp000066400000000000000000000413371446635226000220150ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2015 Intel Corporation * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Stefan Vacek Intel Corporation * * \copyright Copyright © 2015 Intel Corporation. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_env_ll_unit_test.cpp */ #include "gtest/gtest.h" #include "dlt_user.h" #include "dlt_common.h" /* needed for dlt_set_id */ /* simply include the whole file to allow testing it */ #include "src/lib/dlt_env_ll.c" int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } TEST(DltExtensionTests, extract_id) { /* testing valid input */ char id[4u]; char env0[] = "abcd:1234:3"; char *tmp = &env0[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), 0); ASSERT_EQ(tmp - &env0[0], 4); /* moved 4 bytes */ ASSERT_EQ(id[0], 'a'); ASSERT_EQ(id[1], 'b'); ASSERT_EQ(id[2], 'c'); ASSERT_EQ(id[3], 'd'); char env1[] = "abc:1234:3"; tmp = &env1[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), 0); ASSERT_EQ(tmp - &env1[0], 3); /* moved 3 bytes */ ASSERT_EQ(id[0], 'a'); ASSERT_EQ(id[1], 'b'); ASSERT_EQ(id[2], 'c'); ASSERT_EQ(id[3], 0); char env2[] = "ab:1234:3"; tmp = &env2[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), 0); ASSERT_EQ(tmp - &env2[0], 2); /* moved 2 bytes */ ASSERT_EQ(id[0], 'a'); ASSERT_EQ(id[1], 'b'); ASSERT_EQ(id[2], 0); ASSERT_EQ(id[3], 0); char env3[] = "a:1234:3"; tmp = &env3[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), 0); ASSERT_EQ(tmp - &env3[0], 1); /* moved 1 byte */ ASSERT_EQ(id[0], 'a'); ASSERT_EQ(id[1], 0); ASSERT_EQ(id[2], 0); ASSERT_EQ(id[3], 0); char env4[] = ":1234:3"; tmp = &env4[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), 0); ASSERT_EQ(tmp - &env4[0], 0); /* moved 1 byte */ ASSERT_EQ(id[0], 0); ASSERT_EQ(id[1], 0); ASSERT_EQ(id[2], 0); ASSERT_EQ(id[3], 0); char env5[] = "abcd:1234:3;"; tmp = &env5[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), 0); ASSERT_EQ(tmp - &env5[0], 4); /* moved 4 bytes */ ASSERT_EQ(id[0], 'a'); ASSERT_EQ(id[1], 'b'); ASSERT_EQ(id[2], 'c'); ASSERT_EQ(id[3], 'd'); /* testing invalid input */ /* - string too long: abcde: * - string too short/missing end: abc * - NULL string: */ tmp = NULL; ASSERT_EQ(dlt_env_extract_id(&tmp, id), -1); char env6[] = "abcd:1234:3"; tmp = &env6[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, NULL), -1); char invalid0[] = ""; tmp = &invalid0[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), -1); char invalid1[] = "abcd"; /* missing delimiter */ tmp = &invalid1[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), -1); char invalid2[] = "abcde"; /* id too long */ tmp = &invalid2[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, id), -1); } TEST(DltExtensionTests, extract_ll) { /* testing valid input */ int8_t ll; char env_1[] = "-1"; char *tmp = &env_1[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env_1[0], 2); /* moved 2 bytes */ ASSERT_EQ(ll, -1); char env0[] = "0;"; tmp = &env0[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env0[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 0); char env1[] = "1;"; tmp = &env1[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env1[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 1); char env2[] = "2;"; tmp = &env2[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env2[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 2); char env3[] = "3;"; tmp = &env3[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env3[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 3); char env4[] = "4;"; tmp = &env4[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env4[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 4); char env5[] = "5;"; tmp = &env5[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env5[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 5); char env6[] = "6;"; tmp = &env6[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), 0); ASSERT_EQ(tmp - &env6[0], 1); /* moved 1 byte */ ASSERT_EQ(ll, 6); /* testing invalid input */ /* - number outside range, e.g. -2, 103 * - missing delimiter * - NULL string: */ tmp = NULL; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), -1); char env7[] = "abcd:1234:3"; tmp = &env7[0]; ASSERT_EQ(dlt_env_extract_id(&tmp, NULL), -1); char invalid0[] = ""; tmp = &invalid0[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), -1); char invalid1[] = "-2"; /* outside range */ tmp = &invalid1[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), -1); char invalid2[] = "8"; /* outside range */ tmp = &invalid2[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), -1); char invalid3[] = "1e"; /* missing delimiter */ tmp = &invalid3[0]; ASSERT_EQ(dlt_env_extract_ll(&tmp, &ll), -1); } TEST(DltExtensionTests, extract_ll_item) { /* testing valid input */ dlt_env_ll_item item; char env0[] = "abcd:1234:3"; char *tmp = &env0[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), 0); ASSERT_EQ(tmp - &env0[0], 11); /* moved 11 bytes */ ASSERT_EQ(item.appId[0], 'a'); ASSERT_EQ(item.appId[1], 'b'); ASSERT_EQ(item.appId[2], 'c'); ASSERT_EQ(item.appId[3], 'd'); ASSERT_EQ(item.ctxId[0], '1'); ASSERT_EQ(item.ctxId[1], '2'); ASSERT_EQ(item.ctxId[2], '3'); ASSERT_EQ(item.ctxId[3], '4'); ASSERT_EQ(item.ll, 3); char env1[] = "::-1;"; tmp = &env1[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), 0); ASSERT_EQ(tmp - &env1[0], 4); /* moved 4 bytes */ ASSERT_EQ(item.appId[0], 0); ASSERT_EQ(item.appId[1], 0); ASSERT_EQ(item.appId[2], 0); ASSERT_EQ(item.appId[3], 0); ASSERT_EQ(item.ctxId[0], 0); ASSERT_EQ(item.ctxId[1], 0); ASSERT_EQ(item.ctxId[2], 0); ASSERT_EQ(item.ctxId[3], 0); ASSERT_EQ(item.ll, -1); /* testing invalid input */ /* - string too long: abcde: * - string too short/missing end: abc * - NULL string: */ tmp = NULL; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), -1); char env2[] = "abcd:1234:3"; tmp = &env2[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, NULL), -1); char invalid0[] = ""; tmp = &invalid0[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), -1); char invalid1[] = "abcd:1234:"; /* missing ll */ tmp = &invalid1[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), -1); char invalid2[] = "abcd:1234"; /* missing ll, missing delimiter in ctxId */ tmp = &invalid2[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), -1); char invalid3[] = "abcd:"; /* missing ll, missing delimiter in appId */ tmp = &invalid3[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), -1); char invalid4[] = "abcd"; /* missing ll, missing delimiter in appId */ tmp = &invalid4[0]; ASSERT_EQ(dlt_env_extract_ll_item(&tmp, &item), -1); } TEST(DltExtensionTests, basic_ll_set_handling) { dlt_env_init_ll_set(NULL); /* must not crash */ dlt_env_free_ll_set(NULL); /* must not crash */ dlt_env_increase_ll_set(NULL); /* must not crash */ dlt_env_ll_set ll_set; dlt_env_init_ll_set(&ll_set); EXPECT_TRUE(NULL != ll_set.item); EXPECT_EQ(DLT_ENV_LL_SET_INCREASE, ll_set.array_size); EXPECT_EQ(0, ll_set.num_elem); dlt_env_free_ll_set(&ll_set); EXPECT_TRUE(NULL == ll_set.item); EXPECT_EQ(0, ll_set.array_size); EXPECT_EQ(0, ll_set.num_elem); dlt_env_init_ll_set(&ll_set); for (int i = 0; i < DLT_ENV_LL_SET_INCREASE; ++i) ll_set.item[i].ll = i; dlt_env_increase_ll_set(&ll_set); EXPECT_EQ(2 * DLT_ENV_LL_SET_INCREASE, ll_set.array_size); for (int i = 0; i < DLT_ENV_LL_SET_INCREASE; ++i) EXPECT_EQ(ll_set.item[i].ll, i); dlt_env_free_ll_set(&ll_set); EXPECT_TRUE(NULL == ll_set.item); EXPECT_EQ(0, ll_set.array_size); EXPECT_EQ(0, ll_set.num_elem); } TEST(DltExtensionTests, extract_ll_set) { /* testing valid input */ dlt_env_ll_set ll_set; char env0[] = "abcd:1234:3"; char *tmp = &env0[0]; ASSERT_EQ(dlt_env_extract_ll_set(&tmp, &ll_set), 0); EXPECT_EQ(ll_set.array_size, DLT_ENV_LL_SET_INCREASE); EXPECT_EQ(ll_set.num_elem, 1); EXPECT_EQ(ll_set.item[0].ll, 3); dlt_env_free_ll_set(&ll_set); /* force increasing the list */ char env1[] = "abcd:0000:3;abcd:0001:3;abcd:0002:3;abcd:0003:3;abcd:0004:3;abcd:0005:3;abcd:0006:3;abcd:0007:3;abcd:0008:3;abcd:0009:3;abcd:0010:3"; tmp = &env1[0]; ASSERT_EQ(dlt_env_extract_ll_set(&tmp, &ll_set), 0); EXPECT_EQ(ll_set.array_size, 2 * DLT_ENV_LL_SET_INCREASE); EXPECT_EQ(ll_set.num_elem, 11); for (size_t i = 0; i < ll_set.num_elem; ++i) EXPECT_EQ(ll_set.item[i].ctxId[3], i % 10 + '0'); dlt_env_free_ll_set(&ll_set); char env2[] = "SINA:SINC:FATAL"; tmp = &env2[0]; ASSERT_EQ(dlt_env_extract_ll_set(&tmp, &ll_set), 0); EXPECT_EQ(ll_set.array_size, DLT_ENV_LL_SET_INCREASE); EXPECT_EQ(ll_set.num_elem, 1); EXPECT_EQ(ll_set.item[0].ll, 1); dlt_env_free_ll_set(&ll_set); } TEST(DltExtensionTests, ids_match) { ASSERT_EQ(1, dlt_env_ids_match("abcd", "abcd")); ASSERT_EQ(0, dlt_env_ids_match("abcd", "abce")); ASSERT_EQ(0, dlt_env_ids_match("abcd", "abee")); ASSERT_EQ(0, dlt_env_ids_match("abcd", "aeee")); ASSERT_EQ(0, dlt_env_ids_match("abcd", "eeee")); ASSERT_TRUE(dlt_env_ids_match("abcd", "abcd")); ASSERT_FALSE(dlt_env_ids_match("abcd", "abce")); } TEST(DltExtensionTests, get_matching_prio) { char apid[5] = "ABCD"; char ctid[5] = "1234"; dlt_env_ll_item test0; dlt_set_id(test0.appId, ""); dlt_set_id(test0.ctxId, ""); ASSERT_EQ(1, dlt_env_ll_item_get_matching_prio(&test0, apid, ctid)); dlt_set_id(test0.appId, ""); dlt_set_id(test0.ctxId, ctid); ASSERT_EQ(2, dlt_env_ll_item_get_matching_prio(&test0, apid, ctid)); dlt_set_id(test0.appId, apid); dlt_set_id(test0.ctxId, ""); ASSERT_EQ(3, dlt_env_ll_item_get_matching_prio(&test0, apid, ctid)); dlt_set_id(test0.appId, apid); dlt_set_id(test0.ctxId, ctid); ASSERT_EQ(4, dlt_env_ll_item_get_matching_prio(&test0, apid, ctid)); dlt_set_id(test0.appId, "EFGH"); /* appId should not match */ dlt_set_id(test0.ctxId, ctid); ASSERT_EQ(0, dlt_env_ll_item_get_matching_prio(&test0, apid, ctid)); ASSERT_EQ(-1, dlt_env_ll_item_get_matching_prio(NULL, apid, ctid)); ASSERT_EQ(-1, dlt_env_ll_item_get_matching_prio(&test0, NULL, ctid)); ASSERT_EQ(-1, dlt_env_ll_item_get_matching_prio(&test0, apid, NULL)); } TEST(DltExtensionTests, adjust_ll_from_env) { char apid[5] = "ABCD"; char ctid[5] = "1234"; int ll = 42; /* unrealistic value to see that the ll was not touched */ dlt_env_ll_set ll_set; dlt_env_init_ll_set(&ll_set); EXPECT_EQ(ll, dlt_env_adjust_ll_from_env(NULL, apid, ctid, ll)); /* orig value in case of error */ EXPECT_EQ(ll, dlt_env_adjust_ll_from_env(&ll_set, NULL, ctid, ll)); /* orig value in case of error */ EXPECT_EQ(ll, dlt_env_adjust_ll_from_env(&ll_set, apid, NULL, ll)); /* orig value in case of error */ EXPECT_EQ(ll, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); /* an empty set should not match anything */ dlt_set_id(ll_set.item[0].appId, "DEAD"); /* not matching */ dlt_set_id(ll_set.item[0].ctxId, "BEEF"); ll_set.item[0].ll = 0; ll_set.num_elem = 1; EXPECT_EQ(ll, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); /* not matching anything */ dlt_set_id(ll_set.item[1].appId, ""); /* empty rule, weakest */ dlt_set_id(ll_set.item[1].ctxId, ""); ll_set.item[1].ll = 1; ll_set.num_elem = 2; EXPECT_EQ(1, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); dlt_set_id(ll_set.item[2].appId, ""); /* prio 2 */ dlt_set_id(ll_set.item[2].ctxId, ctid); ll_set.item[2].ll = 2; ll_set.num_elem = 3; EXPECT_EQ(2, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); dlt_set_id(ll_set.item[3].appId, apid); /* prio 3 */ dlt_set_id(ll_set.item[3].ctxId, ""); ll_set.item[3].ll = 3; ll_set.num_elem = 4; EXPECT_EQ(3, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); dlt_set_id(ll_set.item[4].appId, apid); /* prio 4 */ dlt_set_id(ll_set.item[4].ctxId, ctid); ll_set.item[4].ll = 4; ll_set.num_elem = 5; EXPECT_EQ(4, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); dlt_set_id(ll_set.item[5].appId, apid); /* does not matter item[4] will always match */ dlt_set_id(ll_set.item[5].ctxId, ""); ll_set.item[5].ll = 5; ll_set.num_elem = 6; EXPECT_EQ(4, dlt_env_adjust_ll_from_env(&ll_set, apid, ctid, ll)); /* remember, item[4] matches */ dlt_env_free_ll_set(&ll_set); } /* int dlt_env_helper_to_lower(char **env, char *result, int res_len) */ TEST(DltExtensionTests, dlt_env_helper_to_lower) { /* default behavior */ char env0[] = "1238<><<>>>>#$//abcdABCDEDFGHIJKLMNOPQRSTUVWXYZpo;ABcd"; char res0[] = "1238<><<>>>>#$//abcdabcdedfghijklmnopqrstuvwxyzpo"; char *tmp0 = &env0[0]; char result0[sizeof(res0)]; ASSERT_EQ(0, dlt_env_helper_to_lower(&tmp0, result0, sizeof(result0))); ASSERT_EQ(';', *tmp0); /* next char is ';' */ ASSERT_STREQ(res0, result0); /* stops at ';' and is correctly converted */ /* default behavior with end of string */ char env1[] = "1238<><<>>>>#$//abcdABCDEDFGHIJKLMNOPQRSTUVWXYZpo"; char res1[] = "1238<><<>>>>#$//abcdabcdedfghijklmnopqrstuvwxyzpo"; char *tmp1 = &env1[0]; char result1[sizeof(res1)]; ASSERT_EQ(0, dlt_env_helper_to_lower(&tmp1, result1, sizeof(result1))); ASSERT_EQ(0, *tmp1); /* next char is void */ ASSERT_STREQ(res1, result1); /* stops at end-of-string and is correctly converted */ /* result string too short */ char env2[] = "2238<><<>>>>#$//abcdABCDEDFGHIJKLMNOPQRSTUVWXYZpo"; char res2[] = "2238<><<>>>>#$//abcdabcdedfg"; char *tmp2 = &env2[0]; char result2[sizeof(res2)]; ASSERT_EQ(-1, dlt_env_helper_to_lower(&tmp2, result2, sizeof(result2))); ASSERT_EQ('H', *tmp2); /* next char is void */ ASSERT_STREQ(res2, result2); /* stops at end-of-string and is partially converted */ /* input string shorter than result */ char env3[] = "3338<><<>>>>#$//abcdABCDEDFGHIJKLMNOPQRSTUVWXYZpo"; char res3[] = "3338<><<>>>>#$//abcdabcdedfghijklmnopqrstuvwxyzpo"; char *tmp3 = &env3[0]; char result3[sizeof(res3) + 5]; ASSERT_EQ(0, dlt_env_helper_to_lower(&tmp3, result3, sizeof(result3))); ASSERT_EQ(0, *tmp3); /* next char is void */ ASSERT_STREQ(res3, result3); /* stops at end-of-string and is correctly converted */ } /* int dlt_env_extract_symbolic_ll(char **env, int8_t * ll) */ TEST(DltExtensionTests, dlt_env_extract_symbolic_ll) { int8_t result; /* correct behavior */ char env0[] = "DEFAULT;off;fatal;error;warning;info;DeBuG;verbose"; char *tmp0 = &env0[0]; ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('o', *tmp0); ASSERT_EQ(-1, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('f', *tmp0); ASSERT_EQ(0, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('e', *tmp0); ASSERT_EQ(1, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('w', *tmp0); ASSERT_EQ(2, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('i', *tmp0); ASSERT_EQ(3, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('D', *tmp0); ASSERT_EQ(4, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ('v', *tmp0); ASSERT_EQ(5, result); ASSERT_EQ(0, dlt_env_extract_symbolic_ll(&tmp0, &result)); ASSERT_EQ(0, *tmp0); ASSERT_EQ(6, result); /* incorrect behavior */ char env1[] = "DEF"; char *tmp1 = &env1[0]; result = 18; ASSERT_EQ(-1, dlt_env_extract_symbolic_ll(&tmp1, &result)); ASSERT_EQ(0, *tmp1); ASSERT_EQ(18, result); /* 'result' is not touched */ /* incorrect behavior */ char env2[] = "DEFaultingfBa"; char *tmp2 = &env2[0]; result = 28; ASSERT_EQ(-1, dlt_env_extract_symbolic_ll(&tmp2, &result)); ASSERT_EQ('i', *tmp2); ASSERT_EQ(28, result); /* 'result' is not touched */ } dlt-daemon-2.18.10/tests/dlt_test_receiver.c000066400000000000000000000343721446635226000207440ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Alexander Wenzel * Markus Klein * Stefan Held * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_test_receiver.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt-receive.cpp ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** Markus Klein ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** ** mk Markus Klein Fraunhofer ESK ** *******************************************************************************/ /******************************************************************************* ** Revision Control History ** *******************************************************************************/ /* * $LastChangedRevision: 1670 $ * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $ * $LastChangedBy$ * Initials Date Comment * aw 13.01.2010 initial */ #include /* for isprint() */ #include /* for atoi() */ #include /* for S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH */ #include /* for open() */ #include /* for writev() */ #include #include #include "dlt_client.h" #define DLT_RECEIVE_ECU_ID "RECV" /* Function prototypes */ int dlt_receive_filetransfer_callback(DltMessage *message, void *data); typedef struct { int vflag; int yflag; char *ovalue; char *evalue; int bvalue; int filetransfervalue; int systemjournalvalue; int systemloggervalue; char ecuid[4]; int ohandle; int sendSerialHeaderFlag; int resyncSerialHeaderFlag; DltFile file; DltFilter filter; } DltReceiveData; FILE *fp; int result = 0; /** * Print usage information of tool. */ void usage() { char version[255]; dlt_get_version(version, 255); printf("Usage: dlt-receive [options] hostname/serial_device_name\n"); printf("Receive DLT messages from DLT daemon and print or store the messages.\n"); printf("Use filters to filter received messages.\n"); printf("%s \n", version); printf("Options:\n"); printf(" -v Verbose mode\n"); printf(" -h Usage\n"); printf(" -S Send message with serial header (Default: Without serial header)\n"); printf(" -R Enable resync serial header\n"); printf(" -y Serial device mode\n"); printf(" -f Activate filetransfer test case\n"); printf(" -s Activate systemd journal test case\n"); printf(" -l Activate system logger test case"); printf(" -b baudrate Serial device baudrate (Default: 115200)\n"); printf(" -e ecuid Set ECU ID (Default: RECV)\n"); printf(" -o filename Output messages in new DLT file\n"); } /** * Main function of tool. */ int main(int argc, char *argv[]) { DltClient dltclient; DltReceiveData dltdata; int c; int index; /* Initialize dltdata */ dltdata.vflag = 0; dltdata.yflag = 0; dltdata.ovalue = 0; dltdata.evalue = 0; dltdata.bvalue = 0; dltdata.sendSerialHeaderFlag = 0; dltdata.resyncSerialHeaderFlag = 0; dltdata.ohandle = -1; dltdata.filetransfervalue = 0; dltdata.systemjournalvalue = 0; /* Fetch command line arguments */ opterr = 0; while ((c = getopt (argc, argv, "vshSRyfla:o:e:b:")) != -1) switch (c) { case 'v': { dltdata.vflag = 1; break; } case 'h': { usage(); return -1; } case 'S': { dltdata.sendSerialHeaderFlag = 1; break; } case 'R': { dltdata.resyncSerialHeaderFlag = 1; break; } case 'y': { dltdata.yflag = 1; break; } case 'f': { dltdata.filetransfervalue = 1; break; } case 's': { dltdata.systemjournalvalue = 1; break; } case 'l': { dltdata.systemloggervalue = 1; break; } case 'o': { dltdata.ovalue = optarg; break; } case 'e': { dltdata.evalue = optarg; break; } case 'b': { dltdata.bvalue = atoi(optarg); break; } case '?': { if (optopt == 'o') fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); /* unknown or wrong option used, show usage information and terminate */ usage(); return -1; } default: { abort (); return -1; /*for parasoft */ } } /* Initialize DLT Client */ dlt_client_init(&dltclient, dltdata.vflag); /* Register callback to be called when message was received */ dlt_client_register_message_callback(dlt_receive_filetransfer_callback); /* Setup DLT Client structure */ dltclient.mode = dltdata.yflag; if (dltclient.mode == 0) { for (index = optind; index < argc; index++) if (dlt_client_set_server_ip(&dltclient, argv[index]) == -1) { fprintf(stderr, "set server ip didn't succeed\n"); return -1; } if (dltclient.servIP == 0) { /* no hostname selected, show usage and terminate */ fprintf(stderr, "ERROR: No hostname selected\n"); usage(); dlt_client_cleanup(&dltclient, dltdata.vflag); return -1; } } else { for (index = optind; index < argc; index++) if (dlt_client_set_serial_device(&dltclient, argv[index]) == -1) { fprintf(stderr, "set serial device didn't succeed\n"); return -1; } if (dltclient.serialDevice == 0) { /* no serial device name selected, show usage and terminate */ fprintf(stderr, "ERROR: No serial device name specified\n"); usage(); return -1; } dlt_client_setbaudrate(&dltclient, dltdata.bvalue); } /* Update the send and resync serial header flags based on command line option */ dltclient.send_serial_header = dltdata.sendSerialHeaderFlag; dltclient.resync_serial_header = dltdata.resyncSerialHeaderFlag; /* initialise structure to use DLT file */ dlt_file_init(&(dltdata.file), dltdata.vflag); /* first parse filter file if filter parameter is used */ dlt_filter_init(&(dltdata.filter), dltdata.vflag); /* open DLT output file */ if (dltdata.ovalue) { dltdata.ohandle = open(dltdata.ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */ if (dltdata.ohandle == -1) { dlt_file_free(&(dltdata.file), dltdata.vflag); fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", dltdata.ovalue); return -1; } } if (dltdata.evalue) dlt_set_id(dltdata.ecuid, dltdata.evalue); else dlt_set_id(dltdata.ecuid, DLT_RECEIVE_ECU_ID); /* Connect to TCP socket or open serial device */ if (dlt_client_connect(&dltclient, dltdata.vflag) != DLT_RETURN_ERROR) { /* Dlt Client Main Loop */ dlt_client_main_loop(&dltclient, &dltdata, dltdata.vflag); /* Dlt Client Cleanup */ dlt_client_cleanup(&dltclient, dltdata.vflag); } /* dlt-receive cleanup */ if (dltdata.ovalue) close(dltdata.ohandle); dlt_file_free(&(dltdata.file), dltdata.vflag); dlt_filter_free(&(dltdata.filter), dltdata.vflag); return 0; } int dlt_receive_filetransfer_callback(DltMessage *message, void *data) { DltReceiveData *dltdata; static char text[DLT_RECEIVE_BUFSIZE]; char filename[255]; struct iovec iov[2]; int bytes_written; if ((message == 0) || (data == 0)) return -1; dltdata = (DltReceiveData *)data; if (dltdata->filetransfervalue) { dlt_message_print_ascii(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); /* 1st find starting point of tranfering data packages */ if (strncmp(text, "FLST", 4) == 0) { char *tmpFilename; tmpFilename = strrchr(text, '/') + 1; unsigned int i; for (i = 0; i < strlen(tmpFilename); i++) if (isspace(tmpFilename[i])) { tmpFilename[i] = '\0'; break; } /* create file for each received file, as named as crc value */ snprintf(filename, 255, "/tmp/%s", tmpFilename); fp = fopen(filename, "w+"); } /* 3rd close fp */ if (strncmp(text, "FLFI", 4) == 0) { printf("TEST FILETRANSFER PASSED\n"); fclose(fp); } /* 2nd check if incomming data are filetransfer data */ if (strncmp(text, "FLDA", 4) == 0) { /* truncate beginning of data stream ( FLDA, File identifier and package number) */ char *position = strchr(text, 32); /* search for space */ strncpy(text, position + 1, DLT_RECEIVE_BUFSIZE); position = strchr(text, 32); strncpy(text, position + 1, DLT_RECEIVE_BUFSIZE); position = strchr(text, 32); strncpy(text, position + 1, DLT_RECEIVE_BUFSIZE); /* truncate ending of data stream ( FLDA ) */ int len = strlen(text); text[len - 4] = '\0'; /* hex to ascii and store at /tmp */ char tmp[3]; int i; for (i = 0; i < (int)strlen(text); i = i + 3) { tmp[0] = text[i]; tmp[1] = text[i + 1]; tmp[2] = '\0'; unsigned long h = strtoul(tmp, NULL, 16); fprintf(fp, "%c", (int)h); } } } if (dltdata->systemjournalvalue) { dlt_message_print_ascii(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); /* 1st find the relevant packages */ char *tmp = message->extendedheader->ctid; tmp[4] = '\0'; if (strcmp(tmp, (const char *)"JOUR") == 0) { if (strstr(text, "DLT SYSTEM JOURNAL TEST")) { result++; if (result == 1000) exit(159); } } } if (dltdata->systemloggervalue) { dlt_message_print_ascii(message, text, DLT_RECEIVE_BUFSIZE, dltdata->vflag); /* 1st find the relevant packages */ char *tmp = message->extendedheader->ctid; tmp[4] = '\0'; const char *substring = text; const char *founding = "Test Systemlogger"; int length = strlen(founding); if (strcmp(tmp, (const char *)"PROC") == 0) { substring = strstr(text, founding); while (substring != NULL) { result++; substring += length; if (result == 1000) exit(159); } } } /* if file output enabled write message */ if (dltdata->ovalue) { iov[0].iov_base = message->headerbuffer; iov[0].iov_len = message->headersize; iov[1].iov_base = message->databuffer; iov[1].iov_len = message->datasize; bytes_written = writev(dltdata->ohandle, iov, 2); if (0 > bytes_written) { printf("dlt_receive_message_callback: writev(dltdata->ohandle, iov, 2); returned an error!"); return -1; } } return 0; } dlt-daemon-2.18.10/tests/gtest_dlt_common.cpp000066400000000000000000006333571446635226000211470ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Stefan Held * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file gtest_dlt_common.cpp */ #include #include #include #include #define MAX_LINE 200 #define BINARY_FILE_NAME "/testfile.dlt" #define FILTER_FILE_NAME "/testfilter.txt" extern "C" { #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_user_cfg.h" #include "dlt_version.h" #include "dlt_client.h" #include "dlt_protocol.h" int dlt_buffer_increase_size(DltBuffer *); int dlt_buffer_minimize_size(DltBuffer *); int dlt_buffer_reset(DltBuffer *); DltReturnValue dlt_buffer_push(DltBuffer *, const unsigned char *, unsigned int); DltReturnValue dlt_buffer_push3(DltBuffer *, const unsigned char *, unsigned int, const unsigned char *, unsigned int, const unsigned char *, unsigned int); int dlt_buffer_get(DltBuffer *, unsigned char *, int, int); int dlt_buffer_pull(DltBuffer *, unsigned char *, int); int dlt_buffer_remove(DltBuffer *); void dlt_buffer_status(DltBuffer *); void dlt_buffer_write_block(DltBuffer *, int *, const unsigned char *, unsigned int); void dlt_buffer_read_block(DltBuffer *, int *, unsigned char *, unsigned int); void dlt_buffer_info(DltBuffer *); } /* Begin Method: dlt_common::dlt_buffer_init_dynamic */ TEST(t_dlt_buffer_init_dynamic, normal) { DltBuffer init_dynamic; /* Normal Use-Case for initializing a buffer */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&init_dynamic, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&init_dynamic)); /* Min Values for a success init */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&init_dynamic, 12, 12, 12)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&init_dynamic)); } TEST(t_dlt_buffer_init_dynamic, abnormal) { /* DltBuffer buf; */ /* Initialze buffer twice, expected -1 for second init */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_free_dynamic(&buf)); */ /* Initialize buffer with max-value of uint32, expected 0 */ /* TODO: what should the maximum parameter values be? UINT_MAX is too large and leads to segfault */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, UINT_MAX,UINT_MAX,UINT_MAX)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_free_dynamic(&buf)); */ /* Initialize buffer with min-value of uint32, expected 0 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, 0,0,0)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_free_dynamic(&buf)); */ /* Initialize buffer min-value > max-value, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_free_dynamic(&buf)); */ /* Initialsize buffer step-value > max-value, expected -1 */ /* EXPECT_GE(-1,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE * 2)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_init_dynamic, nullpointer) { DltBuffer buf; /* NULL-Pointer, expect -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, 0, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, 0, 0, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, 0, DLT_USER_RINGBUFFER_MAX_SIZE, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, 0, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, DLT_USER_RINGBUFFER_MIN_SIZE, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, DLT_USER_RINGBUFFER_MIN_SIZE, 0, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(NULL, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, 0, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, 0, 0, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, 0, DLT_USER_RINGBUFFER_MAX_SIZE, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, 0, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, 0, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, 0)); } /* End Method: dlt_common::dlt_buffer_init_dynamic */ /* Begin Method: dlt_common::dlt_buffer_free_dynamic */ TEST(t_dlt_buffer_free_dynamic, normal) { DltBuffer buf; /* Normal Use-Case szenario */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case szenario */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, 12, 12, 12)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_free_dynamic, abnormal) { /* DltBuffer buf; */ /* Free uninizialised buffer, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_free_dynamic(&buf)); */ /* Free buffer twice, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_GE(-1, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_free_dynamic, nullpointer) { /* NULL-POinter */ EXPECT_GE(-1, dlt_buffer_free_dynamic(NULL)); } /* End Method: dlt_common::dlt_buffer_free_dynamic */ /* Begin Method: dlt_common::dlt_buffer_increase_size */ TEST(t_dlt_buffer_increase_size, normal) { DltBuffer buf; /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(0, dlt_buffer_increase_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Fill buffer to max-value, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); for (int i = 0; i <= (DLT_USER_RINGBUFFER_MAX_SIZE / DLT_USER_RINGBUFFER_MIN_SIZE); i += DLT_USER_RINGBUFFER_STEP_SIZE) EXPECT_LE(0, dlt_buffer_increase_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_increase_size, abnormal) { /* DltBuffer buf; */ /* Increase uninizialised buffer */ /* EXPECT_GE(-1, dlt_buffer_increase_size(&buf)); */ /* Fill buffer over max-value, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_increase_size(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* min-value > max-value, trying to increase buffer, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_increase_size(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* trying to increase buffer with 0 , expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, 0)); */ /* EXPECT_GE(-1, dlt_buffer_increase_size(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_increase_size, nullpointer) { /* NULL-Pointer, expected -1 */ EXPECT_GE(-1, dlt_buffer_increase_size(NULL)); } /* End Method: dlt_common::dlt_buffer_increase_size */ /* Begin Method: dlt_common::dlt_buffer_minimize_size */ TEST(t_dlt_buffer_minimize_size, normal) { DltBuffer buf; /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(0, dlt_buffer_minimize_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* minimize buffer to min-value, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); for (int i = (DLT_USER_RINGBUFFER_MAX_SIZE / DLT_USER_RINGBUFFER_MIN_SIZE); i >= 0; i -= DLT_USER_RINGBUFFER_STEP_SIZE) EXPECT_LE(0, dlt_buffer_minimize_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_minimize_size, abnormal) { /* DltBuffer buf; */ /* Minimize uninizialised buffer */ /* EXPECT_GE(-1, dlt_buffer_minimize_size(&buf)); */ /* minimize buffer under min-value, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_minimize_size(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* min-value > max-value, trying to minimize buffer, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_minimize_size(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* trying to minimize buffer with 0 , expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, 0)); */ /* EXPECT_GE(-1, dlt_buffer_minimize_size(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_minimize_size, nullpointer) { /* NULL-Pointer, expected -1 */ EXPECT_GE(-1, dlt_buffer_minimize_size(NULL)); } /* End Method: dlt_common::dlt_buffer_minimize_size */ /* Begin Method: dlt_common::dlt_buffer_reset */ TEST(t_dlt_buffer_reset, normal) { DltBuffer buf; /* Normal Use-Case. expect 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(0, dlt_buffer_reset(&buf)); } TEST(t_dlt_buffer_reset, abnormal) { /* DltBuffer buf; */ /*Use uninizialsied buffer, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_reset(&buf)); */ } TEST(t_dlt_buffer_reset, nullpointer) { /*Use NULL-Pointer, expected -1 */ EXPECT_GE(-1, dlt_buffer_reset(NULL)); } /* End Method: dlt_common::dlt_buffer_reset */ /* Begin Method: dlt_common::dlt_buffer_push*/ TEST(t_dlt_buffer_push, normal) { DltBuffer buf; char *test; unsigned int size = sizeof(test); /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&test, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Push till buffer is full, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); for (unsigned int i = 0; i <= (DLT_USER_RINGBUFFER_MIN_SIZE / (size + sizeof(DltBufferBlockHead))); i++) { EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&test, size)); } EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_push, abnormal) { /* DltBuffer buf; */ /* char * test; */ /* int size = sizeof(test); */ /* Use uninizialsied, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_push(&buf,(unsigned char *)&test,size)); */ /* set size == 0, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(&buf,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* set size == 0 and char == 0 expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(&buf,0,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* Push till buffer is overfilled , expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* for(int i=0; i<= (DLT_USER_RINGBUFFER_MIN_SIZE/size) + size; i++) */ /* { */ /* if(i <= DLT_USER_RINGBUFFER_MIN_SIZE) */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf,(unsigned char *)&test,size)); */ /* else */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(&buf,(unsigned char *)&test,size)); */ /* } */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* All use-case, wich works with null pointer, has to discuss */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(&buf,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(&buf,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_push, nullpointer) { char *test; int size = sizeof(test); /* NULL-Pointer, expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(NULL, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(NULL, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(NULL, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push(NULL, (unsigned char *)&test, size)); } /* End Method: dlt_common::dlt_buffer_push*/ /* Begin Method: dlt_common::dlt_buffer_push3 */ TEST(t_dlt_buffer_push3, normal) { DltBuffer buf; char *test; int size = sizeof(test); /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push3(&buf, (unsigned char *)&test, size, 0, 0, 0, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push3(&buf, (unsigned char *)&test, size, (unsigned char *)&test, size, (unsigned char *)&test, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Push till buffer is full, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); for (unsigned int i = 0; i <= (DLT_USER_RINGBUFFER_MIN_SIZE / (size * 3 + sizeof(DltBufferBlockHead))); i++) EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push3(&buf, (unsigned char *)&test, size, (unsigned char *)&test, size, (unsigned char *)&test, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_push3, abnormal) { /* DltBuffer buf; */ /* char * test; */ /* int size = sizeof(test); */ /* Use uninizialsied, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,size,(unsigned char *)&test,size)); */ /* set size == 0, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0, (unsigned char *)&test,0, (unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* set size == 0 and char == 0 expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,0,0,0,0,0,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* works with null pointer, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* Push till buffer is overfilled , expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* for(int i=0; i<= (DLT_USER_RINGBUFFER_MIN_SIZE/size) + size; i++) */ /* { */ /* if(i <= DLT_USER_RINGBUFFER_MIN_SIZE) */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,size,(unsigned char *)&test,size)); */ /* else */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,size,(unsigned char *)&test,size)); */ /* } */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* All use-case, wich works with null pointer, has to discuss */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,0,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,0,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,size,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,NULL,size,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,0,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,0,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,size,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,0,(unsigned char *)&test,size,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,0,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,0,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,size,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,NULL,size,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,0,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,0,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,size,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,NULL,size,(unsigned char *)&test,size,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,0,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,0,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,size,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,NULL,size,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,(unsigned char *)&test,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,(unsigned char *)&test,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,(unsigned char *)&test,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,0,(unsigned char *)&test,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,0,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,0,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,size,(unsigned char *)&test,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,NULL,size,(unsigned char *)&test,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,0,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,0,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,size,NULL,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK,dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(&buf,(unsigned char *)&test,size,(unsigned char *)&test,size,NULL,size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_push3, nullpointer) { char *test; int size = sizeof(test); /*Null Pointer, expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, NULL, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, 0, (unsigned char *)&test, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, NULL, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, NULL, size, (unsigned char *)&test, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, NULL, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, 0, (unsigned char *)&test, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, NULL, size, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, 0, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, 0, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, 0, (unsigned char *)&test, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, size, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, size, NULL, size)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, size, (unsigned char *)&test, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_buffer_push3(NULL, (unsigned char *)&test, size, (unsigned char *)&test, size, (unsigned char *)&test, size)); } /* End Method: dlt_common::dlt_buffer_push3 */ /* Begin Method: dlt_common::dlt_buffer_pull */ TEST(t_dlt_buffer_pull, normal) { /*Normal Use Cases, expected 0 or -1 in return */ DltBuffer buf; DltUserHeader header; int size = sizeof(DltUserHeader); /* Normal Use-Case, empty pull, expected -1 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_pull(&buf, (unsigned char *)&header, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case, expected > 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); EXPECT_LE(1, dlt_buffer_pull(&buf, (unsigned char *)&header, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_pull, abnormal) { /* DltBuffer buf; */ /* DltUserHeader header; */ /* Uninizialised, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_pull(&buf, (unsigned char*)&header, sizeof(DltUserHeader))); */ /* data == 0 and max_size == 0, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf,(unsigned char *)&header,sizeof(DltUserHeader))); */ /* EXPECT_GE(-1, dlt_buffer_pull(&buf, 0, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* no push before pull, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_pull(&buf, 0, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_pull, nullpointer) { DltBuffer buf; DltUserHeader header; /* NULL-Point, expected -1 */ EXPECT_GE(-1, dlt_buffer_pull(NULL, NULL, 0)); EXPECT_GE(-1, dlt_buffer_pull(NULL, NULL, sizeof(DltUserHeader))); EXPECT_GE(-1, dlt_buffer_pull(NULL, (unsigned char *)&header, 0)); EXPECT_GE(-1, dlt_buffer_pull(NULL, (unsigned char *)&header, sizeof(DltUserHeader))); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_pull(&buf, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_pull(&buf, NULL, sizeof(DltUserHeader))); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } /* End Method: dlt_common::dlt_buffer_pull */ /* Begin Method: dlt_common::dlt_buffer_remove */ TEST(t_dlt_buffer_remove, normal) { DltBuffer buf; DltUserHeader header; int size = sizeof(DltUserHeader); /* Normal Use-Case, empty pull, expected -1 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_remove(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case, expected > 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, size)); EXPECT_LE(0, dlt_buffer_remove(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_remove, abnormal) { /* DltBuffer buf; */ /* DltUserHeader header; */ /* int size = sizeof(DltUserHeader); */ /* Uninizialised, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_remove(&buf)); */ /* no push before remove, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_GE(-1, dlt_buffer_remove(&buf)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ /* Call remove 10 time, expected > 1 till buffer is empty */ /* pushed one time so expect one > 1 and 9 times < 0 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf,(unsigned char *)&header,size)); */ /* for(int i=0; i<10;i++) */ /* { */ /* if(i == 0) */ /* EXPECT_LE(1, dlt_buffer_remove(&buf)); */ /* else */ /* EXPECT_GE(-1, dlt_buffer_remove(&buf)); */ /* } */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_remove, nullpointer) { /* NULL_Pointer, expected -1 */ EXPECT_GE(-1, dlt_buffer_remove(NULL)); } /* End Method: dlt_common::dlt_buffer_remove*/ /* Begin Method: dlt_common::dlt_buffer_copy */ TEST(t_dlt_buffer_copy, normal) { DltBuffer buf; DltUserHeader header; int size = sizeof(DltUserHeader); /* Normal Use-Case, empty pull, expected -1 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_copy(&buf, (unsigned char *)&header, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case, expected > 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); EXPECT_LE(1, dlt_buffer_copy(&buf, (unsigned char *)&header, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_copy, abnormal) { /* DltBuffer buf; */ /* DltUserHeader header; */ /* int size = sizeof(DltUserHeader); */ /* Uninizialised buffer , expected -1 */ /* EXPECT_LE(-1, dlt_buffer_copy(&buf, (unsigned char *)&header, size)); */ /* no push before copy, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(-1, dlt_buffer_copy(&buf, (unsigned char *)&header, size)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_copy, nullpointer) { DltBuffer buf; DltUserHeader header; int size = sizeof(DltUserHeader); /* NULL-Pointer, expected -1 */ EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_buffer_copy(NULL, NULL, size)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_buffer_copy(NULL, NULL, 0)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_buffer_copy(NULL, (unsigned char *)&header, size)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_buffer_copy(NULL, (unsigned char *)&header, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_buffer_copy(&buf, NULL, size)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_buffer_copy(&buf, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } /* End Method: dlt_common::dlt_buffer_copy */ /* Begin Method: dlt_common::dlt_buffer_get */ TEST(t_dlt_buffer_get, normal) { DltBuffer buf; DltUserHeader header; int size = sizeof(DltUserHeader); /* Normal Use-Case */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, size)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); EXPECT_LE(0, dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, size)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); EXPECT_LE(0, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[0] = 50000; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[1] = 50000; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[2] = -50000; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[2] = 0; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[0] = 4000; ((int *)(buf.shm))[1] = 5000; ((int *)(buf.shm))[2] = 0; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[0] = 10; ((int *)(buf.shm))[1] = 5; ((int *)(buf.shm))[2] = 5; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[2] = 50000; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, size)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[0] = 19; EXPECT_GE(-1, dlt_buffer_get(&buf, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, size)); printf("#### %i\n", dlt_buffer_get(&buf, (unsigned char *)&header, size, 0)); ((int *)(buf.shm))[2] = 19; EXPECT_LE(0, dlt_buffer_get(&buf, (unsigned char *)&header, 5, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_get, abnormal) { /* DltBuffer buf; */ /* DltUserHeader header; */ /* int size = sizeof(DltUserHeader); */ /* Uninizialsied, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_get(&buf,(unsigned char *)&header,size, 0)); */ /* Integer with 12345678 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf,(unsigned char *)&header,size)); */ /* printf("#### %i\n", dlt_buffer_get(&buf,(unsigned char*)&header,size,0)); */ /* EXPECT_LE(0, dlt_buffer_get(&buf,(unsigned char*)&header,size,12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); */ } TEST(t_dlt_buffer_get, nullpointer) { DltBuffer buf; DltUserHeader header; int size = sizeof(DltUserHeader); /* NULL-Pointer */ EXPECT_GE(-1, dlt_buffer_get(NULL, NULL, 0, 0)); EXPECT_GE(-1, dlt_buffer_get(NULL, NULL, 0, 1)); EXPECT_GE(-1, dlt_buffer_get(NULL, NULL, size, 0)); EXPECT_GE(-1, dlt_buffer_get(NULL, NULL, size, 1)); EXPECT_GE(-1, dlt_buffer_get(NULL, (unsigned char *)&header, 0, 0)); EXPECT_GE(-1, dlt_buffer_get(NULL, (unsigned char *)&header, 0, 1)); EXPECT_GE(-1, dlt_buffer_get(NULL, (unsigned char *)&header, size, 0)); EXPECT_GE(-1, dlt_buffer_get(NULL, (unsigned char *)&header, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_get(&buf, NULL, 0, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_get(&buf, NULL, 0, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_get(&buf, NULL, size, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_GE(-1, dlt_buffer_get(&buf, NULL, size, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } /* End Method: dlt_common::dlt_buffer_get */ /* Begin MEthod: dlt_common::dlt_buffer_get_message_count */ TEST(t_dlt_buffer_get_message_count, normal) { DltBuffer buf; DltUserHeader header; /* Normal Usce-Case without pushing data, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); /*printf("##### %i\n", dlt_buffer_get_message_count(&buf)); */ EXPECT_EQ(0, dlt_buffer_get_message_count(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case, with pushing data, expected 1 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); /*printf("#### %i\n", dlt_buffer_get_message_count(&buf)); */ EXPECT_EQ(1, dlt_buffer_get_message_count(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Pushing DLT_USER_RINGBUFFER_MIN_SIZE / (sizeof(DltUserHeader) + sizeof(DltBufferBlockHead)) mesages */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); for (unsigned int i = 1; i <= DLT_USER_RINGBUFFER_MIN_SIZE / (sizeof(DltUserHeader) + sizeof(DltBufferBlockHead)); i++) { EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); /*printf("#### %i\n", dlt_buffer_get_message_count(&buf)); */ EXPECT_EQ(i, dlt_buffer_get_message_count(&buf)); } EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_get_message_count, abnormal) { /* DltBuffer buf; */ /* Uninizialised, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_get_message_count(&buf)); */ } TEST(t_dlt_buffer_get_message_count, nullpointer) { /*NULL-Pointer, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_get_message_count(NULL)); */ } /* Begin MEthod: dlt_common::dlt_buffer_get_message_count */ /* Begin Method: dlt_common::dlt_buffer_get_total_size*/ TEST(t_dlt_buffer_get_total_size, normal) { DltBuffer buf; DltUserHeader header; /* Normal Use-Case, expected max buffer size (DLT_USER_RINGBUFFER_MAX_SIZE) */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); /*printf("##### %i\n", dlt_buffer_get_total_size(&buf)); */ EXPECT_LE(DLT_USER_RINGBUFFER_MAX_SIZE, dlt_buffer_get_total_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case, 1st pushing data, expected max buffer size (DLT_USER_RINGBUFFER_MAX_SIZE) */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); /*printf("##### %i\n", dlt_buffer_get_total_size(&buf)); */ EXPECT_LE(DLT_USER_RINGBUFFER_MAX_SIZE, dlt_buffer_get_total_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_get_total_size, abnormal) { /* DltBuffer buf; */ /* Uninizialised, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_get_total_size(&buf)); */ } TEST(t_dlt_buffer_get_total_size, nullpointer) { /* NULL-Pointer, expect -1 */ EXPECT_GE(-1, dlt_buffer_get_total_size(NULL)); } /* End Method: dlt_common::dlt_buffer_get_total_size*/ /* Begin Method: dlt_common::dlt_buffer_get_used_size*/ TEST(t_dlt_buffer_get_used_size, normal) { DltBuffer buf; DltUserHeader header; int sum = 0; /* Normal Use Cas buffer empty, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); /*printf("##### %i\n", dlt_buffer_get_used_size(&buf)); */ EXPECT_EQ(0, dlt_buffer_get_used_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case with pushing data, expected sum of DltUserHeader and DltBufferBlockHead */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); /*printf("##### %i\n", dlt_buffer_get_used_size(&buf)); */ EXPECT_EQ(sizeof(DltUserHeader) + sizeof(DltBufferBlockHead), dlt_buffer_get_used_size(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); /* Normal Use-Case with pushing DLT_USER_RINGBUFFER_MIN_SIZE / (sizeof(DltUserHeader) + sizeof(DltBufferBlockHead)) data */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); for (unsigned int i = 1; i <= DLT_USER_RINGBUFFER_MIN_SIZE / (sizeof(DltUserHeader) + sizeof(DltBufferBlockHead)); i++) { EXPECT_LE(DLT_RETURN_OK, dlt_buffer_push(&buf, (unsigned char *)&header, sizeof(DltUserHeader))); /*printf("#### %i\n", dlt_buffer_get_used_size(&buf)); */ sum += sizeof(DltUserHeader) + sizeof(DltBufferBlockHead); EXPECT_EQ(sum, dlt_buffer_get_used_size(&buf)); } EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_get_used_size, abnormal) { /* DltBuffer buf; */ /* Uninizialised, expected -1 */ /* EXPECT_GE(-1, dlt_buffer_get_used_size(&buf)); */ } TEST(t_dlt_buffer_get_used_size, nullpointer) { /*NULL-Pointer, expcted -1 */ EXPECT_GE(-1, dlt_buffer_get_used_size(NULL)); } /* End Method: dlt_common::dlt_buffer_get_used_size*/ /* Begin Method: dlt_common::dlt_buffer_write_block */ TEST(t_dlt_buffer_write_block, normal) { DltBuffer buf; unsigned char *data = NULL; int write; int size1 = 516; int size2 = 1024; /* Normal Use-Case, void method, expected no error */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, data, size1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, data, size2)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); int tmp = 0; for (int i = 0; i <= 10000; i += 10) { tmp += i; EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, data, i)); } EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_write_block, abnormal) { /* Boundary check of write position */ DltBuffer buf; const char *data = "data"; int write = DLT_USER_RINGBUFFER_MIN_SIZE; write -= sizeof(DltBufferHead); int size = sizeof(data); // when write = buf->size, it should not throw any warning // and write should equal to size. EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf,DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, (unsigned char *)&data, size)); EXPECT_EQ(size , write); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_write_block, nullpointer) { DltBuffer buf; char *data; int write; int test1 = 1000; /* NULL-Pointer, expected < 0 */ EXPECT_NO_THROW(dlt_buffer_write_block(NULL, NULL, NULL, 0)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, NULL, NULL, test1)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, NULL, (unsigned char *)&data, 0)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, NULL, (unsigned char *)&data, test1)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, &write, NULL, 0)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, &write, NULL, test1)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, &write, (unsigned char *)&data, 0)); EXPECT_NO_THROW(dlt_buffer_write_block(NULL, &write, (unsigned char *)&data, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, NULL, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, NULL, NULL, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, NULL, (unsigned char *)&data, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, NULL, (unsigned char *)&data, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, NULL, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } /* End Method: dlt_common::dlt_buffer_write_block */ /* Begin Method: dlt_common::dlt_buffer_read_block */ TEST(t_dlt_buffer_read_block, normal) { DltBuffer buf; unsigned char *data = NULL; int write, read; int size1 = 516; int size2 = 1024; /* Normal Use-Case, void method, expected no error */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &write, data, size1)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, &write, data, size1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_write_block(&buf, &read, data, size2)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, &write, data, size2)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_buffer_read_block, abnormal) { /* Boundary check of read position */ DltBuffer buf; /* Buffer to read data from DltBuffer */ unsigned char *data_read; data_read = (unsigned char *) calloc(1000, sizeof(char)); int read = DLT_USER_RINGBUFFER_MIN_SIZE; read -= sizeof(DltBufferHead); int size = 1000; // when read = buf->size, it should not throw any warning // and read position should equal to size. EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, &read, data_read, size)); EXPECT_EQ(size,read); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); free(data_read); } TEST(t_dlt_buffer_read_block, nullpointer) { DltBuffer buf; char *data; int read = -1; int test1 = 1000; /* NULL-Pointer, expected < 0 */ EXPECT_NO_THROW(dlt_buffer_read_block(NULL, NULL, NULL, 0)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, NULL, NULL, test1)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, NULL, (unsigned char *)&data, 0)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, NULL, (unsigned char *)&data, test1)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, &read, NULL, 0)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, &read, NULL, test1)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, &read, (unsigned char *)&data, 0)); EXPECT_NO_THROW(dlt_buffer_read_block(NULL, &read, (unsigned char *)&data, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, NULL, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, NULL, NULL, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, NULL, (unsigned char *)&data, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, NULL, (unsigned char *)&data, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, &read, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, &read, NULL, test1)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_read_block(&buf, &read, (unsigned char *)&data, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } /* End Method: dlt_common::dlt_buffer_read_block */ /* Begin Method: dlt_common::dlt_buffer_info */ TEST(t_dlt_buffer_info, normal) { DltBuffer buf; /* Normal Use-Case */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_info(&buf)); } TEST(t_dlt_buffer_info, abnormal) { /* actually no abnormal test cases */ /* because of void function and missing gtest tools for that */ } TEST(t_dlt_buffer_info, nullpointer) { /* NULL-Pointer, no throw */ EXPECT_NO_THROW(dlt_buffer_info(NULL)); } /* End Method: dlt_common::dlt_buffer_info */ /* Begin Method: dlt_common::dlt_buffer_status */ TEST(t_dlt_buffer_status, normal) { DltBuffer buf; /* Normal Use-Case */ EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_NO_THROW(dlt_buffer_status(&buf)); } TEST(t_dlt_buffer_status, abnormal) { /* actual no abnormal test cases */ /* because of void funktion and missing gtest tools for that */ } TEST(t_dlt_buffer_status, nullpointer) { /* NULL-Pointer, expected -1 */ EXPECT_NO_THROW(dlt_buffer_status(NULL)); } /* End Method: dlt_common::dlt_buffer_status */ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /* Begin Method: dlt_common::dlt_message_init*/ TEST(t_dlt_message_init, normal) { DltMessage msg; /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg, 0)); } TEST(t_dlt_message_init, abnormal) { /* DltMessage msg; */ /* Double use init, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg,0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_init(&msg,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg,1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_init(&msg,1)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg,1)); */ /* set Verbose to 12345678, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_init(&msg,12345678)); */ } TEST(t_dlt_message_init, nullpointer) { /*NULL-Pointer, expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_message_init(NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_init(NULL, 1)); } /* End Method: dlt_common::dlt_message_init*/ /* Begin Method: dlt_common::dlt_message_free */ TEST(t_dlt_message_free, normal) { DltMessage msg; /* Normal Use Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg, 1)); } TEST(t_dlt_message_free, abnormal) { /* DltMessage msg; */ /* Double use free, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg,0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_free(&msg,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_init(&msg,0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_message_free(&msg,1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_free(&msg,1)); */ /* set Verbose to 12345678, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_free(&msg,12345678)); */ } TEST(t_dlt_message_free, nullpointer) { /*NULL-Pointer, expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_message_free(NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_free(NULL, 1)); } /* End Method: dlt_common::dlt_message_free */ /* Begin Method: dlt_common::dlt_file_open */ TEST(t_dlt_file_open, normal) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_file_open, abnormal) { /* DltFile file; */ /* / * Get PWD so file can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* Uninizialsied, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(&file, openfile, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(&file, openfile, 1)); */ /* Verbose set to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(&file, openfile, 12345678)); */ /* Path doesn't exist, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(&file, "This Path doesn't exist!!", 0)); */ } TEST(t_dlt_file_open, nullpointer) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* NULL-Pointer, expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(NULL, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(NULL, NULL, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(NULL, openfile, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(NULL, openfile, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(&file, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_file_open(&file, NULL, 1)); } /* End Method: dlt_common::dlt_file_open */ /* Begin Method: dlt_common::dlt_file_quick_parsing */ TEST(t_dlt_file_quick_parsing, normal) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; char output[128] = "/tmp/output_testfile.txt"; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_quick_parsing(&file, output, DLT_OUTPUT_ASCII, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); unlink(output); } TEST(t_dlt_file_quick_parsing, abnormal) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; char output[128] = "/tmp/output_testfile.txt"; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Abnormal Use-Case, expected DLT_RETURN_WRONG_PARAMETER (-5) */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); EXPECT_GE(DLT_RETURN_WRONG_PARAMETER, dlt_file_quick_parsing(&file, NULL, DLT_OUTPUT_ASCII, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); EXPECT_GE(DLT_RETURN_WRONG_PARAMETER, dlt_file_quick_parsing(NULL, output, DLT_OUTPUT_ASCII, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } /* End Method: dlt_common::dlt_file_quick_parsing */ /* Begin Method: dlt_common::dlt_message_print_ascii*/ TEST(t_dlt_message_print_ascii, normal) { DltFile file; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_ascii, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* / * Get PWD so file and filter can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* No messages read, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); */ /* Set verbose to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_ascii_with_filter, abnormal) { /* equal with t_dlt_message_print_ascii */ } TEST(t_dlt_message_print_ascii_with_filter, nullpointer) { /* equal with t_dlt_message_print_ascii */ } /* End Method: dlt_common::dlt_message_print_ascii with filter*/ /* Begin Method: dlt_common::dlt_message_print_header */ TEST(t_dlt_message_print_header, normal) { DltFile file; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_header, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* / * Get PWD so file and filter can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* No messages read, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); */ /* Set verbose to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_header_with_filter, abnormal) { /* equal with t_dlt_message_print_header */ } TEST(t_dlt_message_print_header_with_filter, nullpointer) { /* equal with t_dlt_message_print_header */ } /* End Method: dlt_common::dlt_message_print_header with filter */ /* Begin Method: dlt_common::dlt_message_print_hex */ TEST(t_dlt_message_print_hex, normal) { DltFile file; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_hex, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* / * Get PWD so file and filter can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* No messages read, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); */ /* Set verbose to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_hex(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_hex_with_filter, abnormal) { /* equal with t_dlt_message_print_hex */ } TEST(t_dlt_message_print_hex_with_filter, nullpointer) { /* equal with t_dlt_message_print_hex */ } /* End Method: dlt_common::dlt_message_print_hex with filter */ /* Begin Method: dlt_common::dlt_message_print_mixed_plain */ TEST(t_dlt_message_print_mixed_plain, normal) { DltFile file; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_mixed_plain, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* / * Get PWD so file and filter can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* No messages read, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); */ /* Set verbose to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_plain(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_mixed_plain_with_filter, abnormal) { /* equal with t_dlt_message_print_mixed_plain */ } TEST(t_dlt_message_print_mixed_plain_with_filter, nullpointer) { /* equal with t_dlt_message_print_mixed_plain */ } /* End Method: dlt_common::dlt_message_print_mixed_pain with filter */ /* Begin Method: dlt_common::dlt_message_print_mixed_html */ TEST(t_dlt_message_print_mixed_html, normal) { DltFile file; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_mixed_html, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* / * Get PWD so file and filter can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* No messages read, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); */ /* Set verbose to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_mixed_html(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_mixed_html_with_filter, abnormal) { /* equal with t_dlt_message_print_mixed_html */ } TEST(t_dlt_message_print_mixed_html_with_filter, nullpointer) { /* equal with t_dlt_message_print_mixed_html */ } /* End Method: dlt_common::dlt_message_print_mixed_html_with filter */ /* Begin Method:dlt_common::dlt_message_filter_check */ TEST(t_dlt_message_filter_check, normal) { DltFile file; DltFilter filter; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} char openfilter[MAX_LINE+sizeof(FILTER_FILE_NAME)]; sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); sprintf(openfilter, "%s" FILTER_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expected > 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_filter_init(&filter, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_filter_load(&filter, openfilter, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_set_filter(&file, &filter, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_filter_check(&file.msg, &filter, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_filter_check(&file.msg, &filter, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_filter_check, abnormal) { /* DltFile file; */ /* DltFilter filter; */ /* Get PWD so file and filter can be used*/ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; */ /* char openfilter[MAX_LINE+sizeof(FILTER_FILE_NAME)]; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /* sprintf(openfilter, "%s" FILTER_FILE_NAME, pwd); */ /*---------------------------------------*/ /* No messages read, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_filter_check(&file.msg, &filter, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_filter_check(&file.msg, &filter, 1)); */ /* Set verbose to 12345678 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_filter_check(&file.msg, &filter, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_get_extraparameters(&file.msg, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_get_extraparameters(&file.msg, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_get_extraparamters, abnormal) { /* DltFile file; */ /* Get PWD so file and filter can be used*/ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* Uninizialised, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_get_extraparameters(&file.msg, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_get_extraparameters(&file.msg, 1)); */ /* set verbose to 12345678, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_get_extraparameters(&file.msg, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); printf("%s \n", text); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); printf("%s \n", text); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_header, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* Get PWD so file and filter can be used*/ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* Uninizialised, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); */ /* set verbose to 12345678, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header(&file.msg, text, DLT_DAEMON_TEXTSIZE, 12345678)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NONE, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TIME, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TMSTP, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGCNT, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ECUID, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_APID, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_CTID, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGTYPE, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGSUBTYPE, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_VNVSTATUS, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NOARG, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ALL, 0)); printf("%s \n", text); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NONE, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TIME, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TMSTP, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGCNT, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ECUID, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_APID, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_CTID, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGTYPE, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGSUBTYPE, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_VNVSTATUS, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NOARG, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ALL, 1)); printf("%s \n", text); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_header_flags, abnormal) { /* DltFile file; */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /* / * Get PWD so file and filter can be used* / */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];;; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* Uninizialised, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NONE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TIME, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TMSTP, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGCNT, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ECUID, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_APID, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_CTID, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGTYPE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGSUBTYPE, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_VNVSTATUS, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NOARG, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ALL, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NONE, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TIME, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_TMSTP, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGCNT, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ECUID, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_APID, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_CTID, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGTYPE, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_MSGSUBTYPE, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_VNVSTATUS, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_NOARG, 1)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_HEADER_SHOW_ALL, 1)); */ /* USE own DLT_HEADER_SHOW , expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_header_flags(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0x1234, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_HEX, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_PLAIN, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_HTML, 0)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII_LIMITED, 0)); printf("%s \n", text); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_HEX, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_PLAIN, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_HTML, 1)); printf("%s \n", text); EXPECT_LE(DLT_RETURN_OK, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII_LIMITED, 1)); printf("%s \n", text); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_payload, abnormal) { DltFile file; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file and filter can be used*/ char pwd[MAX_LINE]; if (getcwd(pwd, MAX_LINE) == NULL) {} char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Uninizialised, expected -1 */ memset(&file, 0x00, sizeof(DltFile)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_HEX, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_PLAIN, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_HTML, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII_LIMITED, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_HEX, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_PLAIN, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_MIXED_FOR_HTML, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, DLT_OUTPUT_ASCII_LIMITED, 1)); /* USE own DLT_HEADER_SHOW , expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, 99, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file,0)>=0){} for(int i=0;i 0 but */ /* we don't have text: */ /* dlt_common.c line 943: ptr = msg->databuffer; */ /* (gdb) p ptr */ /* $28 = (uint8_t *) 0x5124010337d46c00 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_payload(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0, 1)); */ } /* End Method:dlt_common::dlt_message_payload */ /* Begin Method:dlt_common::dlt_message_set_extraparameters */ TEST(t_dlt_message_set_extraparamters, normal) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ /* Normal Use-Case, expect 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_set_extraparameters(&file.msg, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_set_extraparameters(&file.msg, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_set_extraparamters, abnormal) { /* DltFile file; */ /* // Get PWD so file and filter can be used */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /*---------------------------------------*/ /* Uninizialised, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_set_extraparameters(&file.msg, 0)); */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_set_extraparameters(&file.msg, 1)); */ /* set verbos to 12345678 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_ERROR, dlt_message_read(&file.msg, (unsigned char *)buffer, 255, 0, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); EXPECT_LE(DLT_RETURN_OK, dlt_buffer_init_dynamic(&buf, DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)); EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_ERROR, dlt_message_read(&file.msg, (unsigned char *)buffer, 255, 1, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_buffer_free_dynamic(&buf)); } TEST(t_dlt_message_read, abnormal) {} TEST(t_dlt_message_read, nullpointer) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); /*---------------------------------------*/ DltBuffer buf; /* NULL_Pointer, expected -1 */ EXPECT_GE(DLT_RETURN_ERROR, dlt_message_read(NULL, NULL, 0, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_read(NULL, (uint8_t *)&buf, 0, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_read(&file.msg, NULL, 0, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_message_read(&file.msg, (uint8_t *)&buf, 0, 0, 0)); } /* End Method:dlt_common::dlt_message_read */ /* Begin Method:dlt_common::dlt_message_argument_print */ TEST(t_dlt_message_argument_print, normal) { DltFile file; /* Get PWD so file can be used*/ char pwd[MAX_LINE]; char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)]; /* ignore returned value from getcwd */ if (getcwd(pwd, MAX_LINE) == NULL) {} sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); static char text[DLT_DAEMON_TEXTSIZE]; /*---------------------------------------*/ uint8_t *ptr; int32_t datalength; uint8_t **pptr; int32_t *pdatalength; /* Normal Use-Case, expect 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); ptr = file.msg.databuffer; datalength = file.msg.datasize; pptr = &ptr; pdatalength = &datalength; EXPECT_GE(DLT_RETURN_OK, dlt_message_argument_print(&file.msg, DLT_TYPE_INFO_BOOL, pptr, pdatalength, text, DLT_DAEMON_TEXTSIZE, 0, 1)); /*printf("### ARGUMENT:%s\n", text); */ } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); ptr = file.msg.databuffer; datalength = file.msg.datasize; pptr = &ptr; pdatalength = &datalength; EXPECT_GE(DLT_RETURN_OK, dlt_message_argument_print(&file.msg, DLT_TYPE_INFO_RAWD, pptr, pdatalength, text, DLT_DAEMON_TEXTSIZE, 0, 1)); /*printf("### ARGUMENT:%s\n", text); */ } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_argument_print, abnormal) { /* DltFile file; */ /* Get PWD so file and filter can be used */ /* char pwd[MAX_LINE]; */ /* getcwd(pwd, MAX_LINE); */ /* char openfile[MAX_LINE+sizeof(BINARY_FILE_NAME)];; */ /* sprintf(openfile, "%s" BINARY_FILE_NAME, pwd); */ /* static char text[DLT_DAEMON_TEXTSIZE]; */ /*---------------------------------------*/ /* uint8_t *ptr; */ /* int32_t datalength; */ /* uint8_t **pptr; */ /* int32_t *pdatalength; */ /* Uninizialised, expected -1 */ /* EXPECT_GE(DLT_RETURN_ERROR, dlt_message_argument_print(&file.msg,12345678,pptr,pdatalength,text,DLT_DAEMON_TEXTSIZE,0,1)); */ /* Use a non defined type_info, expected -1 */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); */ /* EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); */ /* while (dlt_file_read(&file,0)>=0){} */ /* for(int i=0;i|"; */ /* char text3[DLT_DAEMON_TEXTSIZE]; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_hex_string(text3,DLT_DAEMON_TEXTSIZE,(unsigned char *)test3, strlen(test3))); */ /*printf("text:%s\n", text3); */ /* convert text3 to an ascii string to compare with the original */ /* char * converted = (char*) malloc(strlen(test3) +1); */ /* int t = 0; */ /* for(unsigned int i=0;i|"; */ /* char text5[DLT_DAEMON_TEXTSIZE]; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_mixed_string(text5,DLT_DAEMON_TEXTSIZE,(unsigned char *)test5,strlen(test5),0)); */ /* printf("%s\n", text5); */ /* const char * test6 = "^°!\"§$%&/()=?`´¹²³¼½¬{[]}\\¸@€üöä+#*'~`,.-;:_·…–<>|"; */ /* char text6[DLT_DAEMON_TEXTSIZE]; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_mixed_string(text6,DLT_DAEMON_TEXTSIZE,(unsigned char *)test6,strlen(test6),1)); */ /* printf("%s\n", text6); */ /* const char * test7 = ""; */ /* char text7[DLT_DAEMON_TEXTSIZE]; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_mixed_string(text7,DLT_DAEMON_TEXTSIZE,(unsigned char *)test7,strlen(test7),0)); */ /* printf("%s\n", text7); */ /* const char * test8 = ""; */ /* char text8[DLT_DAEMON_TEXTSIZE]; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_mixed_string(text8,DLT_DAEMON_TEXTSIZE,(unsigned char *)test8,strlen(test8),1)); */ /* printf("%s\n", text8); */ } TEST(t_dlt_print_mixed_string, nullpointer) { const char *test9 = ""; char text9[DLT_DAEMON_TEXTSIZE]; EXPECT_GE(DLT_RETURN_ERROR, dlt_print_mixed_string(NULL, 0, 0, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_mixed_string(NULL, 0, 0, 0, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_mixed_string(NULL, 0, (unsigned char *)test9, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_mixed_string(NULL, 0, (unsigned char *)test9, 0, 1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_mixed_string(text9, 0, NULL, 0, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_mixed_string(text9, 0, NULL, 0, 1)); } /* End Method:dlt_common::dlt_print_mixed_string */ /* Begin Method:dlt_common::dlt_print_char_string */ TEST(t_dlt_print_char_string, normal) { /* Normal Use-Case, expect 0 */ const char *test1 = "HELLO"; char text1[DLT_DAEMON_TEXTSIZE]; char *ptr1 = text1; EXPECT_LE(DLT_RETURN_OK, dlt_print_char_string(&ptr1, DLT_DAEMON_TEXTSIZE, (unsigned char *)test1, strlen(test1))); printf("text:%s\n", text1); EXPECT_STREQ(text1, test1); const char *test2 = "qwertzuiopasdfghjklyxcvbnm1234567890"; char text2[DLT_DAEMON_TEXTSIZE]; char *ptr2 = text2; EXPECT_LE(DLT_RETURN_OK, dlt_print_char_string(&ptr2, DLT_DAEMON_TEXTSIZE, (unsigned char *)test2, strlen(test2))); printf("text:%s\n", text2); EXPECT_STREQ(text2, test2); } TEST(t_dlt_print_char_string, abnormal) { /* print special characters, expected 0 */ /* const char * test3 = "^°!\"§$%&/()=?`´¹²³¼½¬{[]}\\¸@€üöä+#*'~`,.-;:_·…–<>|"; */ /* char text3[DLT_DAEMON_TEXTSIZE]; */ /* char * ptr3 = text3; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_char_string(&ptr3,DLT_DAEMON_TEXTSIZE,(unsigned char *)test3, strlen(test3))); */ /* printf("text:%s\n", text3); */ /* EXPECT_STREQ(text3, test3); */ /* Empty char *, expect 0 */ /* const char * test4 = ""; */ /* char text4[DLT_DAEMON_TEXTSIZE]; */ /* char * ptr4 = text4; */ /* EXPECT_LE(DLT_RETURN_OK, dlt_print_char_string(&ptr4,DLT_DAEMON_TEXTSIZE,(unsigned char *)test4, strlen(test4))); */ /* printf("text:%s\n", text4); */ /* EXPECT_STREQ(text4, test4); */ } TEST(t_dlt_print_char_string, nullpointer) { const char *test5 = "HELLO"; char text5[DLT_DAEMON_TEXTSIZE]; char *ptr5 = text5; EXPECT_GE(DLT_RETURN_ERROR, dlt_print_char_string(NULL, 0, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_char_string(NULL, 0, (unsigned char *)test5, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_print_char_string(&ptr5, 0, NULL, 0)); } /* End Method:dlt_common::dlt_print_char_string */ /* Begin Method:dlt_common::dlt_strnlen_s*/ TEST(t_dlt_strnlen_s, nullpointer) { size_t len = dlt_strnlen_s(NULL, 0); EXPECT_EQ(len, 0); } TEST(t_dlt_strnlen_s, len_zero) { const char text[] = "The Quick Brown Fox"; size_t len = dlt_strnlen_s(text, 0); EXPECT_EQ(len, 0); } TEST(t_dlt_strnlen_s, len_smaller) { const char text[] = "The Quick Brown Fox"; size_t len = dlt_strnlen_s(text, 10); EXPECT_EQ(len, 10); } TEST(t_dlt_strnlen_s, len_equal) { const char text[] = "The Quick Brown Fox"; size_t len = dlt_strnlen_s(text, 19); EXPECT_EQ(len, 19); } TEST(t_dlt_strnlen_s, len_larger) { const char text[] = "The Quick Brown Fox"; size_t len = dlt_strnlen_s(text, 100); EXPECT_EQ(len, 19); } /* End Method:dlt_common::dlt_strnlen_s*/ /* Begin Method:dlt_common::dlt_print_id */ TEST(t_dlt_print_id, normal) { /* Normal Use-Case, expect text==id */ const char *id = "DLTD"; char text[DLT_DAEMON_TEXTSIZE]; dlt_print_id(text, id); EXPECT_STREQ(text, id); } TEST(t_dlt_print_id, abnormal) { /* id to long, expect only first 4 chars */ /* const char* id = "DLTD123456789"; */ /* char text[DLT_DAEMON_TEXTSIZE]; */ /* dlt_print_id(text,id); */ /* EXPECT_STREQ(text,"DLTD"); */ /* id to short, expect expend with "-" to 4 chars */ /* id = "DL"; */ /* dlt_print_id(text,id); */ /* EXPECT_STREQ(text,"DL--"); */ } TEST(t_dlt_print_id, nullpointer) { const char *id = "DLTD"; char text[DLT_DAEMON_TEXTSIZE]; /* NULL-Pointer, expected nothing in return */ EXPECT_NO_THROW(dlt_print_id(NULL, NULL)); EXPECT_NO_THROW(dlt_print_id(NULL, id)); EXPECT_NO_THROW(dlt_print_id(text, NULL)); } /* End Method:dlt_common::dlt_print_id */ /* Begin Method:dlt_common::dlt_get_version */ TEST(t_dlt_get_version, normal) { /* Normal Use-Case */ char ver[255]; dlt_get_version(ver, 255); printf("%s\n", ver); } TEST(t_dlt_get_version, abnormal) { /* Change default length of ver to 1 */ /* char ver[1]; */ /* dlt_get_version(ver, DLT_USER_MAX_LIB_VERSION_LENGTH); */ /* printf("%s\n", ver); */ /* Change default length of ver to 1 and reduce second para to 1, too */ /* dlt_get_version(ver, 1); */ /* printf("%s\n", ver); */ } TEST(t_dlt_get_version, nullpointer) { EXPECT_NO_THROW(dlt_get_version(NULL, 0)); } /* End Method:dlt_common::dlt_get_version */ /* Begin Method:dlt_common::dlt_get_major_version */ TEST(dlt_get_major_version, normal) { char ver[DLT_USER_MAX_LIB_VERSION_LENGTH]; dlt_get_major_version(ver, DLT_USER_MAX_LIB_VERSION_LENGTH); EXPECT_STREQ(ver, _DLT_PACKAGE_MAJOR_VERSION); } TEST(dlt_get_major_version, abnormal) { /* Change default length of ver to 1 */ /* char ver[1]; */ /* dlt_get_major_version(ver, DLT_USER_MAX_LIB_VERSION_LENGTH); */ /* EXPECT_STREQ(ver, _DLT_PACKAGE_MAJOR_VERSION); */ /* Change default length of ver to 1 and reduce second para to 1, too */ /* dlt_get_major_version(ver, 1); */ /* EXPECT_STREQ(ver, _DLT_PACKAGE_MAJOR_VERSION); */ } TEST(dlt_get_major_version, nullpointer) { /* NULL-Pointer, expect exeption */ EXPECT_NO_THROW(dlt_get_major_version(NULL, 0)); } /* End Method:dlt_common::dlt_get_major_version */ /* Begin Method:dlt_common::dlt_get_minor_version */ TEST(dlt_get_minor_version, normal) { char ver[DLT_USER_MAX_LIB_VERSION_LENGTH]; dlt_get_minor_version(ver, DLT_USER_MAX_LIB_VERSION_LENGTH); EXPECT_STREQ(ver, _DLT_PACKAGE_MINOR_VERSION); } TEST(dlt_get_minor_version, abnormal) { /* Change default length of ver to 1 */ /* char ver[1]; */ /* dlt_get_minor_version(ver, DLT_USER_MAX_LIB_VERSION_LENGTH); */ /* EXPECT_STREQ(ver, _DLT_PACKAGE_MINOR_VERSION); */ /* Change default length of ver to 1 and reduce second para to 1, too */ /* dlt_get_minor_version(ver, 1); */ /* EXPECT_STREQ(ver, _DLT_PACKAGE_MINOR_VERSION); */ } TEST(dlt_get_minor_version, nullpointer) { /* NULL-Pointer, expect exeption */ EXPECT_NO_THROW(dlt_get_minor_version(NULL, 0)); } /* End Method:dlt_common::dlt_get_minor_version */ TEST(dlt_client_parse_get_log_info_resp_text, normal) { char input[] = "get_log_info, 07, 02 00 4c 4f 47 00 03 00 54 45 53 54 ff ff 18 00 54 65 73 74 20 43 6f 6e 74 65 78 74 20 66 6f 72 20 4c 6f 67 67 69 6e 67 54 53 31 00 ff ff 1b 00 54 65 73 74 20 43 6f 6e 74 65 78 74 31 20 66 6f 72 20 69 6e 6a 65 63 74 69 6f 6e 54 53 32 00 ff ff 1b 00 54 65 73 74 20 43 6f 6e 74 65 78 74 32 20 66 6f 72 20 69 6e 6a 65 63 74 69 6f 6e 1c 00 54 65 73 74 20 41 70 70 6c 69 63 61 74 69 6f 6e 20 66 6f 72 20 4c 6f 67 67 69 6e 67 53 59 53 00 02 00 4a 4f 55 52 ff ff 0f 00 4a 6f 75 72 6e 61 6c 20 41 64 61 70 74 65 72 4d 47 52 00 ff ff 22 00 43 6f 6e 74 65 78 74 20 6f 66 20 6d 61 69 6e 20 64 6c 74 20 73 79 73 74 65 6d 20 6d 61 6e 61 67 65 72 12 00 44 4c 54 20 53 79 73 74 65 6d 20 4d 61 6e 61 67 65 72 72 65 6d 6f"; /* expected output: * APID:LOG- Test Application for Logging * CTID:TEST -1 -1 Test Context for Logging * CTID:TS1- -1 -1 Test Context1 for injection * CTID:TS2- -1 -1 Test Context2 for injection * APID:SYS- DLT System Manager * CTID:JOUR -1 -1 Journal Adapter * CTID:MGR- -1 -1 Context of main dlt system manager */ DltServiceGetLogInfoResponse * resp = (DltServiceGetLogInfoResponse *)malloc(sizeof(DltServiceGetLogInfoResponse )); DltReturnValue ret = (DltReturnValue) dlt_set_loginfo_parse_service_id( input, &resp->service_id, &resp->status); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(DLT_SERVICE_ID_GET_LOG_INFO, resp->service_id); EXPECT_EQ(GET_LOG_INFO_STATUS_MAX, resp->status); ret = dlt_client_parse_get_log_info_resp_text(resp, input); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(2,resp->log_info_type.count_app_ids); EXPECT_EQ(0, memcmp( "LOG", resp->log_info_type.app_ids[0].app_id,4)); EXPECT_EQ(0, strcmp("Test Application for Logging", resp->log_info_type.app_ids[0].app_description)); EXPECT_EQ(28, resp->log_info_type.app_ids[0].len_app_description); EXPECT_EQ(3, resp->log_info_type.app_ids[0].count_context_ids); EXPECT_EQ(0, memcmp( "TEST", resp->log_info_type.app_ids[0].context_id_info[0].context_id,4)); EXPECT_EQ(0, strcmp( "Test Context for Logging",resp->log_info_type.app_ids[0].context_id_info[0].context_description )); EXPECT_EQ(24,resp->log_info_type.app_ids[0].context_id_info[0].len_context_description); EXPECT_EQ(-1,resp->log_info_type.app_ids[0].context_id_info[0].log_level); EXPECT_EQ(-1,resp->log_info_type.app_ids[0].context_id_info[0].trace_status); EXPECT_EQ(0, memcmp( "TS1", resp->log_info_type.app_ids[0].context_id_info[1].context_id,4)); EXPECT_EQ(0, strcmp( "Test Context1 for injection",resp->log_info_type.app_ids[0].context_id_info[1].context_description )); EXPECT_EQ(27,resp->log_info_type.app_ids[0].context_id_info[1].len_context_description); EXPECT_EQ(-1,resp->log_info_type.app_ids[0].context_id_info[1].log_level); EXPECT_EQ(-1,resp->log_info_type.app_ids[0].context_id_info[1].trace_status); EXPECT_EQ(0, memcmp( "TS2", resp->log_info_type.app_ids[0].context_id_info[2].context_id,4)); EXPECT_EQ(0, strcmp( "Test Context2 for injection",resp->log_info_type.app_ids[0].context_id_info[2].context_description )); EXPECT_EQ(27,resp->log_info_type.app_ids[0].context_id_info[2].len_context_description); EXPECT_EQ(-1,resp->log_info_type.app_ids[0].context_id_info[2].log_level); EXPECT_EQ(-1,resp->log_info_type.app_ids[0].context_id_info[2].trace_status); EXPECT_EQ(0, memcmp( "SYS", resp->log_info_type.app_ids[1].app_id,4)); EXPECT_EQ(0, strcmp("DLT System Manager", resp->log_info_type.app_ids[1].app_description)); EXPECT_EQ(18, resp->log_info_type.app_ids[1].len_app_description); EXPECT_EQ(2, resp->log_info_type.app_ids[1].count_context_ids); EXPECT_EQ(0, memcmp( "JOUR", resp->log_info_type.app_ids[1].context_id_info[0].context_id,4)); EXPECT_EQ(0, strcmp( "Journal Adapter",resp->log_info_type.app_ids[1].context_id_info[0].context_description )); EXPECT_EQ(15,resp->log_info_type.app_ids[1].context_id_info[0].len_context_description); EXPECT_EQ(-1,resp->log_info_type.app_ids[1].context_id_info[0].log_level); EXPECT_EQ(-1,resp->log_info_type.app_ids[1].context_id_info[0].trace_status); EXPECT_EQ(0, memcmp( "MGR", resp->log_info_type.app_ids[1].context_id_info[1].context_id,4)); EXPECT_EQ(0, strcmp( "Context of main dlt system manager",resp->log_info_type.app_ids[1].context_id_info[1].context_description )); EXPECT_EQ(34,resp->log_info_type.app_ids[1].context_id_info[1].len_context_description); EXPECT_EQ(-1,resp->log_info_type.app_ids[1].context_id_info[1].log_level); EXPECT_EQ(-1,resp->log_info_type.app_ids[1].context_id_info[1].trace_status); ret = (DltReturnValue)dlt_client_cleanup_get_log_info(resp); EXPECT_EQ(DLT_RETURN_OK,ret); } TEST(dlt_getloginfo_conv_ascii_to_string, normal) { /* NULL-Pointer, expect exeption */ char rp_1[] = "72 65 6d 6f"; char rp_2[] = "123456789 72 65 6d 6f"; int rp_count = 0; char rp_str[] = { 0x72, 0x65, 0x6d, 0x6f, 0x00 }; char wp[5]; dlt_getloginfo_conv_ascii_to_string(rp_1, &rp_count, wp, 4); EXPECT_EQ(0, strcmp(rp_str, wp)); EXPECT_EQ(12, rp_count); rp_count = 10; dlt_getloginfo_conv_ascii_to_string(rp_2, &rp_count, wp, 4); EXPECT_EQ(0, strcmp(rp_str, wp)); EXPECT_EQ(22, rp_count); } /*##############################################################################################################################*/ /*##############################################################################################################################*/ /*##############################################################################################################################*/ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_break_on_failure = true; /*::testing::FLAGS_gtest_filter = "*.normal"; */ return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/gtest_dlt_daemon_common.cpp000066400000000000000000002337131446635226000224620ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Stefan Held * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file gtest_dlt_common.cpp */ #include #include extern "C" { #include "dlt_daemon_common.h" #include "dlt_daemon_common_cfg.h" #include "dlt_user_shared_cfg.h" #include "errno.h" #include #include "dlt_types.h" #include "dlt-daemon.h" #include "dlt-daemon_cfg.h" #include "dlt_daemon_common_cfg.h" #include "dlt_daemon_socket.h" #include "dlt_daemon_serial.h" #include "dlt_daemon_client.h" #include "dlt_offline_trace.h" #include "dlt_gateway_types.h" } #ifndef DLT_USER_DIR # define DLT_USER_DIR "/tmp/dltpipes" #endif /* Name of named pipe to DLT daemon */ #ifndef DLT_USER_FIFO # define DLT_USER_FIFO "/tmp/dlt" #endif /* Begin Method:dlt_daemon_common::dlt_daemon_init_user_information */ TEST(t_dlt_daemon_init_user_information, normal_one_list) { DltDaemon daemon; DltGateway gateway; char ecu[] = "ECU1"; EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } /* Begin Method:dlt_daemon_common::dlt_daemon_init_user_information */ TEST(t_dlt_daemon_init_user_information, normal_multiple_lists) { DltDaemon daemon; DltGateway gateway; char ecu[] = "ECU1"; char ecu2[] = "ECU2"; char ecu3[] = "ECU3"; gateway.connections = (DltGatewayConnection *)calloc(2, sizeof(DltGatewayConnection)); gateway.connections[0].ecuid = &ecu2[0]; gateway.connections[1].ecuid = &ecu3[0]; gateway.num_connections = 2; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 1, 0)); EXPECT_EQ(3, daemon.num_user_lists); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_EQ(DLT_RETURN_OK, strncmp(gateway.connections[0].ecuid, daemon.user_list[1].ecu, DLT_ID_SIZE)); EXPECT_EQ(DLT_RETURN_OK, strncmp(gateway.connections[1].ecuid, daemon.user_list[2].ecu, DLT_ID_SIZE)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); free(gateway.connections); } TEST(t_dlt_daemon_init_user_information, nullpointer) { DltDaemon daemon; DltGateway gateway; EXPECT_EQ(-1, dlt_daemon_init_user_information(NULL, NULL, 0, 0)); EXPECT_EQ(-1, dlt_daemon_init_user_information(NULL, &gateway, 0, 0)); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, NULL, 0, 0)); EXPECT_EQ(-1, dlt_daemon_init_user_information(&daemon, NULL, 1, 0)); } /* Begin Method:dlt_daemon_common::dlt_daemon_find_users_list */ TEST(t_dlt_daemon_find_users_list, normal_one_list) { DltDaemon daemon; DltGateway gateway; DltDaemonRegisteredUsers *user_list; char ecu[] = "ECU1"; EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); user_list = dlt_daemon_find_users_list(&daemon, &ecu[0], 0); EXPECT_NE(user_list, nullptr); EXPECT_EQ(DLT_RETURN_OK, strncmp(user_list->ecu, daemon.ecuid, DLT_ID_SIZE)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } /* Begin Method:dlt_daemon_common::dlt_daemon_find_users_list */ TEST(t_dlt_daemon_find_users_list, abnormal) { DltDaemon daemon; DltGateway gateway; DltDaemonRegisteredUsers *user_list; char ecu[] = "ECU1"; char bla[] = "BLAH"; EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); user_list = dlt_daemon_find_users_list(&daemon, bla, 0); EXPECT_EQ(user_list, nullptr); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } /* Begin Method:dlt_daemon_common::dlt_daemon_init_user_information */ TEST(t_dlt_daemon_find_users_list, normal_multiple_lists) { DltDaemon daemon; DltGateway gateway; char ecu[] = "ECU1"; char ecu2[] = "ECU2"; char ecu3[] = "ECU3"; DltDaemonRegisteredUsers *user_list; gateway.connections = (DltGatewayConnection *)calloc(2, sizeof(DltGatewayConnection)); gateway.connections[0].ecuid = &ecu2[0]; gateway.connections[1].ecuid = &ecu3[0]; gateway.num_connections = 2; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 1, 0)); EXPECT_EQ(3, daemon.num_user_lists); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_EQ(DLT_RETURN_OK, strncmp(gateway.connections[0].ecuid, daemon.user_list[1].ecu, DLT_ID_SIZE)); EXPECT_EQ(DLT_RETURN_OK, strncmp(gateway.connections[1].ecuid, daemon.user_list[2].ecu, DLT_ID_SIZE)); user_list = dlt_daemon_find_users_list(&daemon, &ecu[0], 0); EXPECT_NE(user_list, nullptr); EXPECT_EQ(DLT_RETURN_OK, strncmp(user_list->ecu, daemon.ecuid, DLT_ID_SIZE)); user_list = dlt_daemon_find_users_list(&daemon, &ecu2[0], 0); EXPECT_NE(user_list, nullptr); EXPECT_EQ(DLT_RETURN_OK, strncmp(user_list->ecu, gateway.connections[0].ecuid, DLT_ID_SIZE)); user_list = dlt_daemon_find_users_list(&daemon, &ecu3[0], 0); EXPECT_NE(user_list, nullptr); EXPECT_EQ(DLT_RETURN_OK, strncmp(user_list->ecu, gateway.connections[1].ecuid, DLT_ID_SIZE)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); free(gateway.connections); } TEST(t_dlt_daemon_find_users_list, nullpointer) { DltDaemon daemon; char ecu[] = "ECU1"; EXPECT_EQ(NULL, dlt_daemon_find_users_list(NULL, NULL, 0)); EXPECT_EQ(NULL, dlt_daemon_find_users_list(&daemon, NULL, 0)); EXPECT_EQ(NULL, dlt_daemon_find_users_list(NULL, &ecu[0], 0)); } /* Begin Method:dlt_daemon_common::dlt_daemon_application_add */ TEST(t_dlt_daemon_application_add, normal) { DltDaemon daemon; DltGateway gateway; const char *apid = "TEST"; pid_t pid = 0; const char *desc = "HELLO_TEST"; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 15; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); /*printf("### APP: APID=%s DESCR=%s NUMCONTEXT=%i PID=%i USERHANDLE=%i\n", app->apid,app->application_description, app->num_contexts, app->pid, app->user_handle); */ EXPECT_STREQ(apid, app->apid); EXPECT_STREQ(desc, app->application_description); EXPECT_EQ(pid, app->pid); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* Apid > 4, expected truncate to 4 char or error */ apid = "TO_LONG"; app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); char tmp[5]; strncpy(tmp, apid, 4); tmp[4] = '\0'; EXPECT_STREQ(tmp, app->apid); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_application_add, abnormal) { /* DltDaemon daemon; */ /* const char * apid = "TEST"; */ /* pid_t pid = 0; */ /* const char * desc = "HELLO_TEST"; */ /* DltDaemonApplication *app = NULL; */ /* Add the same application with same pid twice */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_LE((DltDaemonApplication *) 0, app); */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_EQ((DltDaemonApplication *) 0, app); */ /* dlt_daemon_application_del(&daemon,app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Add the same applicaiotn with different pid */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, 0, (char *) desc, 0); */ /* EXPECT_LE((DltDaemonApplication *) 0, app); */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, 123, (char *) desc, 0); */ /* EXPECT_EQ((DltDaemonApplication *) 0, app); */ /* dlt_daemon_application_del(&daemon,app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* verbose value != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 12345678)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Apid < 4, expected fill to 4 chars or error */ /* apid = "SH"; */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* char tmp[5]; */ /* strncpy(tmp, apid, 4); */ /* tmp[4] = '\0'; */ /* EXPECT_STREQ(tmp, app->apid); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_application_add, nullpointer) { DltDaemon daemon; const char *apid = "TEST"; const char *desc = "HELLO_TEST"; int fd = 42; char ecu[] = "ECU1"; /* NULL-Pointer test */ EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(NULL, NULL, 0, NULL, 0, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(NULL, NULL, 0, (char *)desc, 0, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(NULL, (char *)apid, 0, NULL, 0, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(NULL, (char *)apid, 0, (char *)desc, 0, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(&daemon, NULL, 0, NULL, 0, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(&daemon, NULL, 0, (char *)desc, 0, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(NULL, NULL, 0, NULL, fd, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_add(NULL, NULL, 0, NULL, 0, ecu, 0)); } /* End Method:dlt_daemon_common::dlt_daemon_application_add */ /* Begin Method: dlt_daemon_common::dlt_daemon_application_del */ TEST(t_dlt_daemon_application_del, normal) { DltDaemon daemon; DltGateway gateway; const char *apid = "TEST"; pid_t pid = 0; const char *desc = "HELLO_TEST"; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case, retrun type cannot be tested, only apid and desc */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_application_del, abnormal) { /* DltDaemon daemon; */ /* const char * apid = "TEST"; */ /* pid_t pid = 0; */ /* const char * desc = "HELLO_TEST"; */ /* DltDaemonApplication *app = NULL; */ /* no application exists, expect < 0 */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_application_del(&daemon, app, 0)); */ /* Call delete two times */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_LE(0, dlt_daemon_application_del(&daemon,app, 0)); */ /* EXPECT_GE(-1, dlt_daemon_application_del(&daemon,app, 0)); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Verbose parameter != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_application_del(&daemon,app, 123456789)); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_application_del, nullpointer) { DltDaemon daemon; DltDaemonApplication app; char ecu[] = "ECU1"; /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_application_del(NULL, NULL, NULL, 0)); EXPECT_GE(-1, dlt_daemon_application_del(NULL, &app, NULL, 0)); EXPECT_GE(-1, dlt_daemon_application_del(&daemon, NULL, ecu, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_application_del */ /* Begin Method: dlt_daemon_common::dlt_daemon_applikation_find */ TEST(t_dlt_daemon_application_find, normal) { DltDaemon daemon; DltGateway gateway; const char *apid = "TEST"; pid_t pid = 0; const char *desc = "HELLO_TEST"; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); EXPECT_STREQ(apid, app->apid); EXPECT_STREQ(desc, app->application_description); EXPECT_EQ(pid, app->pid); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* Application doesn't exist, expect NULL */ EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_find(&daemon, ecu, (char *)apid, 0)); /* Use a different apid, expect NULL */ app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); EXPECT_LE((DltDaemonApplication *)0, dlt_daemon_application_find(&daemon, ecu, (char *)apid, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_find(&daemon, ecu, (char *)"NEXI", 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_application_find, abnormal) { /* DltDaemon daemon; */ /* const char * apid = "TEST"; */ /* pid_t pid = 0; */ /* const char * desc = "HELLO_TEST"; */ /* DltDaemonApplication *app = NULL; */ /* Verbose != 0 or 1, expect error */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* dlt_daemon_application_find(&daemon, (char *) apid, 0); */ /* EXPECT_EQ((DltDaemonApplication *) 0, dlt_daemon_application_find(&daemon, (char *) apid, 123456789)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_application_find, nullpointer) { DltDaemon daemon; const char *apid = "TEST"; /* NULL-Pointer, expected NULL */ EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_find(NULL, NULL, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_find(NULL, (char *)apid, NULL, 0)); EXPECT_EQ((DltDaemonApplication *)0, dlt_daemon_application_find(&daemon, NULL, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_applikation_find */ /* Begin Method: dlt_daemon_common::dlt_daemon_applications_clear */ TEST(t_dlt_daemon_applications_clear, normal) { DltDaemon daemon; DltGateway gateway; pid_t pid = 0; char ecu[] = "ECU1"; int fd = 42; /* Normal Use Case, expect >= 0 */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_LE((DltDaemonApplication *)0, dlt_daemon_application_add(&daemon, (char *)"TES1", pid, (char *)"Test clear 1", fd, ecu, 0)); dlt_daemon_application_add(&daemon, (char *)"TES2", pid, (char *)"Test clear 2", fd, ecu, 0); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_applications_clear, abnormal) { /* DltDaemon daemon; */ /* pid_t pid = 0; */ /* No applications added, expect < -1 */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_applications_clear(&daemon, 0)); */ /* Verbose != 0 or 1, expect error */ /* dlt_daemon_application_add(&daemon, (char *) "TEST", pid, (char *) "Test clear", 0); */ /* EXPECT_GE(-1, dlt_daemon_applications_clear(&daemon, 123456789)); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_applications_clear, nullpointer) { /* NULL-Pointer, expect < 0 */ EXPECT_GE(-1, dlt_daemon_applications_clear(NULL, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_applications_clear */ /* Begin Method: dlt_daemon_common::dlt_daemon_applications_invalidate_fd */ TEST(t_dlt_daemon_applications_invalidate_fd, normal) { DltDaemon daemon; DltGateway gateway; const char *apid = "TEST"; pid_t pid = 0; const char *desc = "HELLO_TEST"; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); EXPECT_LE(0, dlt_daemon_applications_invalidate_fd(&daemon, ecu, app->user_handle, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_applications_invalidate_fd, abnormal) { /* DltDaemon daemon; */ /* const char * apid = "TEST"; */ /* pid_t pid = 0; */ /* const char * desc = "HELLO_TEST"; */ /* DltDaemonApplication *app = NULL; */ /* Daemon isn't initialized, expected error */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_applications_invalidate_fd(&daemon, 0, 0)); */ /* Verbose != 0 or 1, expect error */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_applications_invalidate_fd(&daemon, app->user_handle, 123456789)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_applications_invalidate_fd, nullpointer) { /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_applications_invalidate_fd(NULL, NULL, 0, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_applications_invalidate_fd */ /* Begin Method: dlt_daemon_common::dlt_daemon_applications_save */ TEST(t_dlt_daemon_applications_save, normal) { DltDaemon daemon; DltGateway gateway; const char *apid = "TEST"; pid_t pid = 0; const char *desc = "HELLO_TEST"; DltDaemonApplication *app = NULL; const char *filename = "/tmp/dlt-runtime.cfg"; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, (char *)apid, pid, (char *)desc, fd, ecu, 0); EXPECT_LE(0, dlt_daemon_applications_save(&daemon, (char *)filename, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_applications_save, abnormal) { /* DltDaemon daemon; */ /* const char * apid = "TEST"; */ /* pid_t pid = 0; */ /* const char * desc = "HELLO_TEST"; */ /* DltDaemonApplication *app = NULL; */ /* const char * filename = "/tmp/dlt-runtime.cfg"; */ /* Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_applications_save(&daemon, (char *) filename, 0)); */ /* Verbose != 1 or 0, expect error */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_applications_save(&daemon, (char *) filename, 123456789)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Wrong path filename */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_applications_save(&daemon, (char *) "PATH_DONT_EXIST", 0)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_applications_save, nullpointer) { DltDaemon daemon; const char *filename = "/tmp/dlt-runtime.cfg"; /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_applications_save(NULL, NULL, 0)); EXPECT_GE(-1, dlt_daemon_applications_save(NULL, (char *)filename, 0)); EXPECT_GE(-1, dlt_daemon_applications_save(&daemon, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_applications_save */ /* Begin Method: dlt_daemon_common::dlt_daemon_applications_load */ TEST(t_dlt_daemon_applications_load, normal) { DltDaemon daemon; DltGateway gateway; char ecu[] = "ECU1"; const char *filename = "/tmp/dlt-runtime.cfg"; /* Normal Use-Case, first execute t_dlt_daemon_applications_save !! */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_LE(0, dlt_daemon_applications_load(&daemon, (char *)filename, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_applications_load, abnormal) { /* DltDaemon daemon; */ /* const char * apid = "TEST"; */ /* pid_t pid = 0; */ /* const char * desc = "HELLO_TEST"; */ /* DltDaemonApplication *app = NULL; */ /* const char * filename = "/tmp/dlt-runtime.cfg"; */ /* Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_applications_load(&daemon, (char *) filename, 0)); */ /* Verbose != 1 or 0, expect error */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_applications_load(&daemon, (char *) filename, 123456789)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Wrong path filename */ /* app = dlt_daemon_application_add(&daemon,(char *) apid, pid, (char *) desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_applications_load(&daemon, (char *) "PATH_DONT_EXIST", 0)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_applications_load, nullpointer) { DltDaemon daemon; const char *filename = "/tmp/dlt-runtime.cfg"; /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_applications_load(NULL, NULL, 0)); EXPECT_GE(-1, dlt_daemon_applications_load(NULL, (char *)filename, 0)); EXPECT_GE(-1, dlt_daemon_applications_load(&daemon, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_applications_load */ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /* Begin Method: dlt_daemon_common::dlt_daemon_context_add */ TEST(t_dlt_daemon_context_add, normal) { /* Log Level */ /* DLT_LOG_DEFAULT = -1, / **< Default log level * / */ /* DLT_LOG_OFF = 0x00, / **< Log level off * / */ /* DLT_LOG_FATAL = 0x01, / **< fatal system error * / */ /* DLT_LOG_ERROR = 0x02, / **< error with impact to correct functionality * / */ /* DLT_LOG_WARN = 0x03, / **< warning, correct behaviour could not be ensured * / */ /* DLT_LOG_INFO = 0x04, / **< informational * / */ /* DLT_LOG_DEBUG = 0x05, / **< debug * / */ /* DLT_LOG_VERBOSE = 0x06 / **< highest grade of information * / */ /* Trace Status */ /* DLT_TRACE_STATUS_DEFAULT = -1, / **< Default trace status * / */ /* DLT_TRACE_STATUS_OFF = 0x00, / **< Trace status: Off * / */ /* DLT_TRACE_STATUS_ON = 0x01 / **< Trace status: On * / */ DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); /*printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ EXPECT_STREQ(apid, daecontext->apid); EXPECT_STREQ(ctid, daecontext->ctid); EXPECT_STREQ(desc, daecontext->context_description); EXPECT_EQ(DLT_LOG_DEFAULT, daecontext->log_level); EXPECT_EQ(DLT_TRACE_STATUS_DEFAULT, daecontext->trace_status); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_context_add, abnormal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Log Level dont exists */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); DltLogLevelType DLT_LOG_NOT_EXIST = (DltLogLevelType) - 100; app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_NOT_EXIST, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); /*printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ EXPECT_EQ((DltDaemonContext *)0, daecontext); EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* Trace Status dont exists */ DltTraceStatusType DLT_TRACE_TYPE_NOT_EXIST = (DltTraceStatusType) - 100; app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_TYPE_NOT_EXIST, 0, 0, desc, ecu, 0); /*printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ EXPECT_EQ((DltDaemonContext *)0, daecontext); EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* Apid to long */ /* char apid_tl[8] = "TO_LONG"; */ /* app = dlt_daemon_application_add(&daemon, apid_tl, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid_tl,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ /* EXPECT_STREQ(apid_tl, daecontext->apid); */ /* EXPECT_STREQ(ctid, daecontext->ctid); */ /* EXPECT_STREQ(desc, daecontext->context_description); */ /* EXPECT_EQ(DLT_LOG_DEFAULT, daecontext->log_level); */ /* EXPECT_EQ(DLT_TRACE_STATUS_DEFAULT, daecontext->trace_status); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Apid to short */ /* char apid_ts[3] = "TS"; */ /* app = dlt_daemon_application_add(&daemon, apid_ts, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid_ts,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* //printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ /* EXPECT_STREQ(apid_ts, daecontext->apid); */ /* EXPECT_STREQ(ctid, daecontext->ctid); */ /* EXPECT_STREQ(desc, daecontext->context_description); */ /* EXPECT_EQ(DLT_LOG_DEFAULT, daecontext->log_level); */ /* EXPECT_EQ(DLT_TRACE_STATUS_DEFAULT, daecontext->trace_status); */ /* //EXPECT_EQ(4, strlen(apid_ts)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Ctid to long */ /* char ctid_tl[8] = "TO_LONG"; */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid_tl,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* //printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ /* EXPECT_STREQ(apid, daecontext->apid); */ /* EXPECT_STREQ(ctid_tl, daecontext->ctid); */ /* EXPECT_STREQ(desc, daecontext->context_description); */ /* EXPECT_EQ(DLT_LOG_DEFAULT, daecontext->log_level); */ /* EXPECT_EQ(DLT_TRACE_STATUS_DEFAULT, daecontext->trace_status); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Ctid to short */ /* char ctid_ts[4] = "TS"; */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid_ts,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* //printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ /* EXPECT_STREQ(apid, daecontext->apid); */ /* EXPECT_STREQ(ctid_ts, daecontext->ctid); */ /* EXPECT_STREQ(desc, daecontext->context_description); */ /* EXPECT_EQ(DLT_LOG_DEFAULT, daecontext->log_level); */ /* EXPECT_EQ(DLT_TRACE_STATUS_DEFAULT, daecontext->trace_status); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Verbose != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,123456789); */ /* //printf("### CONTEXT: APID=%s\tCTID=%s\n", daecontext->apid,daecontext->ctid); */ /* EXPECT_EQ((DltDaemonContext *) 0, daecontext); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_context_add, nullpointer) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char ecu[] = "ECU1"; char desc[255] = "TEST dlt_daemon_context_add"; /* NULL-Pointer */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, NULL, NULL, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, NULL, ctid, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, NULL, ctid, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, apid, NULL, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, apid, NULL, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, apid, ctid, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(NULL, apid, ctid, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, NULL, NULL, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, NULL, ctid, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, NULL, ctid, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, apid, NULL, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, apid, NULL, 0, 0, 0, 0, desc, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_add(&daemon, apid, ctid, 0, 0, 0, 0, NULL, NULL, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_context_add */ /* Begin Method: dlt_daemon_common::dlt_daemon_context_del */ TEST(t_dlt_daemon_context_del, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_context_del, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext; */ /* DltDaemonApplication *app; */ /* Context uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, 0)); */ /* No application used */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, 0)); */ /* EXPECT_GE(-1, dlt_daemon_application_del(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, 0)); */ /* EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, 0)); */ /* No contex added */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, 0)); */ /* EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, 0)); */ /* EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, 0)); */ /* Verbose != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, 123456789)); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_context_del, nullpointer) { DltDaemon daemon; DltDaemonContext daecontext; char ecu[] = "ECU1"; /*NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_context_del(NULL, NULL, ecu, 0)); EXPECT_GE(-1, dlt_daemon_context_del(NULL, &daecontext, NULL, 0)); EXPECT_GE(-1, dlt_daemon_context_del(&daemon, NULL, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_context_del */ /* Begin Method: dlt_daemon_common::dlt_daemon_context_find */ TEST(t_dlt_daemon_context_find, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_STREQ(apid, daecontext->apid); EXPECT_STREQ(ctid, daecontext->ctid); EXPECT_STREQ(desc, daecontext->context_description); EXPECT_EQ(DLT_LOG_DEFAULT, daecontext->log_level); EXPECT_EQ(DLT_TRACE_STATUS_DEFAULT, daecontext->trace_status); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_context_find, abnormal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Uninitialized */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, apid, ctid, ecu, 0)); /* No apid */ char no_apid[1] = ""; app = dlt_daemon_application_add(&daemon, no_apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, no_apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, no_apid, ctid, ecu, 0)); EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_GE(-1, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* No ctid */ char no_ctid[1] = ""; app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, no_ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, apid, no_ctid, ecu, 0)); EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* No application added */ daecontext = dlt_daemon_context_add(&daemon, no_apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, no_apid, ctid, ecu, 0)); EXPECT_GE(-1, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); /* Verbose != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_EQ((DltDaemonContext *) 0 ,dlt_daemon_context_find(&daemon, apid, ctid, 123456789)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_context_find, nullpointer) { DltDaemon daemon; ID4 apid = "TES"; ID4 ctid = "CON"; ID4 ecu = "ECU"; EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(NULL, NULL, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(NULL, NULL, ctid, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(NULL, apid, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(NULL, apid, ctid, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, NULL, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, NULL, ctid, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, apid, NULL, NULL, 0)); EXPECT_EQ((DltDaemonContext *)0, dlt_daemon_context_find(&daemon, NULL, NULL, ecu, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_context_find */ /* Begin Method: dlt_daemon_common::dlt_daemon_contexts_clear */ TEST(t_dlt_daemon_contexts_clear, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_contexts_clear, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext = NULL; */ /* DltDaemonApplication *app = NULL; */ /* No context added */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_contexts_clear(&daemon, 0)); */ /* Verbose != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, 123456789)); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_contexts_clear, nullpointer) { /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_contexts_clear(NULL, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_contexts_clear */ /* Begin Method: dlt_daemon_common::dlt_daemon_contexts_invalidate_fd */ TEST(t_dlt_daemon_contexts_invalidate_fd, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_LE(0, dlt_daemon_contexts_invalidate_fd(&daemon, ecu, app->user_handle, 0)); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_contexts_invalidate_fd, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext = NULL; */ /* DltDaemonApplication *app = NULL; */ /* Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_contexts_invalidate_fd(&daemon, app->user_handle, 0)); */ /* Verbose != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_contexts_invalidate_fd(&daemon, app->user_handle, 123456789)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_contexts_invalidate_fd, nullpointer) { /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_contexts_invalidate_fd(NULL, NULL, 0, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_contexts_invalidate_fd */ /* Begin Method: dlt_daemon_common::dlt_daemon_contexts_save */ TEST(t_dlt_daemon_contexts_save, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; const char *filename = "/tmp/dlt-runtime-context.cfg"; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_LE(0, dlt_daemon_contexts_save(&daemon, filename, 0)); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_contexts_save, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext = NULL; */ /* DltDaemonApplication *app = NULL; */ /* const char * filename = "/tmp/dlt-runtime-context.cfg"; */ /* Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_contexts_save(&daemon, filename, 0)); */ /* Verbose != 1 or 0, expect error */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_contexts_save(&daemon, filename, 123456789)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Wrong path filename */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_contexts_save(&daemon, (char *) "PATCH_NOT_EXISTS", 0)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_contexts_save, nullpointer) { DltDaemon daemon; const char *filename = "/tmp/dlt-runtime-context.cfg"; /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_contexts_save(NULL, NULL, 0)); EXPECT_GE(-1, dlt_daemon_contexts_save(NULL, filename, 0)); EXPECT_GE(-1, dlt_daemon_contexts_save(&daemon, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_contexts_save */ /* Begin Method: dlt_daemon_common::dlt_daemon_contexts_load */ TEST(t_dlt_daemon_contexts_load, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; const char *filename = "/tmp/dlt-runtime-context.cfg"; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 0, desc, ecu, 0); EXPECT_LE(0, dlt_daemon_contexts_load(&daemon, filename, 0)); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_contexts_load, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext = NULL; */ /* DltDaemonApplication *app = NULL; */ /* const char * filename = "/tmp/dlt-runtime-context.cfg"; */ /* Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_contexts_load(&daemon, filename, 0)); */ /* Verbose != 1 or 0, expect error */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_contexts_load(&daemon, filename, 123456789)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* Wrong path filename */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_contexts_load(&daemon, (char *) "PATCH_NOT_EXISTS", 0)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_contexts_load, nullpointer) { DltDaemon daemon; const char *filename = "/tmp/dlt-runtime-context.cfg"; /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_contexts_load(NULL, NULL, 0)); EXPECT_GE(-1, dlt_daemon_contexts_load(NULL, filename, 0)); EXPECT_GE(-1, dlt_daemon_contexts_load(&daemon, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_contexts_load */ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /* Begin Method: dlt_daemon_common::dlt_daemon_user_send_all_log_state */ /* Can't test this Method, maybe a return value would be a better solution */ TEST(t_dlt_daemon_user_send_all_log_state, normal) { DltDaemon daemon; DltGateway gateway; char ecu[] = "ECU1"; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_NO_FATAL_FAILURE(dlt_daemon_user_send_all_log_state(&daemon, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_user_send_all_log_state, abnormal) {} TEST(t_dlt_daemon_user_send_all_log_state, nullpointer) { EXPECT_NO_FATAL_FAILURE(dlt_daemon_user_send_all_log_state(NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_user_send_all_log_state */ /* Begin Method: dlt_daemon_common::dlt_daemon_user_send_default_update */ /* Can't test this Method, maybe a return value would be a better solution */ TEST(t_dlt_daemon_user_send_default_update, normal) { DltDaemon daemon; DltGateway gateway; char ecu[] = "ECU1"; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); EXPECT_NO_FATAL_FAILURE(dlt_daemon_user_send_default_update(&daemon, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_user_send_default_update, abnormal) {} TEST(t_dlt_daemon_user_send_default_update, nullpointer) { EXPECT_NO_FATAL_FAILURE(dlt_daemon_user_send_default_update(NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_user_send_default_update */ /* Begin Method: dlt_daemon_common::dlt_daemon_user_send_log_level */ TEST(t_dlt_daemon_user_send_log_level, normal) { DltDaemon daemon; DltGateway gateway; ID4 apid = "TES"; ID4 ctid = "CON"; char desc[255] = "TEST dlt_daemon_context_add"; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; char ecu[] = "ECU1"; int fd = 42; /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); app = dlt_daemon_application_add(&daemon, apid, 0, desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, 1, desc, ecu, 0); EXPECT_LE(0, dlt_daemon_user_send_log_level(&daemon, daecontext, 0)); EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, ecu, 0)); EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, ecu, 0)); EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, ecu, 0)); EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, ecu, 0)); EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_user_send_log_level, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext = NULL; */ /* DltDaemonApplication *app = NULL; */ /* Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_user_send_log_level(&daemon, daecontext, 0)); */ /* File Handler <= 0 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,-1,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_user_send_log_level(&daemon, daecontext, 0)); */ /* EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, 0)); */ /* EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, 0)); */ /* EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, 0)); */ /* Verbose != 0 or 1 */ /* app = dlt_daemon_application_add(&daemon, apid, 0, desc, 0); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,1,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_user_send_log_level(&daemon, daecontext, 123456789)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_user_send_log_level, nullpointer) { DltDaemon daemon; DltDaemonContext daecontext; /* NULL-Pointer */ EXPECT_GE(-1, dlt_daemon_user_send_log_level(NULL, NULL, 0)); EXPECT_GE(-1, dlt_daemon_user_send_log_level(NULL, &daecontext, 0)); EXPECT_GE(-1, dlt_daemon_user_send_log_level(&daemon, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_user_send_log_level */ /* Begin Method: dlt_daemon_common::dlt_daemon_user_send_log_state */ TEST(t_dlt_daemon_user_send_log_state, normal) { DltDaemon daemon; DltGateway gateway; /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext; */ /* DltDaemonApplication *app; */ pid_t pid = 18166; char ecu[] = "ECU1"; char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE + 1]; snprintf(filename, DLT_DAEMON_COMMON_TEXTBUFSIZE, "%s/dlt%d", DLT_USER_DIR, pid); /* Normal Use-Case */ EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE)); /* open(filename, O_RDWR |O_NONBLOCK); */ /* dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, "",0); */ /* app = dlt_daemon_application_add(&daemon, apid, pid, desc, 0); */ /* //printf("### USERHANDLE=%i\n", app->user_handle); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(0, dlt_daemon_user_send_log_state(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, 0)); */ /* EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, 0)); */ /* EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, 0)); */ /* EXPECT_LE(0, close(app->user_handle)); */ EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); } TEST(t_dlt_daemon_user_send_log_state, abnormal) { /* DltDaemon daemon; */ /* ID4 apid = "TES"; */ /* ID4 ctid = "CON"; */ /* char desc[255] = "TEST dlt_daemon_context_add"; */ /* DltDaemonContext *daecontext = NULL; */ /* DltDaemonApplication *app = NULL; */ /* pid_t pid = 18166; */ /* char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE+1]; */ /* snprintf(filename,DLT_DAEMON_COMMON_TEXTBUFSIZE,"%s/dlt%d",DLT_USER_DIR,pid); */ /*Uninitialized */ /* EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY,DLT_LOG_INFO, DLT_TRACE_STATUS_OFF,0,0)); */ /* EXPECT_GE(-1, dlt_daemon_user_send_log_state(&daemon, app, 0)); */ /* No Pipe open */ /*open(filename, O_RDWR |O_NONBLOCK); */ /* dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, "",0); */ /* app = dlt_daemon_application_add(&daemon, apid, pid, desc, 0); */ /*printf("### USERHANDLE=%i\n", app->user_handle); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_user_send_log_state(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_context_del(&daemon, daecontext, 0)); */ /* EXPECT_LE(0, dlt_daemon_application_del(&daemon, app, 0)); */ /* EXPECT_LE(0, dlt_daemon_contexts_clear(&daemon, 0)); */ /* EXPECT_LE(0, dlt_daemon_applications_clear(&daemon, 0)); */ /* EXPECT_LE(0, close(app->user_handle)); */ /* Verbose != 1 or 0 */ /* open(filename, O_RDWR |O_NONBLOCK); */ /* dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, "",0); */ /* app = dlt_daemon_application_add(&daemon, apid, pid, desc, 0); */ /* //printf("### USERHANDLE=%i\n", app->user_handle); */ /* daecontext = dlt_daemon_context_add(&daemon,apid,ctid,DLT_LOG_DEFAULT,DLT_TRACE_STATUS_DEFAULT,0,0,desc,0); */ /* EXPECT_GE(-1, dlt_daemon_user_send_log_state(&daemon, app, 123456789)); */ /* dlt_daemon_context_del(&daemon, daecontext, 0); */ /* dlt_daemon_application_del(&daemon, app, 0); */ /* dlt_daemon_contexts_clear(&daemon, 0); */ /* dlt_daemon_applications_clear(&daemon, 0); */ /* close(app->user_handle); */ /* EXPECT_EQ(0, dlt_daemon_free(&daemon, 0)); */ } TEST(t_dlt_daemon_user_send_log_state, nullpointer) { DltDaemon daemon; DltDaemonApplication app; EXPECT_GE(0, dlt_daemon_user_send_log_state(NULL, NULL, 0)); EXPECT_GE(0, dlt_daemon_user_send_log_state(NULL, &app, 0)); EXPECT_GE(0, dlt_daemon_user_send_log_state(&daemon, NULL, 0)); } /* End Method: dlt_daemon_common::dlt_daemon_user_send_log_state */ /*##############################################################################################################################*/ /*##############################################################################################################################*/ /*##############################################################################################################################*/ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_break_on_failure = true; /*::testing::FLAGS_gtest_filter = "*.normal"; */ /*::testing::FLAGS_gtest_repeat = 10000; */ return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/gtest_dlt_daemon_event_handler.cpp000066400000000000000000000601111446635226000237760ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2016 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Onkar Palkar onkar.palkar@wipro.com * * \copyright Copyright © 2016 Advanced Driver Information Technology. * * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file gtest_dlt_daemon_event_handler.cpp */ /******************************************************************************* ** ** ** SRC-MODULE: gtest_dlt_daemon_event_handler.cpp ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Onkar Palkar onkar.palkar@wipro.com ** ** PURPOSE : Unit test connection and event handling ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** op Onkar Palkar Wipro ** *******************************************************************************/ #include int connectServer(void); extern "C" { #include "dlt_daemon_event_handler.h" #include "dlt_daemon_connection.h" #include #include #include #include } /* Begin Method: dlt_daemon_event_handler::t_dlt_daemon_prepare_event_handling*/ TEST(t_dlt_daemon_prepare_event_handling, normal) { DltEventHandler ev; EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_prepare_event_handling(&ev)); } TEST(t_dlt_daemon_prepare_event_handling, nullpointer) { /* NULL-Pointer, expect -1 */ EXPECT_EQ(DLT_RETURN_ERROR, dlt_daemon_prepare_event_handling(NULL)); } /* Begin Method: dlt_daemon_event_handler::t_dlt_daemon_handle_event*/ TEST(t_dlt_daemon_handle_event, normal) { DltDaemonLocal daemon_local; DltDaemon daemon; EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_prepare_event_handling(&daemon_local.pEvent)); EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_handle_event(&daemon_local.pEvent, &daemon, &daemon_local)); } TEST(t_dlt_daemon_handle_event, nullpointer) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_daemon_handle_event(NULL, NULL, NULL)); } /* Begin Method: dlt_daemon_event_handler::dlt_event_handler_find_connection*/ TEST(t_dlt_event_handler_find_connection, normal) { int fd = 10; DltEventHandler ev; DltConnection connections; DltConnection *ret = nullptr; DltReceiver receiver; memset(&ev, 0, sizeof(DltEventHandler)); memset(&connections, 0, sizeof(DltConnection)); memset(&receiver, 0, sizeof(DltReceiver)); receiver.fd = fd; ev.connections = &connections; ev.connections->receiver = &receiver; ret = dlt_event_handler_find_connection(&ev, fd); EXPECT_EQ(10, ret->receiver->fd); } /* Begin Method: dlt_daemon_event_handler::dlt_daemon_add_connection*/ TEST(t_dlt_daemon_add_connection, normal) { DltEventHandler ev1; DltConnection *head = nullptr; DltConnection *connections1 = nullptr; DltReceiver receiver; memset(&ev1, 0, sizeof(DltEventHandler)); memset(&receiver, 0, sizeof(DltReceiver)); ev1.connections = (DltConnection *)malloc(sizeof(DltConnection)); head = (DltConnection *)ev1.connections; memset(ev1.connections, 0, sizeof(DltConnection)); ev1.connections->next = 0; ev1.connections->type = DLT_CONNECTION_CLIENT_MSG_SERIAL; connections1 = (DltConnection *)malloc(sizeof(DltConnection)); memset(connections1, 0, sizeof(DltConnection)); connections1->next = 0; connections1->type = DLT_CONNECTION_GATEWAY; connections1->receiver = &receiver; EXPECT_EQ(DLT_CONNECTION_CLIENT_MSG_SERIAL, ev1.connections->type); dlt_daemon_add_connection(&ev1, connections1); head = (DltConnection *)ev1.connections->next; EXPECT_EQ(DLT_CONNECTION_GATEWAY, head->type); free(ev1.connections); free(connections1); } /* Begin Method: dlt_daemon_event_handler::dlt_daemon_remove_connection*/ TEST(t_dlt_daemon_remove_connection, normal) { DltEventHandler ev1; DltConnection *head = nullptr; DltConnection *connections1 = nullptr; memset(&ev1, 0, sizeof(DltEventHandler)); ev1.connections = (DltConnection *)malloc(sizeof(DltConnection)); head = (DltConnection *)ev1.connections; memset(ev1.connections, 0, sizeof(DltConnection)); ev1.connections->next = 0; ev1.connections->type = DLT_CONNECTION_CLIENT_MSG_SERIAL; connections1 = (DltConnection *)malloc(sizeof(DltConnection)); memset(connections1, 0, sizeof(DltConnection)); connections1->next = 0; connections1->type = DLT_CONNECTION_GATEWAY; DltReceiver receiver; connections1->receiver = &receiver; EXPECT_EQ(DLT_CONNECTION_CLIENT_MSG_SERIAL, ev1.connections->type); dlt_daemon_add_connection(&ev1, connections1); head = (DltConnection *)ev1.connections->next; EXPECT_EQ(DLT_CONNECTION_GATEWAY, head->type); EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_remove_connection(&ev1, connections1)); } /* Begin Method: dlt_daemon_event_handler::dlt_event_handler_cleanup_connections*/ TEST(t_dlt_event_handler_cleanup_connections, normal) { DltEventHandler ev1; DltReceiver receiver1; memset(&ev1, 0, sizeof(DltEventHandler)); memset(&receiver1, 0, sizeof(DltReceiver)); ev1.connections = (DltConnection *)malloc(sizeof(DltConnection)); memset(ev1.connections, 0, sizeof(DltConnection)); ev1.connections->next = 0; ev1.connections->type = DLT_CONNECTION_GATEWAY; ev1.connections->receiver = &receiver1; dlt_event_handler_cleanup_connections(&ev1); } /* Begin Method: dlt_daemon_event_handler::dlt_connection_check_activate*/ TEST(t_dlt_connection_check_activate, normal) { int ret; DltEventHandler evhdl; DltReceiver receiver; DltConnection con; memset(&evhdl, 0, sizeof(DltEventHandler)); memset(&receiver, 0, sizeof(DltReceiver)); memset(&con, 0, sizeof(DltConnection)); receiver.fd = 1; con.receiver = &receiver; con.status = INACTIVE; con.type = DLT_CONNECTION_CLIENT_MSG_TCP; EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_prepare_event_handling(&evhdl)); ret = dlt_connection_check_activate(&evhdl, &con, ACTIVATE); EXPECT_EQ(DLT_RETURN_OK, ret); ret = dlt_connection_check_activate(&evhdl, &con, DEACTIVATE); EXPECT_EQ(DLT_RETURN_OK, ret); free(evhdl.pfd); } TEST(t_dlt_connection_check_activate, nullpointer) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_connection_check_activate(NULL, NULL, DEACTIVATE)); } /* Begin Method: dlt_daemon_event_handler::dlt_event_handler_register_connection*/ TEST(t_dlt_event_handler_register_connection, normal) { int ret = 0; DltDaemonLocal daemon_local; int mask = 0; DltEventHandler ev1; DltConnection *connections1 = nullptr; DltReceiver receiver; memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&ev1, 0, sizeof(DltEventHandler)); memset(&receiver, 0, sizeof(DltReceiver)); EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_prepare_event_handling(&ev1)); connections1 = (DltConnection *)malloc(sizeof(DltConnection)); memset(connections1, 0, sizeof(DltConnection)); connections1->next = 0; connections1->type = DLT_CONNECTION_GATEWAY; connections1->receiver = &receiver; ret = dlt_event_handler_register_connection(&ev1, &daemon_local, connections1, mask); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(DLT_CONNECTION_GATEWAY, ev1.connections->type); free(ev1.pfd); free(connections1); } TEST(t_dlt_event_handler_register_connection, nullpointer) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_event_handler_register_connection(NULL, NULL, NULL, 1)); } /* Begin Method: dlt_daemon_event_handler::dlt_event_handler_unregister_connection*/ TEST(t_dlt_event_handler_unregister_connection, normal) { int ret = 0; DltDaemonLocal daemon_local; int mask = 0; DltEventHandler ev1; DltConnection *connections1 = nullptr; DltReceiver receiver; memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&ev1, 0, sizeof(DltEventHandler)); memset(&receiver, 0, sizeof(DltReceiver)); EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_prepare_event_handling(&ev1)); connections1 = (DltConnection *)malloc(sizeof(DltConnection)); memset(connections1, 0, sizeof(DltConnection)); connections1->next = 0; connections1->type = DLT_CONNECTION_GATEWAY; connections1->receiver = &receiver; receiver.fd = 100; ret = dlt_event_handler_register_connection(&ev1, &daemon_local, connections1, mask); EXPECT_EQ(DLT_RETURN_OK, ret); EXPECT_EQ(DLT_CONNECTION_GATEWAY, ev1.connections->type); ret = dlt_event_handler_unregister_connection(&ev1, &daemon_local, receiver.fd); EXPECT_EQ(DLT_RETURN_OK, ret); free(ev1.pfd); } /* Begin Method: dlt_daemon_connections::dlt_connection_create*/ TEST(t_dlt_connection_create, normal) { int fd = 100; int ret = 0; DltDaemonLocal daemon_local; memset(&daemon_local, 0, sizeof(DltDaemonLocal)); EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_prepare_event_handling(&daemon_local.pEvent)); ret = dlt_connection_create(&daemon_local, &daemon_local.pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_MSG_SERIAL); EXPECT_EQ(DLT_RETURN_OK, ret); dlt_event_handler_unregister_connection(&daemon_local.pEvent, &daemon_local, fd); free(daemon_local.pEvent.pfd); } /* Begin Method: dlt_daemon_connections::dlt_connection_destroy*/ TEST(t_dlt_connection_destroy, normal) { DltConnection *to_destroy = (DltConnection *)malloc(sizeof(DltConnection)); memset(to_destroy, 0, sizeof(DltConnection)); to_destroy->next = 0; to_destroy->type = DLT_CONNECTION_CLIENT_MSG_SERIAL; to_destroy->receiver = (DltReceiver *)malloc(sizeof(DltReceiver)); memset(to_destroy->receiver, 0, sizeof(DltReceiver)); to_destroy->receiver->fd = -1; to_destroy->receiver->buffer = nullptr; dlt_connection_destroy(to_destroy); } /* Begin Method: dlt_daemon_connections::t_dlt_connection_destroy_receiver*/ TEST(t_dlt_connection_destroy_receiver, normal) { DltConnection to_destroy; memset(&to_destroy, 0, sizeof(DltConnection)); to_destroy.receiver = (DltReceiver *)malloc(sizeof(DltReceiver)); memset(to_destroy.receiver, 0, sizeof(DltReceiver)); to_destroy.receiver->fd = -1; to_destroy.receiver->buffer = nullptr; dlt_connection_destroy_receiver(&to_destroy); } /* Begin Method: dlt_daemon_connections::t_dlt_connection_get_receiver*/ TEST(t_dlt_connection_get_receiver, normal) { int fd = 10; DltReceiver *ret; DltDaemonLocal daemon_local; memset(&daemon_local, 0, sizeof(DltDaemonLocal)); ret = dlt_connection_get_receiver(&daemon_local, DLT_CONNECTION_CLIENT_MSG_TCP, fd); ASSERT_NE(ret, nullptr); EXPECT_EQ(fd, ret->fd); } /* Begin Method: dlt_daemon_connections::(t_dlt_connection_get_next*/ TEST(t_dlt_connection_get_next, normal) { int type_mask = (DLT_CON_MASK_CLIENT_MSG_TCP | DLT_CON_MASK_CLIENT_MSG_SERIAL); DltConnection *ret = nullptr; DltConnection node; DltConnection current; memset(&node, 0, sizeof(DltConnection)); memset(¤t, 0, sizeof(DltConnection)); node.type = DLT_CONNECTION_CLIENT_MSG_TCP; current.type = DLT_CONNECTION_ONE_S_TIMER; current.next = &node; ret = dlt_connection_get_next(¤t, type_mask); ASSERT_NE(ret, nullptr); EXPECT_EQ(DLT_CONNECTION_CLIENT_MSG_TCP, ret->type); EXPECT_NE(DLT_CONNECTION_ONE_S_TIMER, ret->type); } /* Begin Method: dlt_daemon_connections::(t_dlt_connection_get_next*/ TEST(t_dlt_connection_get_next, abnormal) { int type_mask = (DLT_CON_MASK_CLIENT_MSG_TCP | DLT_CON_MASK_CLIENT_MSG_SERIAL); DltConnection *ret; DltConnection node; DltConnection current; memset(&node, 0, sizeof(DltConnection)); memset(¤t, 0, sizeof(DltConnection)); node.type = DLT_CONNECTION_CLIENT_MSG_TCP; current.type = DLT_CONNECTION_CLIENT_MSG_SERIAL; current.next = &node; ret = dlt_connection_get_next(¤t, type_mask); ASSERT_NE(ret, nullptr); EXPECT_NE(DLT_CONNECTION_CLIENT_MSG_TCP, ret->type); EXPECT_EQ(DLT_CONNECTION_CLIENT_MSG_SERIAL, ret->type); } /* Begin Method: dlt_daemon_connections::t_dlt_connection_send*/ TEST(t_dlt_connection_send, normal_1) { int ret = 0; DltConnection conn; DltReceiver receiver; void *data1 = nullptr; int size1 = 0; DltDaemonLocal daemon_local; memset(&conn, 0, sizeof(DltConnection)); memset(&receiver, 0, sizeof(DltReceiver)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); receiver.fd = connectServer(); EXPECT_NE(-1, receiver.fd); conn.receiver = &receiver; conn.type = DLT_CONNECTION_CLIENT_MSG_TCP; daemon_local.msg.databuffer = (uint8_t *)malloc(sizeof(uint8_t)); if (daemon_local.msg.databuffer == NULL) close(receiver.fd); EXPECT_NE((uint8_t *)NULL, daemon_local.msg.databuffer); memset(daemon_local.msg.databuffer, 1, sizeof(uint8_t)); daemon_local.msg.datasize = sizeof(uint8_t); data1 = daemon_local.msg.databuffer; size1 = daemon_local.msg.datasize; ret = dlt_connection_send(&conn, data1, size1); EXPECT_EQ(DLT_RETURN_OK, ret); close(receiver.fd); free(daemon_local.msg.databuffer); } TEST(t_dlt_connection_send, normal_2) { int ret = 0; DltConnection conn; DltReceiver receiver; memset(&conn, 0, sizeof(DltConnection)); memset(&receiver, 0, sizeof(DltReceiver)); receiver.fd = 1; conn.receiver = &receiver; conn.type = DLT_CONNECTION_CLIENT_MSG_SERIAL; ret = dlt_connection_send(&conn, (void *)dltSerialHeader, sizeof(dltSerialHeader)); EXPECT_EQ(DLT_RETURN_OK, ret); } TEST(t_dlt_connection_send, abnormal) { int ret = 0; DltConnection conn; DltReceiver receiver; memset(&conn, 0, sizeof(DltConnection)); memset(&receiver, 0, sizeof(DltReceiver)); receiver.fd = -1; conn.receiver = &receiver; conn.type = DLT_CONNECTION_TYPE_MAX; ret = dlt_connection_send(&conn, (void *)dltSerialHeader, sizeof(dltSerialHeader)); EXPECT_EQ(DLT_RETURN_ERROR, ret); } /* Begin Method: dlt_daemon_connections::t_dlt_connection_send_multiple*/ TEST(t_dlt_connection_send_multiple, normal_1) { int ret = 0; void *data1 = nullptr; void *data2 = nullptr; int size1 = 0; int size2 = 0; DltConnection conn; DltReceiver receiver; DltDaemonLocal daemon_local; memset(&conn, 0, sizeof(DltConnection)); memset(&receiver, 0, sizeof(DltReceiver)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); data1 = daemon_local.msg.headerbuffer + sizeof(DltStorageHeader); size1 = daemon_local.msg.headersize - sizeof(DltStorageHeader); data2 = daemon_local.msg.databuffer; size2 = daemon_local.msg.datasize; receiver.fd = connectServer(); EXPECT_NE(-1, receiver.fd); conn.receiver = &receiver; conn.type = DLT_CONNECTION_CLIENT_MSG_TCP; daemon_local.msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra) + sizeof(DltExtendedHeader); memset(daemon_local.msg.headerbuffer, 0, daemon_local.msg.headersize); data1 = daemon_local.msg.headerbuffer + sizeof(DltStorageHeader); size1 = daemon_local.msg.headersize - sizeof(DltStorageHeader); daemon_local.msg.databuffer = (uint8_t *)malloc(sizeof(uint8_t)); if (daemon_local.msg.databuffer == NULL) close(receiver.fd); EXPECT_NE((uint8_t *)NULL, daemon_local.msg.databuffer); memset(daemon_local.msg.databuffer, 0, sizeof(uint8_t)); daemon_local.msg.datasize = sizeof(uint8_t); data2 = daemon_local.msg.databuffer; size2 = daemon_local.msg.datasize; ret = dlt_connection_send_multiple(&conn, data1, size1, data2, size2, 1); EXPECT_EQ(DLT_RETURN_OK, ret); close(receiver.fd); free(daemon_local.msg.databuffer); } TEST(t_dlt_connection_send_multiple, normal_2) { int ret = 0; void *data1 = nullptr; void *data2 = nullptr; int size1 = 0; int size2 = 0; DltConnection conn; DltReceiver receiver; DltDaemonLocal daemon_local; memset(&conn, 0, sizeof(DltConnection)); memset(&receiver, 0, sizeof(DltReceiver)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); data1 = daemon_local.msg.headerbuffer + sizeof(DltStorageHeader); size1 = daemon_local.msg.headersize - sizeof(DltStorageHeader); data2 = daemon_local.msg.databuffer; size2 = daemon_local.msg.datasize; receiver.fd = connectServer(); EXPECT_NE(-1, receiver.fd); conn.receiver = &receiver; conn.type = DLT_CONNECTION_CLIENT_MSG_TCP; daemon_local.msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra) + sizeof(DltExtendedHeader); memset(daemon_local.msg.headerbuffer, 0, daemon_local.msg.headersize); data1 = daemon_local.msg.headerbuffer + sizeof(DltStorageHeader); size1 = daemon_local.msg.headersize - sizeof(DltStorageHeader); daemon_local.msg.databuffer = (uint8_t *)malloc(sizeof(uint8_t)); if (daemon_local.msg.databuffer == NULL) close(receiver.fd); EXPECT_NE((uint8_t *)NULL, daemon_local.msg.databuffer); memset(daemon_local.msg.databuffer, 0, sizeof(uint8_t)); daemon_local.msg.datasize = sizeof(uint8_t); data2 = daemon_local.msg.databuffer; size2 = daemon_local.msg.datasize; ret = dlt_connection_send_multiple(&conn, data1, size1, data2, size2, 0); EXPECT_EQ(DLT_RETURN_OK, ret); close(receiver.fd); free(daemon_local.msg.databuffer); } TEST(t_dlt_connection_send_multiple, nullpointer) { int ret = 0; void *data1 = nullptr; void *data2 = nullptr; int size1 = 0; int size2 = 0; DltDaemonLocal daemon_local; memset(&daemon_local, 0, sizeof(DltDaemonLocal)); data1 = daemon_local.msg.headerbuffer + sizeof(DltStorageHeader); size1 = daemon_local.msg.headersize - sizeof(DltStorageHeader); data2 = daemon_local.msg.databuffer; size2 = daemon_local.msg.datasize; ret = dlt_connection_send_multiple(NULL, data1, size1, data2, size2, 0); EXPECT_EQ(DLT_RETURN_ERROR, ret); } int connectServer(void) { int sockfd = 0, portno = 0; struct sockaddr_in serv_addr; struct hostent *server = nullptr; portno = 8080; sockfd = socket(AF_INET, SOCK_STREAM, 0); server = gethostbyname("127.0.0.1"); memset((char *)&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("Error: %s (%d) occured in connect socket\n", strerror(errno), errno); close(sockfd); return -1; } return sockfd; } #define GTEST_SOCKS_ACCEPTED 3 int main(int argc, char **argv) { pid_t cpid = fork(); if (cpid == -1) { printf("fork fail\n"); return -1; } if (cpid) { int i = GTEST_SOCKS_ACCEPTED; int j = 0, optval = 1; char buffer[256] = {}; int sockfd = 0, newsockfd[GTEST_SOCKS_ACCEPTED] = {}, portno = 0; socklen_t clilen = {}; struct sockaddr_in serv_addr, cli_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("Error in creating socket\n"); return -1; } memset((char *) &serv_addr, 0, sizeof(serv_addr)); memset((char *) &cli_addr, 0, sizeof(cli_addr)); portno = 8080; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { perror("setsockopt"); close(sockfd); exit(1); } j = bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (j == -1) { perror("Bind Error\n"); close(sockfd); return -1; } listen(sockfd, 5); while (i) { clilen = sizeof(cli_addr); newsockfd[i - 1] = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); if (newsockfd[i - 1] == -1) { printf("Error in accept"); return -1; } memset(buffer, 0, 256); (void)(read(newsockfd[i - 1], buffer, 255) + 1); /* just ignore result */ i--; } for (j = 0; j < GTEST_SOCKS_ACCEPTED; j++) close(newsockfd[i]); close(sockfd); } else { ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_break_on_failure = false; /* ::testing::FLAGS_gtest_filter = "t_dlt_event_handler_register_connection*"; */ return RUN_ALL_TESTS(); } return 0; } dlt-daemon-2.18.10/tests/gtest_dlt_daemon_gateway.cpp000066400000000000000000000656031446635226000226340ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2016 Advanced Driver Information Technology. * This code is developed by Advanced Driver Information Technology. * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Onkar Palkar onkar.palkar@wipro.com * * \copyright Copyright © 2015 Advanced Driver Information Technology. * * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file gtest_dlt_daemon_gateway.cpp */ /******************************************************************************* ** ** ** SRC-MODULE: gtest_dlt_daemon_gateway.cpp ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Onkar Palkar onkar.palkar@wipro.com ** ** PURPOSE : Unit test for dlt_gateway.c ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** op Onkar Palkar Wipro ** *******************************************************************************/ #include #include #include extern "C" { #include "dlt_gateway.h" #include "dlt_gateway_internal.h" } /* Begin Method: dlt_gateway::t_dlt_gateway_init*/ TEST(t_dlt_gateway_init, normal) { DltDaemonLocal daemon_local; DltGatewayConnection connections; daemon_local.pGateway.connections = &connections; daemon_local.pGateway.num_connections = 1; daemon_local.flags.lflag = 0; DltConnection connections1; DltReceiver receiver; daemon_local.pEvent.connections = &connections1; daemon_local.pEvent.pfd = 0; daemon_local.pEvent.nfds = 0; daemon_local.pEvent.max_nfds = 0; daemon_local.pEvent.connections->receiver = &receiver; daemon_local.pEvent.connections->next = NULL; memset(daemon_local.flags.gatewayConfigFile, 0, DLT_DAEMON_FLAG_MAX); strncpy(daemon_local.flags.gatewayConfigFile, "/tmp/dlt_gateway.conf", DLT_DAEMON_FLAG_MAX - 1); EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_init(&daemon_local, 1)); dlt_gateway_deinit(&daemon_local.pGateway, 0); } TEST(t_dlt_gateway_init, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_init(NULL, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_send_control_message*/ TEST(t_dlt_gateway_send_control_message, Normal) { DltDaemonLocal daemon_local; DltGatewayConnection connections; DltConnection connections1; DltReceiver receiver1; DltPassiveControlMessage p_control_msgs; DltServiceSetLogLevel req; memset(&daemon_local,0, sizeof(DltDaemonLocal)); memset(&connections, 0, sizeof(DltGatewayConnection)); memset(&p_control_msgs,0, sizeof(DltPassiveControlMessage)); strcpy(req.apid,"LOG"); strcpy(req.ctid,"TES"); req.log_level = 1; daemon_local.pGateway.connections = &connections; daemon_local.pEvent.connections = &connections1; daemon_local.pGateway.connections->p_control_msgs = &p_control_msgs; daemon_local.pEvent.connections->next = NULL; daemon_local.pEvent.pfd = 0; daemon_local.pEvent.nfds = 0; daemon_local.pEvent.max_nfds = 0; daemon_local.pEvent.connections->receiver = &receiver1; memset(daemon_local.flags.gatewayConfigFile, 0, DLT_DAEMON_FLAG_MAX); strncpy(daemon_local.flags.gatewayConfigFile, "/tmp/dlt_gateway.conf", DLT_DAEMON_FLAG_MAX - 1); (void) dlt_gateway_init(&daemon_local, 0); daemon_local.pGateway.connections->p_control_msgs->id = DLT_SERVICE_ID_GET_LOG_INFO; daemon_local.pGateway.connections->p_control_msgs->type = CONTROL_MESSAGE_ON_DEMAND; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_send_control_message(daemon_local.pGateway.connections, daemon_local.pGateway.connections->p_control_msgs, NULL, 0)); daemon_local.pGateway.connections->p_control_msgs->id = DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_send_control_message(daemon_local.pGateway.connections, daemon_local.pGateway.connections->p_control_msgs, NULL, 0)); daemon_local.pGateway.connections->p_control_msgs->id = DLT_SERVICE_ID_GET_SOFTWARE_VERSION; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_send_control_message(daemon_local.pGateway.connections, daemon_local.pGateway.connections->p_control_msgs, NULL, 0)); daemon_local.pGateway.connections->p_control_msgs->id = DLT_SERVICE_ID_SET_LOG_LEVEL; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_send_control_message(daemon_local.pGateway.connections, daemon_local.pGateway.connections->p_control_msgs, (void*)&req, 0)); } TEST(t_dlt_gateway_send_control_message, nullpointer) { DltDaemonLocal daemon_local; DltGatewayConnection connections; DltConnection connections1; DltReceiver receiver1; DltPassiveControlMessage p_control_msgs; memset(&daemon_local,0, sizeof(DltDaemonLocal)); memset(&connections, 0, sizeof(DltGatewayConnection)); memset(&p_control_msgs,0, sizeof(DltPassiveControlMessage)); daemon_local.pGateway.connections = &connections; daemon_local.pEvent.connections = &connections1; daemon_local.pGateway.connections->p_control_msgs = &p_control_msgs; daemon_local.pEvent.connections->next = NULL; daemon_local.pEvent.connections->receiver = &receiver1; memset(daemon_local.flags.gatewayConfigFile,0,DLT_DAEMON_FLAG_MAX); strncpy(daemon_local.flags.gatewayConfigFile, "/tmp/dlt_gateway.conf", DLT_DAEMON_FLAG_MAX - 1); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_send_control_message(NULL, NULL, NULL, 0)); daemon_local.pGateway.connections->p_control_msgs->id = DLT_SERVICE_ID_SET_LOG_LEVEL; EXPECT_EQ(DLT_RETURN_ERROR,dlt_gateway_send_control_message(daemon_local.pGateway.connections, daemon_local.pGateway.connections->p_control_msgs, NULL, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_store_connection*/ TEST(t_dlt_gateway_store_connection, normal) { char ip_address[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "10.113.100.100"; char ecuid[] = "1234"; DltGateway gateway; DltGatewayConnection tmp; DltGatewayConnection tmp1; gateway.num_connections = 1; gateway.connections = &tmp1; gateway.connections->status = DLT_GATEWAY_UNINITIALIZED; tmp.ip_address = ip_address; tmp.ecuid = ecuid; tmp.sock_domain = 1; tmp.sock_type = 2; tmp.sock_protocol = 1; tmp.port = 1; tmp.trigger = DLT_GATEWAY_ON_STARTUP; tmp.timeout = 500; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_store_connection(&gateway, &tmp, 0)); EXPECT_EQ(gateway.connections->sock_domain, tmp.sock_domain); EXPECT_EQ(gateway.connections->sock_type, tmp.sock_type); EXPECT_EQ(gateway.connections->port, tmp.port); } TEST(t_dlt_gateway_store_connection, nullpointer) { DltGateway gateway; EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_store_connection(NULL, NULL, 0)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_store_connection(&gateway, NULL, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_ip*/ TEST(t_dlt_gateway_check_ip, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "10.113.100.100"; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_ip(con, value)); } TEST(t_dlt_gateway_check_ip, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_ip(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_send_serial*/ TEST(t_dlt_gateway_check_send_serial, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "134dltgatway"; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_send_serial(con, value)); } TEST(t_dlt_gateway_check_send_serial, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_send_serial(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_allocate_control_messages*/ TEST(t_dlt_gateway_allocate_control_messages, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; tmp.p_control_msgs = NULL; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_allocate_control_messages(con)); } TEST(t_dlt_gateway_allocate_control_messages, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_allocate_control_messages(NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_control_messages*/ TEST(t_dlt_gateway_check_control_messages, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "1,2,3,4,5"; tmp.p_control_msgs = NULL; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_control_messages(con, value)); } TEST(t_dlt_gateway_check_control_messages, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_control_messages(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_periodic_control_messages*/ TEST(t_dlt_gateway_check_periodic_control_messages, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "1:5,2:10"; tmp.p_control_msgs = NULL; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_periodic_control_messages(con, value)); } TEST(t_dlt_gateway_check_periodic_control_messages, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_periodic_control_messages(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_port*/ TEST(t_dlt_gateway_check_port, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "3490"; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_port(con, value)); } TEST(t_dlt_gateway_check_port, abnormal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "9999999999"; con = &tmp; EXPECT_EQ(DLT_RETURN_ERROR, dlt_gateway_check_port(con, value)); } TEST(t_dlt_gateway_check_port, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_port(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_ecu*/ TEST(t_dlt_gateway_check_ecu, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "ECU2"; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_ecu(con, value)); } TEST(t_dlt_gateway_check_ecu, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_ecu(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_connect_trigger*/ TEST(t_dlt_gateway_check_connect_trigger, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "OnStartup"; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_connect_trigger(con, value)); } TEST(t_dlt_gateway_check_connect_trigger, abnormal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "wrong_parameter"; con = &tmp; EXPECT_EQ(DLT_RETURN_ERROR, dlt_gateway_check_connect_trigger(con, value)); } TEST(t_dlt_gateway_check_connect_trigger, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_connect_trigger(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_timeout*/ TEST(t_dlt_gateway_check_timeout, normal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "10"; con = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_timeout(con, value)); } TEST(t_dlt_gateway_check_timeout, abnormal) { DltGatewayConnection tmp; DltGatewayConnection *con; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "-1"; con = &tmp; EXPECT_EQ(DLT_RETURN_ERROR, dlt_gateway_check_timeout(con, value)); } TEST(t_dlt_gateway_check_timeout, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_timeout(NULL, NULL)); } /* Begin Method: dlt_gateway::t_dlt_gateway_establish_connections*/ TEST(t_dlt_gateway_establish_connections, normal) { char ip[] = "127.0.0.1"; int port = 3491; DltDaemonLocal daemon_local; DltGateway *gateway = &daemon_local.pGateway; DltGatewayConnection connections; gateway->num_connections = 1; gateway->connections = &connections; gateway->connections->status = DLT_GATEWAY_INITIALIZED; gateway->connections->trigger = DLT_GATEWAY_ON_STARTUP; gateway->connections->client.mode = DLT_CLIENT_MODE_TCP; gateway->connections->client.servIP = ip; gateway->connections->client.port = port; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_establish_connections(gateway, &daemon_local, 0)); } TEST(t_dlt_gateway_establish_connections, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_establish_connections(NULL, NULL, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_get_connection_receiver*/ TEST(t_dlt_gateway_get_connection_receiver, normal) { DltReceiver *ret = NULL; DltGateway gateway; DltGatewayConnection connections; memset(&gateway, 0, sizeof(DltGateway)); memset(&connections, 0, sizeof(DltGatewayConnection)); gateway.connections = &connections; int fd = 10; gateway.num_connections = 1; gateway.connections->client.sock = fd; gateway.connections->client.receiver.fd = 12; gateway.connections->status = DLT_GATEWAY_CONNECTED; ret = dlt_gateway_get_connection_receiver(&gateway, fd); EXPECT_EQ(12, ret->fd); } TEST(t_dlt_gateway_get_connection_receiver, abnormal) { DltReceiver *ret = NULL; DltGateway gateway; DltGatewayConnection connections; memset(&gateway, 0, sizeof(DltGateway)); memset(&connections, 0, sizeof(DltGatewayConnection)); gateway.connections = &connections; int fd = 10; gateway.num_connections = 1; gateway.connections->client.sock = fd; gateway.connections->client.receiver.fd = 12; ret = dlt_gateway_get_connection_receiver(&gateway, fd); EXPECT_EQ(NULL, ret); } TEST(t_dlt_gateway_get_connection_receiver, nullpointer) { DltReceiver *ret; ret = dlt_gateway_get_connection_receiver(NULL, 0); EXPECT_EQ(NULL, ret); } /* Begin Method: dlt_gateway::t_dlt_gateway_parse_get_log_info*/ TEST(t_dlt_gateway_parse_get_log_info, normal) { int32_t len; int32_t ret = DLT_RETURN_ERROR; DltDaemon daemon; DltGateway gateway; DltMessage msg; char ecuid[] = "ECU2"; uint32_t sid = DLT_SERVICE_ID_GET_LOG_INFO; uint8_t status = 7; uint16_t count_app_ids = 1; uint16_t count_context_ids = 1; const char *apid = "LOG"; const char *ctid = "TEST"; const char *com = "remo"; char app_description[] = "Test Application for Logging"; char context_description[] = "Test Context for Logging"; uint16_t len_app = 0; uint16_t len_con = 0; int8_t log_level = -1; int8_t trace_status = -1; int offset = 0; memset(&daemon, 0, sizeof(DltDaemon)); dlt_set_id(daemon.ecuid, ecuid); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); ret = strncmp(daemon.ecuid, daemon.user_list[0].ecu, DLT_ID_SIZE); ASSERT_EQ(DLT_RETURN_OK, ret); /* create response message */ msg.datasize = sizeof(DltServiceGetLogInfoResponse) + sizeof(AppIDsType) + sizeof(ContextIDsInfoType) + strlen(app_description) + strlen(context_description); msg.databuffer = (uint8_t *)malloc(msg.datasize); msg.databuffersize = msg.datasize; memset(msg.databuffer, 0, msg.datasize); memcpy(msg.databuffer, &sid, sizeof(uint32_t)); offset += sizeof(uint32_t); memcpy(msg.databuffer + offset, &status, sizeof(int8_t)); offset += sizeof(int8_t); memcpy(msg.databuffer + offset, &count_app_ids, sizeof(uint16_t)); offset += sizeof(uint16_t); dlt_set_id((char *)(msg.databuffer + offset), apid); offset += sizeof(ID4); memcpy(msg.databuffer + offset, &count_context_ids, sizeof(uint16_t)); offset += sizeof(uint16_t); dlt_set_id((char *)(msg.databuffer + offset), ctid); offset += sizeof(ID4); memcpy(msg.databuffer + offset, &log_level, sizeof(int8_t)); offset += sizeof(int8_t); memcpy(msg.databuffer + offset, &trace_status, sizeof(int8_t)); offset += sizeof(int8_t); len_con = strlen(context_description); memcpy(msg.databuffer + offset, &len_con, sizeof(uint16_t)); offset += sizeof(uint16_t); memcpy(msg.databuffer + offset, context_description, strlen(context_description)); offset += strlen(context_description); len_app = strlen(app_description); memcpy(msg.databuffer + offset, &len_app, sizeof(uint16_t)); offset += sizeof(uint16_t); memcpy(msg.databuffer + offset, app_description, strlen(app_description)); offset += strlen(app_description); dlt_set_id((char *)(msg.databuffer + offset), com); msg.storageheader = (DltStorageHeader *)msg.headerbuffer; dlt_set_storageheader(msg.storageheader, ""); msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1; msg.standardheader->mcnt = 0; dlt_set_id(msg.headerextra.ecu, ecuid); msg.headerextra.tmsp = dlt_uptime(); dlt_message_set_extraparameters(&msg, 0); msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); msg.extendedheader->msin = DLT_MSIN_CONTROL_RESPONSE; msg.extendedheader->noar = 1; dlt_set_id(msg.extendedheader->apid, ""); dlt_set_id(msg.extendedheader->ctid, ""); msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp); len = msg.headersize - sizeof(DltStorageHeader) + msg.datasize; msg.standardheader->len = DLT_HTOBE_16(len); EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_parse_get_log_info(&daemon, ecuid, &msg, CONTROL_MESSAGE_NOT_REQUESTED, 0)); } TEST(t_dlt_gateway_parse_get_log_info, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_parse_get_log_info(NULL, NULL, NULL, 0, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_process_passive_node_messages*/ TEST(t_dlt_gateway_process_passive_node_messages, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; DltReceiver receiver; DltGatewayConnection connections; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&receiver, 0, sizeof(DltReceiver)); memset(&connections, 0, sizeof(DltGatewayConnection)); daemon_local.pGateway.connections = &connections; daemon_local.pGateway.num_connections = 1; daemon_local.pGateway.connections->status = DLT_GATEWAY_CONNECTED; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_process_passive_node_messages(&daemon, &daemon_local, &receiver, 1)); } TEST(t_dlt_gateway_process_passive_node_messages, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_process_passive_node_messages(NULL, NULL, NULL, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_process_gateway_timer*/ TEST(t_dlt_gateway_process_gateway_timer, normal) { char ECUVersionString[] = "12.34"; char ip[] = "127.0.0.1"; int port = 3491; DltDaemon daemon; DltDaemonLocal daemon_local; DltReceiver receiver; DltGatewayConnection connections; DltConnection connections1; daemon_local.pGateway.connections = &connections; daemon_local.pGateway.num_connections = 1; DltLogStorage storage_handle; daemon_local.pGateway.connections->status = DLT_GATEWAY_INITIALIZED; daemon_local.pGateway.connections->trigger = DLT_GATEWAY_ON_STARTUP; daemon_local.pGateway.connections->client.mode = DLT_CLIENT_MODE_TCP; daemon_local.pGateway.connections->client.servIP = ip; daemon_local.pGateway.connections->client.port = port; daemon_local.pEvent.connections = &connections1; daemon_local.pEvent.connections->receiver = &receiver; daemon.ECUVersionString = ECUVersionString; daemon.storage_handle = &storage_handle; daemon_local.pEvent.connections->receiver->fd = -1; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_process_gateway_timer(&daemon, &daemon_local, daemon_local.pEvent.connections->receiver, 1)); } TEST(t_dlt_gateway_process_gateway_timer, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_process_gateway_timer(NULL, NULL, NULL, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_process_on_demand_request*/ TEST(t_dlt_gateway_process_on_demand_request, normal) { char node_id[DLT_ID_SIZE] = "123"; uint32_t connection_status = 1; DltDaemonLocal daemon_local; DltGatewayConnection connections; daemon_local.pGateway.connections = &connections; daemon_local.pGateway.num_connections = 1; connections.status = DLT_GATEWAY_CONNECTED; connections.trigger = DLT_GATEWAY_ON_STARTUP; connections.ecuid = node_id; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_process_on_demand_request(&daemon_local.pGateway, &daemon_local, node_id, connection_status, 1)); } TEST(t_dlt_gateway_process_on_demand_request, abnormal) { char node_id[DLT_ID_SIZE] = "123"; uint32_t connection_status = 1; DltDaemonLocal daemon_local; DltGatewayConnection connections; daemon_local.pGateway.connections = &connections; daemon_local.pGateway.num_connections = 1; connections.status = DLT_GATEWAY_INITIALIZED; connections.ecuid = node_id; EXPECT_EQ(DLT_RETURN_ERROR, dlt_gateway_process_on_demand_request(&daemon_local.pGateway, &daemon_local, node_id, connection_status, 0)); } TEST(t_dlt_gateway_process_on_demand_request, nullpointer) { char node_id[DLT_ID_SIZE] = "123"; EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_process_on_demand_request(NULL, NULL, node_id, 1, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_check_param*/ TEST(t_dlt_gateway_check_param, normal) { char value_1[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "10.11.22.33"; char value_2[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "3490"; DltGateway gateway; DltGatewayConnection tmp; gateway.connections = &tmp; EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_param(&gateway, &tmp, GW_CONF_IP_ADDRESS, value_1)); EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_check_param(&gateway, &tmp, GW_CONF_PORT, value_2)); } TEST(t_dlt_gateway_check_param, abnormal) { char value_1[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = "10.11.22.33"; DltGateway gateway; DltGatewayConnection tmp; gateway.connections = &tmp; EXPECT_EQ(DLT_RETURN_ERROR, dlt_gateway_check_param(&gateway, &tmp, GW_CONF_PORT, value_1)); } TEST(t_dlt_gateway_check_param, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_check_param(NULL, NULL, GW_CONF_PORT, 0)); } /* Begin Method: dlt_gateway::t_dlt_gateway_configure*/ TEST(t_dlt_gateway_configure, Normal) { DltGateway gateway; DltGatewayConnection tmp; gateway.connections = &tmp; gateway.num_connections = 1; char gatewayConfigFile[DLT_DAEMON_FLAG_MAX]; strncpy(gatewayConfigFile, "/tmp/dlt_gateway.conf", DLT_DAEMON_FLAG_MAX - 1); EXPECT_EQ(DLT_RETURN_OK, dlt_gateway_configure(&gateway, gatewayConfigFile, 0)); } TEST(t_dlt_gateway_configure, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_gateway_configure(NULL, NULL, 0)); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); /* ::testing::FLAGS_gtest_break_on_failure = true; */ /* ::testing::FLAGS_gtest_filter = "t_dlt_gateway_process_passive_node_messages*"; */ return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/gtest_dlt_daemon_gateway.sh000077500000000000000000000153121446635226000224570ustar00rootroot00000000000000#!/bin/sh ################################################################################ # SPDX license identifier: MPL-2.0 # # Copyright (C) 2016, Advanced Driver Information Technology # This code is developed by Advanced Driver Information Technology. # Copyright of Advanced Driver Information Technology, Bosch and DENSO. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ################################################################################ ################################################################################ #file : g_test_dlt_daemon_gateway.sh # #Description : gateway unit test preparation # #Author Name : Onkar Palkar # Jeevan Ramakant Nagvekar #Email Id : onkar.palkar@wipro.com # jeevan.nagvekar1@wipro.com # #History : Last modified date : 31/07/2018 ipaddr=127.0.0.1 ################################################################################ # Function: -getOSname() # # Description -Retrieves OS name # getOSname() { OS="`uname`" } ################################################################################ # Function: -getDltDaemonPath() # # Description -Retrieves path to dlt-daemon # getDltDaemonPath() { if [ -z "${DLT_UT_DAEMON_PATH}" ]; then echo "WARNNG: env variable DLT_UT_DAEMON_PATH is not set" DLT_DAEMON=`which dlt-daemon` else DLT_DAEMON="${DLT_UT_DAEMON_PATH}" fi } ################################################################################ # # Function: -cleanup() # # Description -Delete the dlt_test folder if it already present # -Check weather required binaries are avaiable or not # -Restore dlt_gateway.conf file # # Return -Zero on success # -Non zero on failure # cleanup() { tmpPath=/tmp if [ "$OS" = "QNX" ] then PIDOF() { slay -p $1 > /dev/null if [ $? -eq '0' ] then return 1 else return 0 fi } KILLALL() { slay -9 -f $1 > /dev/null if [ $? -eq '0' ] then return 1 else return 0 fi } else PIDOF() { pidof $1 > /dev/null return $? } KILLALL() { killall $1 > /dev/null return $? } fi cd $tmpPath BASE=`basename $DLT_DAEMON` PIDOF $BASE if [ $? -eq '0' ] then KILLALL $BASE if [ $? -eq '1' ] then echo "Failed to kill daemons" return 1 fi fi rm -f $tmpPath/dlt.conf rm -f $tmpPath/dlt_gateway.conf rm -f /dev/shm/dlt-shm rm -f /dev/shm/sem.dlt-shm rm -f /dev/shm/dlt-shm-passive rm -f /dev/shm/sem.dlt-shm-passive return 0 } # # Function: -setupTest() # # Description -Create gateway folder # -Create and add dlt.conf and dlt_gateway.conf file in the gateway folder # # Return -Zero on success # -Non zero on failure # setupTest() { which dlt-daemon > /dev/null if [ $? -eq '1' ] then echo "dlt-daemon is not available" return 1 fi touch $tmpPath/dlt.conf if [ $? -eq '1' ] then echo "Error in creating dlt.conf file" return 1 fi echo "SendContextRegistration = 1" >>$tmpPath/dlt.conf echo "ECUId = ECU2" >>$tmpPath/dlt.conf echo "GatewayMode = 1" >>$tmpPath/dlt.conf echo "SharedMemorySize = 100000" >>$tmpPath/dlt.conf echo "LoggingMode = 0" >>$tmpPath/dlt.conf echo "LoggingLevel = 6" >>$tmpPath/dlt.conf echo "LoggingFilename = /tmp/dlt.log" >>$tmpPath/dlt.conf echo "TimeOutOnSend = 4" >>$tmpPath/dlt.conf echo "RingbufferMinSize = 500000" >>$tmpPath/dlt.conf echo "RingbufferMaxSize = 10000000" >>$tmpPath/dlt.conf echo "RingbufferStepSize = 500000" >>$tmpPath/dlt.conf echo "ControlSocketPath = /tmp/dlt-ctrl.sock" >>$tmpPath/dlt.conf echo "GatewayConfigFile = /tmp/dlt_gateway.conf" >>$tmpPath/dlt.conf touch $tmpPath/dlt_gateway.conf if [ $? -eq '1' ] then echo "Error in creating dlt_gateway file" return 1 fi if [ $# -eq 1 ] && [ "$1" = "1" ] then echo "[General]" >>$tmpPath/dlt_gateway.conf echo "Interval=1">>$tmpPath/dlt_gateway.conf fi echo "[PassiveNode1]" >>$tmpPath/dlt_gateway.conf echo "IPaddress=$ipaddr">>$tmpPath/dlt_gateway.conf echo "Port=3490" >>$tmpPath/dlt_gateway.conf echo "EcuID=ECU1" >>$tmpPath/dlt_gateway.conf echo "Connect=OnStartup" >>$tmpPath/dlt_gateway.conf echo "Timeout=10" >>$tmpPath/dlt_gateway.conf echo "SendControl=0x03,0x13" >>$tmpPath/dlt_gateway.conf echo "SendSerialHeader=0" >>$tmpPath/dlt_gateway.conf echo "NOFiles=1" >>$tmpPath/dlt_gateway.conf return 0 } # # Function: -startDaemons() # # Description -Start dlt-daemon as passive node # -Start dlt-daemon as gateway node # # Return -Zero on success # -Non zero on failure # startDaemons() { DLT_PASSIVE_SHM_NAME="" tmpPath=/tmp dlt-daemon -d sleep 1 # Check if the dlt shm file exist (DLT_SHM_ENABLE=ON) if [ -f /dev/shm/dlt-shm ]; then DLT_PASSIVE_SHM_NAME="-s dlt-shm-passive" fi dlt-daemon -d -p 3495 -c $tmpPath/dlt.conf $DLT_PASSIVE_SHM_NAME return 0 } # # Function: -checkDaemonStart # # Description -Check if dlt-daemon instances started successfully # checkDaemonStart() { BASE=`basename $DLT_DAEMON` if [ "$OS" = "QNX" ]; then slay -p $BASE > /dev/null total=$? else total=`pgrep -c $BASE` fi if [ $total -ne '2' ]; then echo "Initialization of dlt-daemon instances failed" exit 1 fi } help() { echo "Usage: " echo "sh ./gtest_dlt_daemon_gateway.sh" } executeTests() { echo "Execute: gtest_dlt_daemon_gateway unit test" } #main function ######################################################################################## getOSname getDltDaemonPath echo "Cleaning up dlt-daemon instances" cleanup if [ $? -ne '0' ] then help exit fi echo "Initializing test" if [ $# -eq 1 ] && [ "$1" = "-w" ] then echo "Including General section in dlt_gateway.conf" setupTest 1 else setupTest fi if [ $? -ne '0' ] then help exit fi echo "Restarting dlt-daemons" startDaemons checkDaemonStart executeTests dlt-daemon-2.18.10/tests/gtest_dlt_daemon_multiple_files_logging.cpp000066400000000000000000000202041446635226000257020ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author * Oleg Tropmann * Daniel Weber * * \copyright Copyright © 2022 Daimler TSS GmbH. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file gtest_dlt_daemon_multiple_files_logging.ccpp */ #include int connectServer(void); extern "C" { #include "dlt_common.h" #include #include #include } // publish prototypes void configure(const char* path, const char* file_name, bool enable_limit, int file_size, int max_files_size); void write_log_message(); void verify_multiple_files(const char* path, const char* file_name, int file_size, int max_files_size); void verify_single_file(const char* path, const char* file_name); void verify_in_one_file(const char* path, const char* file_name, const char* log1, const char* log2); bool file_contains_strings(const char* abs_file_path, const char* str1, const char* str2); int get_file_index(char* file_name); int compare_int(const void* a, const void* b); /** * Configure dlt logging using file size limits. */ TEST(t_dlt_logging_multiple_files, normal) { const char* path = "/tmp"; const char* file_name = "dlt.log"; const int file_size = 128; const int max_file_size = 512; configure(path, file_name, true, file_size, max_file_size); write_log_message(); EXPECT_NO_THROW(dlt_log_free()); verify_multiple_files(path, file_name, file_size, max_file_size); } /** * Configure dlt logging using file size limits. * Though, due to an error during initialization dlt logging defaults to one file logging. */ TEST(t_dlt_logging_one_file_as_fallback, normal) { const char* path = "/tmp"; const char* file_name = "dltlog"; configure(path, file_name, true, 128, 512); write_log_message(); EXPECT_NO_THROW(dlt_log_free()); verify_single_file(path, file_name); } /** * Configure dlt logging without file size limits resulting in one file logging. */ TEST(t_dlt_logging_one_file, normal) { const char* path = "/tmp"; const char* file_name = "dlt.log"; configure(path, file_name, false, 128, 512); write_log_message(); EXPECT_NO_THROW(dlt_log_free()); verify_single_file(path, file_name); } /** * The dlt_daemon calls dlt_log_init multiple times. In the past, so we create * unnecessary two files. The reinit have to append to the first file. */ TEST(t_dlt_logging_multiple_files_append_reinit, normal) { const char* path = "/tmp"; const char* file_name = "dlt.log"; const int file_size = 256; const int max_file_size = 512; const char* log1 = "ONE\n"; const char* log2 = "TWO\n"; configure(path, file_name, true, file_size, max_file_size); dlt_vlog(LOG_INFO, "%s", log1); EXPECT_NO_THROW(dlt_log_free()); configure(path, file_name, true, file_size, max_file_size); dlt_vlog(LOG_INFO, "%s", log2); EXPECT_NO_THROW(dlt_log_free()); verify_in_one_file(path, file_name, log1, log2); } void configure(const char *path, const char* file_name, const bool enable_limit, const int file_size, const int max_files_size) { char abs_file_path[PATH_MAX]; snprintf(abs_file_path, sizeof(abs_file_path), "%s/%s", path, file_name); printf("debug test: %s\n", abs_file_path); EXPECT_NO_THROW(dlt_log_set_filename(abs_file_path)); EXPECT_NO_THROW(dlt_log_set_level(6)); EXPECT_NO_THROW(dlt_log_init_multiple_logfiles_support(DLT_LOG_TO_FILE, enable_limit, file_size, max_files_size)); } void write_log_message() { for (unsigned int i = 0; i < 10; i++) { dlt_vlog(LOG_INFO, "%d. Unit test logging into multiple files if configured.\n", i); } } void verify_multiple_files(const char* path, const char* file_name, const int file_size, const int max_files_size) { int sum_size = 0; int num_files = 0; int file_indices[100]; char filename[PATH_MAX + 1]; struct dirent *dp; struct stat status; char file_name_copy[NAME_MAX]; strncpy(file_name_copy, file_name, NAME_MAX); char filename_base[NAME_MAX]; EXPECT_TRUE(dlt_extract_base_name_without_ext(file_name_copy, filename_base, sizeof(filename_base))); const char *filename_ext = get_filename_ext(file_name); EXPECT_TRUE(filename_ext); DIR *dir = opendir(path); while ((dp = readdir(dir)) != NULL) { if (strstr(dp->d_name, filename_base) && strstr(dp->d_name, filename_ext)) { snprintf(filename, sizeof(filename), "%s/%s", path, dp->d_name); if (0 == stat(filename, &status)) { EXPECT_LE(status.st_size, file_size); EXPECT_GE(status.st_size, file_size/2); sum_size += status.st_size; file_indices[num_files++] = get_file_index(filename); } else { EXPECT_TRUE(false); } } } EXPECT_LE(sum_size, max_files_size); EXPECT_GT(sum_size, 0); EXPECT_GT(num_files, 0); //check that file indices are successive in ascending order qsort(file_indices, num_files, sizeof(int), compare_int); int index = file_indices[0]; for (int i=1; id_name, filename_base) && strstr(dp->d_name, filename_ext)) { snprintf(abs_file_path, sizeof(abs_file_path), "%s/%s", path, dp->d_name); if (file_contains_strings(abs_file_path, log1, log2)) { found = true; break; } } } EXPECT_TRUE(found); } bool file_contains_strings(const char* abs_file_path, const char* str1, const char* str2) { bool found = false; FILE *file = fopen(abs_file_path, "r"); if (file != nullptr) { fseek (file , 0 , SEEK_END); long size = ftell (file); rewind (file); char* buffer = (char*) malloc(size); long read_bytes = fread(buffer, 1, size, file); EXPECT_EQ(size, read_bytes); if ((strstr(buffer, str1) != nullptr) && (strstr(buffer, str2) != nullptr)) { found = true; } fclose(file); free(buffer); } return found; } int get_file_index(char* file_name) { char *dot = strrchr(file_name, '.'); *dot = '\0'; //start with the first zero char *iterator = strchr(file_name, '0'); do {} while (*(++iterator) == '0'); //now iterator points to the first character after 0 return atoi(iterator); } int compare_int(const void* a, const void* b) { if (*((int*)a) == *((int*)b)) return 0; else if (*((int*)a) < *((int*)b)) return -1; else return 1; } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_break_on_failure = true; /*::testing::FLAGS_gtest_filter = "*.normal"; */ /*::testing::FLAGS_gtest_repeat = 10000; */ return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/gtest_dlt_daemon_offline_log.cpp000066400000000000000000002102311446635226000234430ustar00rootroot00000000000000/*! * file gtest_dlt_daemon_logstorage.cpp * * Descriptiom : Unit test for dlt_logstorage.c * * Author : Onkar Palkar * * Email : onkar.palkar@wipro.com * * History : 30-Jun-2016 */ #include int connectServer(void); extern "C" { #include "dlt_offline_logstorage.h" #include "dlt_offline_logstorage_internal.h" #include "dlt_offline_logstorage_behavior.h" #include "dlt_offline_logstorage_behavior_internal.h" #include "dlt_daemon_offline_logstorage.h" #include "dlt_daemon_offline_logstorage_internal.h" #include "dlt_daemon_common_cfg.h" #include #include #include #include #include } unsigned int g_logstorage_cache_max; /* Begin Method: dlt_logstorage::t_dlt_logstorage_list_add*/ TEST(t_dlt_logstorage_list_add, normal) { DltLogStorageFilterList *list = NULL; DltLogStorageFilterConfig *data = NULL; DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; char key = 1; int num_keys = 1; data = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); if (data != NULL) { dlt_logstorage_filter_set_strategy(data, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(&key, num_keys, data, &list)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_destroy(&list, &file_config, path, 0)); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_list_add_config*/ TEST(t_dlt_logstorage_list_add_config, normal) { DltLogStorageFilterConfig *data = NULL; DltLogStorageFilterConfig *listdata = NULL; data = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); listdata = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); if ((data != NULL) && (listdata != NULL)) { dlt_logstorage_list_add_config(data, &listdata); free(data); free(listdata); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_list_destroy*/ TEST(t_dlt_logstorage_list_destroy, normal) { DltLogStorageFilterList *list = NULL; DltLogStorageFilterConfig *data = NULL; DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; char key = 1; int num_keys = 1; data = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); if (data != NULL) { dlt_logstorage_filter_set_strategy(data, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(&key, num_keys, data, &list)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_destroy(&list, &file_config, path, 0)); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_list_find*/ TEST(t_dlt_logstorage_list_find, normal) { DltLogStorageFilterList *list = NULL; DltLogStorageFilterConfig *data = NULL; int num_configs = 0; DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; char key[] = ":1234:5678"; char apid[] = "1234"; char ctid[] = "5678"; int num_keys = 1; DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; data = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); if (data != NULL) { data->apids = strdup(apid); data->ctids = strdup(ctid); dlt_logstorage_filter_set_strategy(data, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key, num_keys, data, &list)); num_configs = dlt_logstorage_list_find(key, &list, config); EXPECT_EQ(1, num_configs); EXPECT_NE((DltLogStorageFilterConfig *)NULL, config[0]); if (num_configs > 0) { EXPECT_STREQ(apid, config[0]->apids); EXPECT_STREQ(ctid, config[0]->ctids); } EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_destroy(&list, &file_config, path, 0)); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_free*/ TEST(t_dlt_logstorage_free, normal) { char key = 1; DltLogStorage handle; DltLogStorageFilterConfig *data = NULL; int reason = 0; handle.num_configs = 0; handle.config_list = NULL; int num_keys = 1; data = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); if (data != NULL) { dlt_logstorage_filter_set_strategy(data, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(&key, num_keys, data, &handle.config_list)); dlt_logstorage_free(&handle, reason); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_count_ids*/ TEST(t_dlt_logstorage_count_ids, normal) { char const *str = "a,b,c,d"; EXPECT_EQ(4, dlt_logstorage_count_ids(str)); } TEST(t_dlt_logstorage_count_ids, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_count_ids(NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_read_number*/ TEST(t_dlt_logstorage_read_number, normal) { char str[] = "100"; unsigned int number; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_number(&number, str)); EXPECT_EQ(100, number); } TEST(t_dlt_logstorage_read_number, null) { unsigned int number; EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_read_number(&number, NULL)); } TEST(t_dlt_logstorage_read_boolean, normal) { unsigned int val; { char str[] = "0"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(0, val); } { char str[] = "1"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(1, val); } { char str[] = "off"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(0, val); } { char str[] = "on"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(1, val); } { char str[] = "false"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(0, val); } { char str[] = "true"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(1, val); } { char str[] = "invalidvalue"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(0, val); } { char str[] = "not"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_bool(&val, str)); EXPECT_EQ(0, val); } } TEST(t_dlt_logstorage_read_boolean, null) { unsigned int val; EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_read_bool(&val, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_create_keys*/ TEST(t_dlt_logstorage_create_keys, normal) { DltLogStorageFilterConfig data; memset(&data, 0, sizeof(DltLogStorageFilterConfig)); char *keys = NULL; int num_keys = 0; char apids[] = "1234"; char ctids[] = "5678"; char ecuid[] = "ECU1"; data.apids = apids; data.ctids = ctids; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_create_keys(data.apids, data.ctids, ecuid, &keys, &num_keys)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_prepare_table*/ TEST(t_dlt_logstorage_prepare_table, normal) { DltLogStorage handle; DltLogStorageFilterConfig data; DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; memset(&handle, 0, sizeof(DltLogStorage)); memset(&data, 0, sizeof(DltLogStorageFilterConfig)); char apids[] = "1234"; char ctids[] = "5678"; data.apids = apids; data.ctids = ctids; data.records = NULL; data.log = NULL; data.cache = NULL; dlt_logstorage_filter_set_strategy(&data, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_table(&handle, &data)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_destroy(&handle.config_list, &file_config, path, 0)); } TEST(t_dlt_logstorage_prepare_table, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_prepare_table(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_validate_filter_name*/ TEST(t_dlt_logstorage_validate_filter_name, normal) { char name[] = "FILTER100"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_validate_filter_name(name)); } TEST(t_dlt_logstorage_validate_filter_name, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_validate_filter_name(NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_filter_set_strategy*/ TEST(t_dlt_logstorage_filter_set_strategy, normal) { DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); dlt_logstorage_filter_set_strategy(&config, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(&dlt_logstorage_prepare_on_msg, config.dlt_logstorage_prepare); dlt_logstorage_filter_set_strategy(&config, 2); EXPECT_EQ(&dlt_logstorage_prepare_msg_cache, config.dlt_logstorage_prepare); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_read_list_of_names*/ TEST(t_dlt_logstorage_read_list_of_names, normal) { char *namesPtr = NULL; char value[] = "a,b,c,d"; namesPtr = (char *)calloc (1, sizeof(char)); if (namesPtr != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_read_list_of_names(&namesPtr, value)); free(namesPtr); } } TEST(t_dlt_logstorage_read_list_of_names, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_read_list_of_names(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_apids*/ TEST(t_dlt_logstorage_check_apids, normal) { char value[] = "a,b,c,d"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.apids = (char *)calloc (1, sizeof(char)); if (config.apids != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_apids(&config, value)); free(config.apids); } } TEST(t_dlt_logstorage_check_apids, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_apids(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_ctids*/ TEST(t_dlt_logstorage_check_ctids, normal) { char value[] = "a,b,c,d"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.ctids = (char *)calloc (1, sizeof(char)); if (config.ctids != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_ctids(&config, value)); free(config.ctids); } } TEST(t_dlt_logstorage_check_ctids, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_ctids(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_loglevel*/ TEST(t_dlt_logstorage_check_loglevel, normal) { char value[] = "DLT_LOG_FATAL"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_loglevel(&config, value)); EXPECT_EQ(1, config.log_level); } TEST(t_dlt_logstorage_check_loglevel, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_loglevel(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_filename*/ TEST(t_dlt_logstorage_check_filename, normal) { char value[] = "file_name"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.file_name = (char *)calloc (1, sizeof(char)); if (config.file_name != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_filename(&config, value)); free(config.file_name); } } TEST(t_dlt_logstorage_check_filename, abnormal) { char value[] = "../file_name"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.file_name = (char *)calloc (1, sizeof(char)); if (config.file_name != NULL) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_filename(&config, value)); free(config.file_name); } } TEST(t_dlt_logstorage_check_filename, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_filename(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_filesize*/ TEST(t_dlt_logstorage_check_filesize, normal) { char value[] = "100"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_filesize(&config, value)); EXPECT_EQ(100, config.file_size); } TEST(t_dlt_logstorage_check_filesize, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_filesize(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_nofiles*/ TEST(t_dlt_logstorage_check_nofiles, normal) { char value[] = "100"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_nofiles(&config, value)); EXPECT_EQ(100, config.num_files); } TEST(t_dlt_logstorage_check_nofiles, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_nofiles(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_sync_strategy*/ TEST(t_dlt_logstorage_check_sync_strategy, normal) { char value[] = "ON_MSG"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.sync = 0; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_sync_strategy(&config, value)); EXPECT_EQ(DLT_LOGSTORAGE_SYNC_ON_MSG, config.sync); } TEST(t_dlt_logstorage_check_sync_strategy, abnormal) { char value[] = "UNKNOWN"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.sync = 0; EXPECT_EQ(DLT_RETURN_TRUE, dlt_logstorage_check_sync_strategy(&config, value)); EXPECT_EQ(DLT_LOGSTORAGE_SYNC_ON_MSG, config.sync); } TEST(t_dlt_logstorage_check_sync_strategy, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_sync_strategy(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_ecuid*/ TEST(t_dlt_logstorage_check_ecuid, normal) { char value[] = "213"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.ecuid = (char *)calloc (1, sizeof(char)); if (config.ecuid != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_ecuid(&config, value)); EXPECT_EQ('2', *config.ecuid); EXPECT_EQ('1', *(config.ecuid + 1)); EXPECT_EQ('3', *(config.ecuid + 2)); free(config.ecuid); } } TEST(t_dlt_logstorage_check_ecuid, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_ecuid(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_check_param*/ TEST(t_dlt_logstorage_check_param, normal) { char value[] = "100"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_check_param(&config, DLT_LOGSTORAGE_FILTER_CONF_FILESIZE, value)); EXPECT_EQ(100, config.file_size); } TEST(t_dlt_logstorage_check_param, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_check_param(NULL, DLT_LOGSTORAGE_FILTER_CONF_FILESIZE, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_store_filters*/ TEST(t_dlt_logstorage_store_filters, normal) { DltLogStorage handle; DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; char config_file_name[] = "/tmp/dlt_logstorage.conf"; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = 0; handle.write_errors = 0; handle.config_list = NULL; handle.newest_file_list = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_store_filters(&handle, config_file_name)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_destroy(&handle.config_list, &file_config, path, 0)); } TEST(t_dlt_logstorage_store_filters, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_store_filters(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_load_config*/ TEST(t_dlt_logstorage_load_config, normal) { DltLogStorage handle; DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = 0; handle.write_errors = 0; handle.config_list = NULL; handle.newest_file_list = NULL; strncpy(handle.device_mount_point, "/tmp", DLT_MOUNT_PATH_MAX); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_load_config(&handle)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_destroy(&handle.config_list, &file_config, path, 0)); } TEST(t_dlt_logstorage_load_config, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_load_config(NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_device_connected*/ TEST(t_dlt_logstorage_device_connected, normal) { DltLogStorage handle; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED; handle.config_status = 0; handle.write_errors = 0; handle.config_list = NULL; handle.newest_file_list = NULL; strncpy(handle.device_mount_point, "/tmp", DLT_MOUNT_PATH_MAX); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_device_connected(&handle, handle.device_mount_point)); } TEST(t_dlt_logstorage_device_connected, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_device_connected(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_device_disconnected*/ TEST(t_dlt_logstorage_device_disconnected, normal) { DltLogStorage handle; int reason = 0; handle.config_status = 0; handle.newest_file_list = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_device_disconnected(&handle, reason)); } TEST(t_dlt_logstorage_device_disconnected, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_device_disconnected(NULL, 1)); } TEST(t_dlt_logstorage_get_loglevel_by_key, normal) { char arr[] = "abc"; char *key = arr; DltLogStorageFilterConfig *config = NULL; DltLogStorage handle; handle.config_status = 0; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; handle.config_list = NULL; handle.newest_file_list = NULL; int num_keys = 1; config = (DltLogStorageFilterConfig *)calloc(1, sizeof(DltLogStorageFilterConfig)); if (config != NULL) { config->log_level = DLT_LOG_ERROR; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key, num_keys, config, &(handle.config_list))); EXPECT_GE(DLT_LOG_ERROR, dlt_logstorage_get_loglevel_by_key(&handle, key)); free(config); } } TEST(t_dlt_logstorage_get_loglevel_by_key, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_get_loglevel_by_key(NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_get_config*/ TEST(t_dlt_logstorage_get_config, normal) { char apid[] = "1234"; char ctid[] = "5678"; char ecuid[] = "12"; char file_name[] = "file_name"; int num_config = 0; DltLogStorageFilterConfig value = {}; value.log_level = 0; value.apids = apid; value.ctids = ctid; value.ecuid = ecuid; value.file_name = file_name; char key0[] = ":1234:\000\000\000\000"; char key1[] = "::5678\000\000\000\000"; char key2[] = ":1234:5678"; DltLogStorageFilterConfig *config[3] = { 0 }; DltLogStorage handle; memset(&handle, 0, sizeof(DltLogStorage)); handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key0, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key1, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key2, num_keys, &value, &(handle.config_list))); num_config = dlt_logstorage_get_config(&handle, config, apid, ctid, ecuid); EXPECT_EQ(num_config, 3); } TEST(t_dlt_logstorage_get_config, null) { int num = -1; num = dlt_logstorage_get_config(NULL, NULL, NULL, NULL, NULL); EXPECT_EQ(num, 0); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_filter*/ TEST(t_dlt_logstorage_filter, normal) { char apid[] = "1234"; char ctid[] = "5678"; char ecuid[] = "12"; char filename[] = "file_name"; int num = 1; DltLogStorageFilterConfig value; memset(&value, 0, sizeof(DltLogStorageFilterConfig)); value.apids = apid; value.ctids = ctid; value.ecuid = ecuid; value.file_name = filename; value.log_level = DLT_LOG_VERBOSE; char key0[] = ":1234:\000\000\000\000"; char key1[] = "::5678\000\000\000\000"; char key2[] = ":1234:5678"; DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; DltLogStorage handle; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; handle.config_list = NULL; handle.newest_file_list = NULL; int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key0, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key1, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key2, num_keys, &value, &(handle.config_list))); num = dlt_logstorage_filter(&handle, config, apid, ctid, ecuid, 0); EXPECT_EQ(num, 3); } TEST(t_dlt_logstorage_filter, null) { DltLogStorageFilterConfig *config[3] = { 0 }; int num = dlt_logstorage_filter(NULL, config, NULL, NULL, NULL, 0); EXPECT_EQ(DLT_RETURN_ERROR, num); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_write*/ TEST(t_dlt_logstorage_write, normal) { char apid[] = "1234"; char ctid[] = "5678"; char ecuid[] = "12"; char file_name[] = "file_name"; DltLogStorage handle; DltLogStorageUserConfig uconfig; unsigned char data1[] = "123"; int size1 = 3; unsigned char data2[] = "123"; int size2 = 3; unsigned char data3[] = "123"; int size3 = 3; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; handle.config_list = NULL; handle.newest_file_list = NULL; DltLogStorageFilterConfig value; memset(&value, 0, sizeof(DltLogStorageFilterConfig)); value.apids = apid; value.ctids = ctid; value.ecuid = ecuid; value.file_name = file_name; char key0[] = ":1234:\000\000\000\000"; char key1[] = "::5678\000\000\000\000"; char key2[] = ":1234:5678"; int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key0, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key1, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key2, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write(&handle, &uconfig, data1, size1, data2, size2, data3, size3)); } TEST(t_dlt_logstorage_write, null) { EXPECT_EQ(0, dlt_logstorage_write(NULL, NULL, NULL, 1, NULL, 1, NULL, 1)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sync_caches*/ TEST(t_dlt_logstorage_sync_caches, normal) { char apid[] = "1234"; char ctid[] = "5678"; char ecuid[] = "12"; char filename[] = "file_name"; char key[] = "12:1234:5678"; DltLogStorage handle; handle.num_configs = 1; handle.config_list = NULL; DltLogStorageFilterConfig configs; memset(&configs, 0, sizeof(DltLogStorageFilterConfig)); configs.apids = apid; configs.ctids = ctid; configs.ecuid = ecuid; configs.file_name = filename; int num_keys = 1; dlt_logstorage_filter_set_strategy(&configs, DLT_LOGSTORAGE_SYNC_ON_MSG); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key, num_keys, &configs, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_sync_caches(&handle)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_log_file_name*/ TEST(t_dlt_logstorage_log_file_name, normal) { char log_file_name[DLT_MOUNT_PATH_MAX] = { '\0' }; DltLogStorageUserConfig file_config; memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); file_config.logfile_delimiter = '/'; file_config.logfile_maxcounter = 0; file_config.logfile_timestamp = 1; file_config.logfile_counteridxlen = 10; int cmpRes = 0; char name[] = "log"; DltLogStorageFilterConfig filter_config; memset(&filter_config, 0, sizeof(filter_config)); filter_config.file_name = &name[0]; dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, 0); cmpRes = strncmp(log_file_name, "log/0000000000", 14); EXPECT_EQ(0, cmpRes); } TEST(t_dlt_logstorage_log_file_name, null) { dlt_logstorage_log_file_name(NULL, NULL, NULL, 0); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sort_file_name*/ TEST(t_dlt_logstorage_sort_file_name, normal) { DltLogStorageFileList *node1, *node2, *node3; DltLogStorageFileList **head; node1 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); node2 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); node3 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); if ((node1 != NULL) && (node2 != NULL) && (node3 != NULL)) { node1->next = node2; node2->next = node3; node3->next = NULL; head = &node1; node1->idx = 8; node2->idx = 4; node3->idx = 1; EXPECT_EQ(8, (*head)->idx); EXPECT_EQ(4, ((*head)->next)->idx); EXPECT_EQ(1, ((((*head)->next)->next)->idx)); EXPECT_EQ(8, dlt_logstorage_sort_file_name(head)); EXPECT_EQ(1, (*head)->idx); EXPECT_EQ(4, ((*head)->next)->idx); EXPECT_EQ(8, ((((*head)->next)->next)->idx)); free((((*head)->next)->next)); free(((*head)->next)); free(*head); node1 = NULL; node2 = NULL; node3 = NULL; } if (node1 != NULL) free(node1); if (node2 != NULL) free(node2); if (node3 != NULL) free(node3); } TEST(t_dlt_logstorage_sort_file_name, null) { dlt_logstorage_sort_file_name(NULL); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_rearrange_file_name*/ TEST(t_dlt_logstorage_rearrange_file_name, normal1) { DltLogStorageFileList *node1, *node2, *node3; DltLogStorageFileList **head; node1 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); node2 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); node3 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); if ((node1 != NULL) && (node2 != NULL) && (node3 != NULL)) { node1->next = node2; node2->next = node3; node3->next = NULL; head = &node1; node1->idx = 1; node2->idx = 4; node3->idx = 8; EXPECT_EQ(1, (*head)->idx); EXPECT_EQ(4, ((*head)->next)->idx); EXPECT_EQ(8, ((((*head)->next)->next)->idx)); dlt_logstorage_rearrange_file_name(head); EXPECT_EQ(4, (*head)->idx); EXPECT_EQ(8, ((*head)->next)->idx); EXPECT_EQ(1, ((((*head)->next)->next)->idx)); free((((*head)->next)->next)); free(((*head)->next)); free(*head); node1 = NULL; node2 = NULL; node3 = NULL; } if (node1 != NULL) free(node1); if (node2 != NULL) free(node2); if (node3 != NULL) free(node3); } TEST(t_dlt_logstorage_rearrange_file_name, normal2) { DltLogStorageFileList *node1, *node2, *node3; DltLogStorageFileList **head; node1 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); node2 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); node3 = (DltLogStorageFileList *)calloc (1, sizeof(DltLogStorageFileList)); if ((node1 != NULL) && (node2 != NULL) && (node3 != NULL)) { node1->next = node2; node2->next = node3; node3->next = NULL; head = &node1; node1->idx = 2; node2->idx = 4; node3->idx = 8; EXPECT_EQ(2, (*head)->idx); EXPECT_EQ(4, ((*head)->next)->idx); EXPECT_EQ(8, ((((*head)->next)->next)->idx)); dlt_logstorage_rearrange_file_name(head); EXPECT_EQ(2, (*head)->idx); EXPECT_EQ(4, ((*head)->next)->idx); EXPECT_EQ(8, ((((*head)->next)->next)->idx)); free((((*head)->next)->next)); free(((*head)->next)); free(*head); node1 = NULL; node2 = NULL; node3 = NULL; } if (node1 != NULL) free(node1); if (node2 != NULL) free(node2); if (node3 != NULL) free(node3); } TEST(t_dlt_logstorage_rearrange_file_name, null) { dlt_logstorage_rearrange_file_name(NULL); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_get_idx_of_log_file*/ TEST(t_dlt_logstorage_get_idx_of_log_file, normal) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char name[] = "Test"; char *file = (char *)"Test_002_20160509_191132.dlt"; DltLogStorageFilterConfig filter_config; memset(&filter_config, 0, sizeof(filter_config)); filter_config.file_name = &name[0]; EXPECT_EQ(2, dlt_logstorage_get_idx_of_log_file(&file_config, &filter_config, file)); char *gz_file = (char *)"Test_142_20160509_191132.dlt.gz"; filter_config.gzip_compression = 1; EXPECT_EQ(142, dlt_logstorage_get_idx_of_log_file(&file_config, &filter_config, gz_file)); } TEST(t_dlt_logstorage_get_idx_of_log_file, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_get_idx_of_log_file(NULL, NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_storage_dir_info*/ TEST(t_dlt_logstorage_storage_dir_info, normal) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test_002_20160509_191132.dlt"; config.records = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_storage_dir_info(&file_config, path, &config)); } TEST(t_dlt_logstorage_storage_dir_info, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_storage_dir_info(NULL, NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_open_log_file*/ TEST(t_dlt_logstorage_open_log_file, normal) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.working_file_name = NULL; config.wrap_id = 0; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_open_log_file(&config, &file_config, path, 1, true)); } TEST(t_dlt_logstorage_open_log_file, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_open_log_file(NULL, NULL, NULL, 0, true)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_prepare_on_msg*/ TEST(t_dlt_logstorage_prepare_on_msg, normal1) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.working_file_name = NULL; config.wrap_id = 0; DltNewestFileName newest_file_name; newest_file_name.file_name = (char *)"Test"; newest_file_name.newest_file = (char *)"Test_003_20200728_191132.dlt"; newest_file_name.wrap_id = 0; newest_file_name.next = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_on_msg(&config, &file_config, path, 1, &newest_file_name)); } TEST(t_dlt_logstorage_prepare_on_msg, normal2) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.working_file_name = NULL; config.wrap_id = 0; DltNewestFileName newest_file_name; newest_file_name.file_name = (char *)"Test"; newest_file_name.newest_file = (char *)"Test_003_20200728_191132.dlt"; newest_file_name.wrap_id = 1; newest_file_name.next = NULL; /* Create dummy file */ char dummy_file[100] = ""; sprintf(dummy_file, "%s/%s", path, newest_file_name.newest_file); int ret = 0; FILE *fp = fopen(dummy_file, "w"); ret = ftruncate(fileno(fp), 1024); fclose(fp); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_on_msg(&config, &file_config, path, 1, &newest_file_name)); if (ret == 0) { remove(dummy_file); } } TEST(t_dlt_logstorage_prepare_on_msg, normal3) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; char *working_file_name = (char *)"Test_002_20160509_191132.dlt"; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.working_file_name = strdup(working_file_name); config.wrap_id = 0; DltNewestFileName newest_file_name; newest_file_name.file_name = (char *)"Test"; newest_file_name.newest_file = (char *)"Test_003_20200728_191132.dlt"; newest_file_name.wrap_id = 1; newest_file_name.next = NULL; /* Create dummy file */ char dummy_file[100] = ""; sprintf(dummy_file, "%s/%s", path, newest_file_name.newest_file); int ret = 0; FILE *fp = fopen(dummy_file, "w"); ret = ftruncate(fileno(fp), 1024); fclose(fp); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_on_msg(&config, &file_config, path, 1, &newest_file_name)); if (ret == 0) { remove(dummy_file); } } TEST(t_dlt_logstorage_prepare_on_msg, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_prepare_on_msg(NULL, NULL, NULL, 0, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_write_on_msg*/ TEST(t_dlt_logstorage_write_on_msg, normal) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.working_file_name = NULL; config.wrap_id = 0; config.gzip_compression = 0; unsigned int size = 8; unsigned char data1[] = "dlt_data"; unsigned char data2[] = "dlt_data"; unsigned char data3[] = "dlt_data"; DltNewestFileName newest_file_name; newest_file_name.file_name = (char *)"Test"; newest_file_name.newest_file = (char *)"Test_003_20200728_191132.dlt"; newest_file_name.wrap_id = 0; newest_file_name.next = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_on_msg(&config, &file_config, path, 1, &newest_file_name)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_on_msg(&config, &file_config, path, data1, size, data2, size, data3, size)); } #ifdef DLT_LOGSTORAGE_USE_GZIP TEST(t_dlt_logstorage_write_on_msg, gzip) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.working_file_name = NULL; config.wrap_id = 0; config.gzip_compression = 1; unsigned int size = 8; unsigned char data1[] = "dlt_data"; unsigned char data2[] = "dlt_data"; unsigned char data3[] = "dlt_data"; DltNewestFileName newest_file_name; newest_file_name.file_name = (char *)"Test"; newest_file_name.newest_file = (char *)"Test_003_20200728_191132.dlt.gz"; newest_file_name.wrap_id = 0; newest_file_name.next = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_on_msg(&config, &file_config, path, 1, &newest_file_name)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_on_msg(&config, &file_config, path, data1, size, data2, size, data3, size)); } #endif TEST(t_dlt_logstorage_write_on_msg, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_write_on_msg(NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sync_on_msg*/ TEST(t_dlt_logstorage_sync_on_msg, normal) { DltLogStorageFilterConfig config; DltLogStorageUserConfig file_config; char apids; char ctids; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.working_file_name = NULL; config.wrap_id = 0; char *path = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_sync_on_msg(&config, &file_config, path, DLT_LOGSTORAGE_SYNC_ON_MSG)); } TEST(t_dlt_logstorage_sync_on_msg, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_sync_on_msg(NULL, NULL, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_prepare_msg_cache*/ TEST(t_dlt_logstorage_prepare_msg_cache, normal) { DltLogStorageUserConfig file_config; file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; DltNewestFileName newest_info; memset(&newest_info, 0, sizeof(DltNewestFileName)); memset(&config, 0, sizeof(DltLogStorageFilterConfig)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.cache = NULL; config.file_size = 0; config.sync = DLT_LOGSTORAGE_SYNC_ON_DEMAND; config.working_file_name = NULL; config.wrap_id = 0; g_logstorage_cache_max = 16; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_msg_cache(&config, &file_config, path, 1, &newest_info)); free(config.cache); } TEST(t_dlt_logstorage_prepare_msg_cache, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_prepare_msg_cache(NULL, NULL, NULL, 0, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_write_msg_cache*/ TEST(t_dlt_logstorage_write_msg_cache, normal) { unsigned int size = 10; unsigned char data1[10] = "dlt_data1"; unsigned char data2[10] = "dlt_data2"; unsigned char data3[10] = "dlt_dat3"; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); DltLogStorageUserConfig file_config; char *path = (char*)"/tmp"; config.cache = calloc(1, 50 + sizeof(DltLogStorageCacheFooter)); if (config.cache != NULL) { config.file_size = 50; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_msg_cache(&config, &file_config, path, data1, size, data2, size, data3, size)); free(config.cache); config.cache = NULL; } } TEST(t_dlt_logstorage_write_msg_cache, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_write_msg_cache(NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_split_key*/ TEST(t_dlt_logstorage_split_key, normal) { char key[] = "dlt:1020:"; char apid[] = ":2345:"; char ctid[] = "::6789"; char ecuid[] = "ECU1"; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_split_key(key, apid, ctid, ecuid)); } TEST(t_dlt_logstorage_split_key, null) { char key[] = "dlt:1020:"; char apid[] = "2345"; char ctid[] = "6789"; char ecuid[] = "ECU1"; EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_split_key(NULL, NULL, NULL, NULL)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_split_key(NULL, apid, ctid, ecuid)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_split_key(key, NULL, ctid, ecuid)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_split_key(key, apid, NULL, ecuid)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_split_key(key, apid, ctid, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_update_all_contexts*/ TEST(t_dlt_logstorage_update_all_contexts, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); char ecu[] = "ECU1"; char apid[] = "123"; daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_update_all_contexts(&daemon, &daemon_local, apid, 1, 1, ecu, 0)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_update_all_contexts(&daemon, &daemon_local, apid, 0, 1, ecu, 0)); } TEST(t_dlt_logstorage_update_all_contexts, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_update_all_contexts(NULL, NULL, NULL, 0, 0, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_update_context*/ TEST(t_dlt_logstorage_update_context, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); int fd = connectServer(); EXPECT_NE(-1, fd); daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; char apid[] = "123"; char ctid[] = "456"; char desc[255] = "TEST dlt_logstorage_update_context"; char ecu[] = "ECU1"; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); app = dlt_daemon_application_add(&daemon, apid, getpid(), desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, app->user_handle, desc, daemon.ecuid, 0); EXPECT_NE((DltDaemonContext *)(NULL), daecontext); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_update_context(&daemon, &daemon_local, apid, ctid, ecu, 1, 0)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_update_context(&daemon, &daemon_local, apid, ctid, ecu, 0, 0)); } TEST(t_dlt_logstorage_update_context, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_update_context(NULL, NULL, NULL, NULL, NULL, 0, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_update_context_loglevel*/ TEST(t_dlt_logstorage_update_context_loglevel, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; DltDaemonContext *daecontext = NULL; DltDaemonApplication *app = NULL; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); int fd = connectServer(); EXPECT_NE(-1, fd); daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; char apid[] = "123"; char ctid[] = "456"; char key[] = ":123:456"; char desc[255] = "TEST dlt_logstorage_update_context_loglevel"; char ecu[] = "ECU1"; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); app = dlt_daemon_application_add(&daemon, apid, getpid(), desc, fd, ecu, 0); daecontext = dlt_daemon_context_add(&daemon, apid, ctid, DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT, 0, app->user_handle, desc, daemon.ecuid, 0); EXPECT_NE((DltDaemonContext *)(NULL), daecontext); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_update_context_loglevel (&daemon, &daemon_local, key, 1, 0)); } TEST(t_dlt_logstorage_update_context_loglevel, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_logstorage_update_context_loglevel(NULL, NULL, NULL, 0, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_reset_application_loglevel*/ TEST(t_dlt_daemon_logstorage_reset_application_loglevel, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(daemon_local)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; char ecu[] = "ECU1"; int device_index = 0; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); EXPECT_NO_THROW(dlt_daemon_logstorage_reset_application_loglevel(&daemon, &daemon_local, device_index, 1, 0)); } TEST(t_dlt_daemon_logstorage_reset_application_loglevel, null) { EXPECT_NO_THROW(dlt_daemon_logstorage_reset_application_loglevel(NULL, NULL, 0, 0, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_get_loglevel*/ TEST(t_dlt_daemon_logstorage_get_loglevel, normal) { char ecu[] = "ECU1"; char apid[] = "1234"; char ctid[] = "5678"; char file_name[] = "file_name"; char key[] = "ECU1:1234:5678"; int device_index = 0; DltDaemon daemon; DltDaemonLocal daemon_local; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); DltLogStorageFilterConfig value; memset(&value, 0, sizeof(DltLogStorageFilterConfig)); value.log_level = 4; value.apids = apid; value.ctids = ctid; value.ecuid = ecu; value.file_name = file_name; DltLogStorage storage_handle; daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); daemon.storage_handle = &storage_handle; daemon.storage_handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; daemon.storage_handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; daemon.storage_handle->config_list = NULL; daemon.storage_handle->num_configs = 1; int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_NO_THROW(dlt_daemon_logstorage_update_application_loglevel(&daemon, &daemon_local, device_index, 0)); EXPECT_EQ(4, dlt_daemon_logstorage_get_loglevel(&daemon, 1, apid, ctid)); } TEST(t_dlt_daemon_logstorage_get_loglevel, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_daemon_logstorage_get_loglevel(NULL, 0, NULL, NULL)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_update_application_loglevel*/ TEST(t_dlt_daemon_logstorage_update_application_loglevel, normal) { char ecu[] = "key"; char apid[] = "1234"; char ctid[] = "5678"; char file_name[] = "file_name"; char key[] = "key:1234:5678"; int device_index = 0; DltDaemon daemon; DltDaemonLocal daemon_local; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); DltLogStorageFilterConfig value; memset(&value, 0, sizeof(DltLogStorageFilterConfig)); value.log_level = 5; value.apids = apid; value.ctids = ctid; value.ecuid = ecu; value.file_name = file_name; DltLogStorage storage_handle; daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); daemon.storage_handle = &storage_handle; daemon.storage_handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; daemon.storage_handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; daemon.storage_handle->config_list = NULL; int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_NO_THROW(dlt_daemon_logstorage_update_application_loglevel(&daemon, &daemon_local, device_index, 0)); } TEST(t_dlt_daemon_logstorage_update_application_loglevel, null) { EXPECT_NO_THROW(dlt_daemon_logstorage_update_application_loglevel(NULL, NULL, 0, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_write*/ TEST(t_dlt_daemon_logstorage_write, normal) { DltDaemon daemon; DltGateway gateway; memset(&daemon, 0, sizeof(DltDaemon)); memset(&gateway, 0, sizeof(DltGateway)); char ecu[] = "ECU1"; DltLogStorage storage_handle; EXPECT_EQ(0, dlt_daemon_init(&daemon, DLT_DAEMON_RINGBUFFER_MIN_SIZE, DLT_DAEMON_RINGBUFFER_MAX_SIZE, DLT_DAEMON_RINGBUFFER_STEP_SIZE, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &gateway, 0, 0)); daemon.storage_handle = &storage_handle; char apid[] = "1234"; char ctid[] = "5678"; char ecuid[] = "12"; char file_name[] = "file_name"; DltDaemonFlags uconfig; uconfig.offlineLogstorageTimestamp = 1; uconfig.offlineLogstorageDelimiter = '/'; uconfig.offlineLogstorageMaxCounter = 5; uconfig.offlineLogstorageMaxCounterIdx = 1; uconfig.offlineLogstorageMaxDevices = 1; unsigned char data1[] = "123"; unsigned char data2[] = "123"; unsigned char data3[] = "123"; int size = 10 * sizeof(uint32_t); daemon.storage_handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; daemon.storage_handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; daemon.storage_handle->config_list = NULL; DltLogStorageFilterConfig value; memset(&value, 0, sizeof(DltLogStorageFilterConfig)); value.apids = apid; value.ctids = ctid; value.ecuid = ecuid; value.file_name = file_name; char key0[] = "1234:\000\000\000\000"; char key1[] = ":5678\000\000\000\000"; char key2[] = "1234:5678"; int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key0, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key1, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key2, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_NO_THROW(dlt_daemon_logstorage_write(&daemon, &uconfig, data1, size, data2, size, data3, size)); } TEST(t_dlt_daemon_logstorage_write, null) { EXPECT_NO_THROW(dlt_daemon_logstorage_write(NULL, NULL, NULL, 0, NULL, 0, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_setup_internal_storage*/ TEST(t_dlt_daemon_logstorage_setup_internal_storage, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; memset(&daemon, 0, sizeof(DltDaemon)); memset(&daemon_local, 0, sizeof(DltDaemonLocal)); memset(&daemon_local.pGateway, 0, sizeof(DltGateway)); daemon_local.RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE; daemon_local.RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE; daemon_local.RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE; char ecu[] = "ECU1"; char path[] = "/tmp"; EXPECT_EQ(0, dlt_daemon_init(&daemon, daemon_local.RingbufferMinSize, daemon_local.RingbufferMaxSize, daemon_local.RingbufferStepSize, DLT_RUNTIME_DEFAULT_DIRECTORY, DLT_LOG_INFO, DLT_TRACE_STATUS_OFF, 0, 0)); dlt_set_id(daemon.ecuid, ecu); EXPECT_EQ(0, dlt_daemon_init_user_information(&daemon, &daemon_local.pGateway, 0, 0)); DltLogStorage storage_handle; daemon.storage_handle = &storage_handle; daemon.storage_handle->config_status = 0; daemon.storage_handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED; daemon.storage_handle->config_list = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_logstorage_setup_internal_storage(&daemon, &daemon_local, path, 1)); } TEST(t_dlt_daemon_logstorage_setup_internal_storage, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_daemon_logstorage_setup_internal_storage(NULL, NULL, NULL, 0)); } /* Begin Method: dlt_logstorage::dlt_daemon_logstorage_set_logstorage_cache_size*/ TEST(t_dlt_daemon_logstorage_set_logstorage_cache_size, normal) { EXPECT_NO_THROW(dlt_daemon_logstorage_set_logstorage_cache_size(1)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_cleanup*/ TEST(t_dlt_daemon_logstorage_cleanup, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; daemon_local.flags.offlineLogstorageMaxDevices = 1; DltLogStorage storage_handle; daemon.storage_handle = &storage_handle; daemon.storage_handle->config_status = 0; EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_logstorage_cleanup(&daemon, &daemon_local, 0)); } TEST(t_dlt_daemon_logstorage_cleanup, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_daemon_logstorage_cleanup(NULL, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_sync_cache*/ TEST(t_dlt_daemon_logstorage_sync_cache, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; daemon_local.flags.offlineLogstorageMaxDevices = 1; DltLogStorage storage_handle; daemon.storage_handle = &storage_handle; daemon.storage_handle->config_status = 0; char path[] = "/tmp"; char apid[] = "1234"; char ctid[] = "5678"; char ecuid[] = "12"; char file_name[] = "file_name"; char key[] = "12:1234:5678"; daemon.storage_handle->num_configs = 1; daemon.storage_handle->config_list = NULL; strncpy(daemon.storage_handle->device_mount_point, "/tmp", 5); DltLogStorageFilterConfig configs; memset(&configs, 0, sizeof(DltLogStorageFilterConfig)); configs.apids = apid; configs.ctids = ctid; configs.ecuid = ecuid; configs.file_name = file_name; dlt_logstorage_filter_set_strategy(&configs, DLT_LOGSTORAGE_SYNC_ON_MSG); int num_keys = 1; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key, num_keys, &configs, &(daemon.storage_handle->config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_logstorage_sync_cache(&daemon, &daemon_local, path, 0)); } TEST(t_dlt_daemon_logstorage_sync_cache, null) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_daemon_logstorage_sync_cache(NULL, NULL, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_get_device*/ TEST(t_dlt_daemon_logstorage_get_device, normal) { DltDaemon daemon; DltDaemonLocal daemon_local; daemon_local.flags.offlineLogstorageMaxDevices = 1; DltLogStorage storage_handle; daemon.storage_handle = &storage_handle; daemon.storage_handle->config_status = 0; char path[] = "/tmp"; strncpy(daemon.storage_handle->device_mount_point, "/tmp", 5); EXPECT_NE((DltLogStorage *)NULL, dlt_daemon_logstorage_get_device(&daemon, &daemon_local, path, 0)); } TEST(t_dlt_daemon_logstorage_get_device, null) { EXPECT_EQ((DltLogStorage *)NULL, dlt_daemon_logstorage_get_device(NULL, NULL, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_find_dlt_header*/ TEST(t_dlt_logstorage_find_dlt_header, normal) { char data[] = { 'a', 'b', 'D', 'L', 'T', 0x01 }; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.cache = calloc(1, sizeof(data)); if (config.cache != NULL) { strncpy((char *)config.cache, data, sizeof(data)); /* DLT header starts from index 2 */ EXPECT_EQ(2, dlt_logstorage_find_dlt_header(config.cache, 0, sizeof(data))); free(config.cache); } } TEST(t_dlt_logstorage_find_dlt_header, null) { char data[] = { 'N', 'o', 'H', 'e', 'a', 'd', 'e', 'r' }; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.cache = calloc(1, sizeof(data)); if (config.cache != NULL) { /* config.cache =(void *) "a,b,D,L,T,0x01"; */ strncpy((char *)config.cache, data, sizeof(data)); EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_find_dlt_header(config.cache, 0, sizeof(data))); free(config.cache); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_find_last_dlt_header*/ TEST(t_dlt_logstorage_find_last_dlt_header, normal) { char data[] = {'a','b','D','L','T',0x01}; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.cache = calloc(1, sizeof(data)); if (config.cache != NULL) { strncpy((char *)config.cache, data, sizeof(data)); /* DLT header starts from index 2 */ EXPECT_EQ(2, dlt_logstorage_find_last_dlt_header(config.cache, 0, sizeof(data))); free(config.cache); } } TEST(t_dlt_logstorage_find_last_dlt_header, null) { char data[] = {'N','o','H','e','a','d','e','r'}; DltLogStorageFilterConfig config; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.cache = calloc(1, sizeof(data)); if (config.cache != NULL) { /* config.cache =(void *) "a,b,D,L,T,0x01"; */ strncpy((char *)config.cache, data, sizeof(data)); EXPECT_EQ(-1, dlt_logstorage_find_last_dlt_header(config.cache, 0, sizeof(data))); free(config.cache); } } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sync_to_file*/ TEST(t_dlt_logstorage_sync_to_file, normal) { DltLogStorageUserConfig file_config; memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); file_config.logfile_timestamp = 191132; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 6; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; DltNewestFileName newest_info; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); memset(&newest_info, 0, sizeof(DltNewestFileName)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.cache = NULL; config.sync = DLT_LOGSTORAGE_SYNC_ON_DEMAND; config.num_files = 6; config.file_size = 50; g_logstorage_cache_max = 16; unsigned int size = 10; unsigned char data1[10] = "dlt_data0"; unsigned char data2[10] = "dlt_data1"; unsigned char data3[10] = "dlt_data2"; newest_info.wrap_id = 0; config.wrap_id = 0; DltLogStorageCacheFooter *footer = NULL; config.cache = calloc(1, config.file_size + sizeof(DltLogStorageCacheFooter)); if (config.cache != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_msg_cache(&config, &file_config, path, 1, &newest_info)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_msg_cache(&config, &file_config, path, data1, size, data2, size, data3, size)); footer = (DltLogStorageCacheFooter *)((uint8_t*)config.cache + config.file_size); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_sync_to_file(&config, &file_config, path, footer, footer->last_sync_offset, footer->offset)); free(config.cache); config.cache = NULL; } } TEST(t_dlt_logstorage_sync_to_file, null) { EXPECT_EQ(-1, dlt_logstorage_sync_to_file(NULL, NULL, NULL, NULL, 0, 1)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sync_msg_cache*/ TEST(t_dlt_logstorage_sync_msg_cache, normal) { DltLogStorageUserConfig file_config; memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); file_config.logfile_timestamp = 191132; file_config.logfile_timestamp = 0; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 8; file_config.logfile_counteridxlen = 2; char *path = (char *)"/tmp"; DltLogStorageFilterConfig config; DltNewestFileName newest_info; memset(&config, 0, sizeof(DltLogStorageFilterConfig)); memset(&newest_info, 0, sizeof(DltNewestFileName)); char apids; char ctids; config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; config.records = NULL; config.log = NULL; config.cache = NULL; config.file_size = 50; config.sync = DLT_LOGSTORAGE_SYNC_ON_DEMAND; config.num_files = 8; g_logstorage_cache_max = 16; unsigned int size = 10; unsigned char data1[10] = "dlt_dataA"; unsigned char data2[10] = "dlt_dataB"; unsigned char data3[10] = "dlt_dataC"; config.cache = calloc(1, config.file_size + sizeof(DltLogStorageCacheFooter)); if (config.cache != NULL) { EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_msg_cache(&config, &file_config, path, 1, &newest_info)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_msg_cache(&config, &file_config, path, data1, size, data2, size, data3, size)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_sync_msg_cache(&config, &file_config, path, DLT_LOGSTORAGE_SYNC_ON_DEMAND)); free(config.cache); config.cache = NULL; } } TEST(t_dlt_logstorage_sync_msg_cache, null) { EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_sync_msg_cache(NULL, NULL, NULL, 0)); } int connectServer(void) { #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC int sockfd, portno; struct sockaddr_in serv_addr; struct hostent *server; portno = 8080; sockfd = socket(AF_INET, SOCK_STREAM, 0); server = gethostbyname("127.0.0.1"); memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("Error: %s (%d) occured in connect socket\n", strerror(errno), errno); close(sockfd); return -1; } #else /* DLT_DAEMON_USE_FIFO_IPC */ char filename[1024]; int sockfd; snprintf(filename, 1024, "/tmp/dltpipes/dlt%d", getpid()); /* Try to delete existing pipe, ignore result of unlink */ unlink(filename); mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP); chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP); sockfd = open(filename, O_RDWR | O_CLOEXEC); #endif return sockfd; } #define GTEST_SOCKS_ACCEPTED 2 int main(int argc, char **argv) { #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC pid_t cpid; cpid = fork(); if (cpid == -1) { printf("fork fail\n"); return -1; } if (cpid) { int i = GTEST_SOCKS_ACCEPTED; int j, optval = 1; char buffer[256]; int sockfd, newsockfd[GTEST_SOCKS_ACCEPTED], portno; socklen_t clilen; struct sockaddr_in serv_addr, cli_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("Error in creating socket\n"); return -1; } memset((char *) &serv_addr, 0, sizeof(serv_addr)); portno = 8080; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { perror("setsockopt"); close(sockfd); exit(1); } j = bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (j == -1) { perror("Bind Error\n"); close(sockfd); return -1; } listen(sockfd, 5); while (i) { clilen = sizeof(cli_addr); newsockfd[i - 1] = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); if (newsockfd[i - 1] == -1) { printf("Error in accept"); return -1; } memset(buffer, 0, 256); (void)(read(newsockfd[i - 1], buffer, 255) + 1); /* just ignore result */ i--; } for (j = 0; j < GTEST_SOCKS_ACCEPTED; j++) close(newsockfd[i]); close(sockfd); } else { #endif ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_break_on_failure = false; /* ::testing::FLAGS_gtest_filter = "t_dlt_event_handler_register_connection*"; */ return RUN_ALL_TESTS(); #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC } #endif return 0; } dlt-daemon-2.18.10/tests/gtest_dlt_daemon_offline_log.sh000077500000000000000000000030101446635226000232710ustar00rootroot00000000000000#!/bin/sh ######################################################################################## #file : g_test_dlt_daemon_logstorage.sh # #Description : logstorage unit test preparation # #Author Name : Onkar Palkar #Email Id : onkar.palkar@wipro.com # #History : Last modified date : 02/09/2016 ######################################################################################## # # Function: -cleanup() # # Description -Delete dlt_logstorage.conf file from tmp folder if present # # Return -Zero on success # -Non zero on failure # cleanup() { tmpPath=/tmp cd $tmpPath rm -rf $tmpPath/dlt_logstorage.conf return 0 } # # Function: -setupTest() # # Description -create logstorage.conf file # # Return -Zero on success # -Non zero on failure # setupTest() { touch $tmpPath/dlt_logstorage.conf if [ $? -eq '1' ] then echo "Error in creating dlt_logstorage.conf file" return 1 fi echo "[FILTER1]" >>$tmpPath/dlt_logstorage.conf echo "LogAppName=DLST" >>$tmpPath/dlt_logstorage.conf echo "ContextName=.*" >>$tmpPath/dlt_logstorage.conf echo "LogLevel=DLT_LOG_ERROR" >>$tmpPath/dlt_logstorage.conf echo "File=Test" >>$tmpPath/dlt_logstorage.conf echo "FileSize=1000000" >>$tmpPath/dlt_logstorage.conf echo "NOFiles=1" >>$tmpPath/dlt_logstorage.conf return 0 } #main function ######################################################################################## cleanup setupTest dlt-daemon-2.18.10/tests/gtest_dlt_json_filter.cpp000066400000000000000000000046201446635226000221560ustar00rootroot00000000000000#include #include #include #include extern "C" { #include "dlt-control-common.h" #include "dlt-daemon.h" } /* Begin Method: dlt_common::dlt_message_print_ascii with json filter*/ TEST(t_dlt_message_print_ascii_with_json_filter, normal) { DltFile file; DltFilter filter; static char text[DLT_DAEMON_TEXTSIZE]; /* Get PWD so file can be used*/ char pwd[100]; char openfile[114]; /* ignore returned value from getcwd */ if (getcwd(pwd, 100) == NULL) {} char openfilter[117]; sprintf(openfile, "%s/testfile_extended.dlt", pwd); sprintf(openfilter, "%s/testfilter.json", pwd); /*---------------------------------------*/ /* Normal Use-Case, expect 0 */ EXPECT_LE(DLT_RETURN_OK, dlt_file_init(&file, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_filter_init(&filter, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_json_filter_load(&filter, openfilter, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_set_filter(&file, &filter, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_file_open(&file, openfile, 0)); char tmp[DLT_ID_SIZE+1]; strncpy(tmp, filter.apid[0], DLT_ID_SIZE); tmp[DLT_ID_SIZE] = {}; EXPECT_STREQ("LOG",tmp); EXPECT_EQ(3,filter.log_level[0]); EXPECT_EQ(0,filter.payload_min[0]); EXPECT_EQ(INT32_MAX,filter.payload_max[0]); strncpy(tmp, filter.apid[1], DLT_ID_SIZE); EXPECT_STREQ("app",tmp); strncpy(tmp, filter.ctid[1], DLT_ID_SIZE); EXPECT_STREQ("",tmp); EXPECT_EQ(0,filter.log_level[2]); EXPECT_EQ(20,filter.payload_min[2]); EXPECT_EQ(50,filter.payload_max[2]); while (dlt_file_read(&file, 0) >= 0) {} for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 0)); } for (int i = 0; i < file.counter; i++) { EXPECT_LE(DLT_RETURN_OK, dlt_file_message(&file, i, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_message_print_ascii(&file.msg, text, DLT_DAEMON_TEXTSIZE, 1)); } EXPECT_LE(DLT_RETURN_OK, dlt_file_free(&file, 0)); } TEST(t_dlt_message_print_ascii_with_json_filter, abnormal) { /* equal with t_dlt_message_print_ascii */ } TEST(t_dlt_message_print_ascii_with_json_filter, nullpointer) { /* equal with t_dlt_message_print_ascii */ } /* End Method: dlt_common::dlt_message_print_ascii with json filter*/ dlt-daemon-2.18.10/tests/gtest_dlt_shm.cpp000066400000000000000000000033001446635226000204210ustar00rootroot00000000000000#include extern "C" { #include "dlt_shm.h" } DltShm *server_buf = (DltShm *)calloc(1, sizeof(DltShm)); DltShm *client_buf = (DltShm *)calloc(1, sizeof(DltShm)); char *dltShmNameTest = (char *)"dlt-shm-test"; int size = 1000; /* Method: dlt_shm::t_dlt_shm_init_server */ TEST(t_dlt_shm_init_server, normal) { EXPECT_EQ(DLT_RETURN_OK, dlt_shm_init_server(server_buf, dltShmNameTest, size)); } /* Method: dlt_shm::t_dlt_shm_init_server */ TEST(t_dlt_shm_init_server, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_shm_init_server(NULL, NULL, size)); } /* Method: dlt_shm::t_dlt_shm_init_client */ TEST(t_dlt_shm_init_client, normal) { EXPECT_EQ(DLT_RETURN_OK, dlt_shm_init_client(client_buf, dltShmNameTest)); } /* Method: dlt_shm::t_dlt_shm_init_client */ TEST(t_dlt_shm_init_client, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_shm_init_client(NULL, NULL)); } /* Method: dlt_shm::t_dlt_shm_free_client */ TEST(t_dlt_shm_free_client, normal) { EXPECT_EQ(DLT_RETURN_OK, dlt_shm_free_client(client_buf)); } /* Method: dlt_shm::t_dlt_shm_free_client */ TEST(t_dlt_shm_free_client, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_shm_free_client(NULL)); } /* Method: dlt_shm::t_dlt_shm_free_server */ TEST(t_dlt_shm_free_server, normal) { EXPECT_EQ(DLT_RETURN_OK, dlt_shm_free_server(server_buf, dltShmNameTest)); } /* Method: dlt_shm::t_dlt_shm_free_server */ TEST(t_dlt_shm_free_server, nullpointer) { EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_shm_free_server(NULL, NULL)); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_break_on_failure = false; return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/gtest_dlt_user.cpp000066400000000000000000007317331446635226000206320ustar00rootroot00000000000000/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of COVESA Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.covesa.org/. */ /*! * \author Jens Bocklage * \author Stefan Held * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file gtest_dlt_common.cpp */ #include #include "gtest/gtest.h" #include #include #include #include #include #include extern "C" { #include "dlt_user.h" #include "dlt_user_cfg.h" } /* TEST COMMENTED OUT WITH */ /* TODO: */ /* DO FAIL! */ /* tested functions */ /* * int dlt_user_log_write_start(DltContext *handle, DltContextData *log, DltLogLevelType loglevel); * int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, uint32_t messageid); * int dlt_user_log_write_finish(DltContextData *log); * int dlt_user_log_write_bool(DltContextData *log, uint8_t data); * int dlt_user_log_write_bool_attr(DltContextData *log, uint8_t data, const char *name); * int dlt_user_log_write_float32(DltContextData *log, float32_t data); * int dlt_user_log_write_float32_attr(DltContextData *log, float32_t data, const char *name, const char *unit); * int dlt_user_log_write_float64(DltContextData *log, double data); * int dlt_user_log_write_float64_attr(DltContextData *log, double data, const char *name, const char *unit); * int dlt_user_log_write_uint(DltContextData *log, unsigned int data); * int dlt_user_log_write_uint_attr(DltContextData *log, unsigned int data, const char *name, const char *unit); * int dlt_user_log_write_uint8(DltContextData *log, uint8_t data); * int dlt_user_log_write_uint8_attr(DltContextData *log, uint8_t data, const char *name, const char *unit); * int dlt_user_log_write_uint16(DltContextData *log, uint16_t data); * int dlt_user_log_write_uint16_attr(DltContextData *log, uint16_t data, const char *name, const char *unit); * int dlt_user_log_write_uint32(DltContextData *log, uint32_t data); * int dlt_user_log_write_uint32_attr(DltContextData *log, uint32_t data, const char *name, const char *unit); * int dlt_user_log_write_uint64(DltContextData *log, uint64_t data); * int dlt_user_log_write_uint64_attr(DltContextData *log, uint64_t data, const char *name, const char *unit); * int dlt_user_log_write_uint8_formatted(DltContextData *log, uint8_t data, DltFormatType type); * int dlt_user_log_write_uint16_formatted(DltContextData *log, uint16_t data, DltFormatType type); * int dlt_user_log_write_uint32_formatted(DltContextData *log, uint32_t data, DltFormatType type); * int dlt_user_log_write_uint64_formatted(DltContextData *log, uint64_t data, DltFormatType type); * int dlt_user_log_write_int(DltContextData *log, int data); * int dlt_user_log_write_int_attr(DltContextData *log, int data, const char *name, const char *unit); * int dlt_user_log_write_int8(DltContextData *log, int8_t data); * int dlt_user_log_write_int8_attr(DltContextData *log, int8_t data, const char *name, const char *unit); * int dlt_user_log_write_int16(DltContextData *log, int16_t data); * int dlt_user_log_write_int16_attr(DltContextData *log, int16_t data, const char *name, const char *unit); * int dlt_user_log_write_int32(DltContextData *log, int32_t data); * int dlt_user_log_write_int32_attr(DltContextData *log, int32_t data, const char *name, const char *unit); * int dlt_user_log_write_int64(DltContextData *log, int64_t data); * int dlt_user_log_write_int64_attr(DltContextData *log, int64_t data, const char *name, const char *unit); * int dlt_user_log_write_string( DltContextData *log, const char *text); * int dlt_user_log_write_string_attr(DltContextData *log, const char *text, const char *name); * int dlt_user_log_write_sized_string(DltContextData *log, const char *text, uint16_t length); * int dlt_user_log_write_sized_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); * int dlt_user_log_write_constant_string( DltContextData *log, const char *text); * int dlt_user_log_write_constant_string_attr(DltContextData *log, const char *text, const char *name); * int dlt_user_log_write_sized_constant_string(DltContextData *log, const char *text, uint16_t length); * int dlt_user_log_write_sized_constant_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); * int dlt_user_log_write_utf8_string(DltContextData *log, const char *text); * int dlt_user_log_write_utf8_string_attr(DltContextData *log, const char *text, const char *name); * int dlt_user_log_write_sized_utf8_string(DltContextData *log, const char *text, uint16_t length); * int dlt_user_log_write_sized_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name); * int dlt_user_log_write_constant_utf8_string(DltContextData *log, const char *text); * int dlt_user_log_write_constant_utf8_string_attr(DltContextData *log, const char *text, const char *name); * int dlt_user_log_write_sized_constant_utf8_string(DltContextData *log, const char *text); * int dlt_user_log_write_sized_constant_utf8_string_attr(DltContextData *log, const char *text, const char *name); * int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length); * int dlt_user_log_write_raw_attr(DltContextData *log,void *data,uint16_t length, const char *name); * int dlt_user_log_write_raw_formatted(DltContextData *log,void *data,uint16_t length,DltFormatType type); * int dlt_user_log_write_raw_formatted_attr(DltContextData *log,void *data,uint16_t length,DltFormatType type, const char *name); */ /* * int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text); * int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data); * int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data); * int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data); * int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data); * int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length); * int dlt_log_marker(); */ /* * int dlt_register_app(const char *apid, const char * description); * int dlt_unregister_app(void); * int dlt_register_context(DltContext *handle, const char *contextid, const char * description); * int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus); * int dlt_unregister_context(DltContext *handle); * int dlt_register_injection_callback(DltContext *handle, uint32_t service_id, int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length)); * int dlt_register_log_level_changed_callback(DltContext *handle, void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE],uint8_t log_level, uint8_t trace_status)); */ /* * int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload); * int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate); * int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload); */ /* * int dlt_set_log_mode(DltUserLogMode mode); * int dlt_get_log_state(); */ /* * int dlt_verbose_mode(void); * int dlt_nonverbose_mode(void); */ static const char *STR_TRUNCATED_MESSAGE = "... <>"; /*/////////////////////////////////////// */ /* start initial dlt */ TEST(t_dlt_init, onetime) { /** * Unset DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to make sure the dlt user buffer initialized with default value */ unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_start */ TEST(t_dlt_user_log_write_start, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start normal")); /* the defined enum values for log level */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_FATAL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_ERROR)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_WARN)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_INFO)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); /* To test the default behaviour and the default log level set to DLT_LOG_INFO */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_OFF)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEBUG)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_VERBOSE)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_start, abnormal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start abnormal")); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_start(&context, &contextData, (DltLogLevelType) - 100)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_start(&context, &contextData, (DltLogLevelType) - 10)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_start(&context, &contextData, (DltLogLevelType)10)); EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_start(&context, &contextData, (DltLogLevelType)100)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_start, startstartfinish) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start startstartfinish")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* shouldn't it return -1, because it is already started? */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_start, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start nullpointer")); /* NULL's */ EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_start(NULL, &contextData, DLT_LOG_DEFAULT)); /*EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(&contextData)); */ EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_start(NULL, NULL, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_start(&context, NULL, DLT_LOG_DEFAULT)); /*EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(&contextData)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_start_id */ TEST(t_dlt_user_log_write_start_id, normal) { DltContext context; DltContextData contextData; uint32_t messageid; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start_id normal")); /* the defined enum values for log level */ messageid = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_FATAL, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_ERROR, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_WARN, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_INFO, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); /* To test the default behaviour and the default log level set to DLT_LOG_INFO */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_OFF, messageid)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEBUG, messageid)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_VERBOSE, messageid)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); messageid = UINT32_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_FATAL, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_ERROR, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_WARN, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_INFO, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); /* To test the default behaviour and the default log level set to DLT_LOG_INFO */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_OFF, messageid)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEBUG, messageid)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_VERBOSE, messageid)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_start_id, abnormal) { DltContext context; /* TODO: DltContextData contextData; */ /* TODO: uint32_t messageid; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start_id abnormal")); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* TODO: messageid = 0; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_start_id(&context, &contextData, (DltLogLevelType)-100, messageid)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_start_id(&context, &contextData, (DltLogLevelType)-10, messageid)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_start_id(&context, &contextData, (DltLogLevelType)10, messageid)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_start_id(&context, &contextData, (DltLogLevelType)100, messageid)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_start_id, startstartfinish) { DltContext context; DltContextData contextData; uint32_t messageid; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start_id startstartfinish")); messageid = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, messageid)); /* shouldn't it return -1, because it is already started? */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, messageid)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_start_id, nullpointer) { DltContext context; uint32_t messageid; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start_id nullpointer")); /* NULL's */ messageid = 0; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_start_id(NULL, &contextData, DLT_LOG_DEFAULT, messageid)); /*EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(&contextData)); */ EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_start_id(NULL, NULL, DLT_LOG_DEFAULT, messageid)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_start_id(&context, NULL, DLT_LOG_DEFAULT, messageid)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_finish */ TEST(t_dlt_user_log_write_finish, finish) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_start finish")); /* finish without start */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(NULL)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(&contextData)); */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_finish finish")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(&contextData)); */ /* finish with start and initialized context */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); /* 2nd finish */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_finish(&contextData)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_finish */ TEST(t_dlt_user_log_write_finish, finish_with_timestamp) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_finish finish")); /* finish with start and initialized context */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); contextData.use_timestamp = DLT_USER_TIMESTAMP; contextData.user_timestamp = UINT32_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_bool */ TEST(t_dlt_user_log_write_bool, normal) { DltContext context; DltContextData contextData; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_bool normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = true; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_bool(&contextData, data)); data = false; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_bool(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_bool, abnormal) { DltContext context; DltContextData contextData; /* TODO: uint8_t data; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_bool abnormal")); /* abnormal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* TODO: data = 2; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_bool(&contextData, data)); */ /* TODO: data = 100; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_bool(&contextData, data)); */ /* TODO: data = UINT8_MAX; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_bool(&contextData, data)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_bool, nullpointer) { DltContext context; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_bool nullpointer")); /* NULL */ data = true; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_bool(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_bool_attr */ TEST(t_dlt_user_log_write_bool_attr, normal) { DltContext context; DltContextData contextData; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_bool_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = true; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_bool_attr(&contextData, data, "state")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_bool_attr(&contextData, data, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_bool_attr(&contextData, data, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_float32 */ TEST(t_dlt_user_log_write_float32, normal) { DltContext context; DltContextData contextData; float32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_float32 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 3.141592653589793238; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32(&contextData, data)); data = -3.141592653589793238; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32(&contextData, data)); data = 0.; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32(&contextData, data)); data = -0.; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32(&contextData, data)); data = FLT_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32(&contextData, data)); data = FLT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_float32, nullpointer) { DltContext context; float32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_float32 nullpointer")); /* NULL */ data = 1.; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_float32(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_float32_attr */ TEST(t_dlt_user_log_write_float32_attr, normal) { DltContext context; DltContextData contextData; float32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_float32_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 3.141592653589793238f; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float32_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_float64 */ TEST(t_dlt_user_log_write_float64, normal) { DltContext context; DltContextData contextData; double data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_float64 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 3.14159265358979323846; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64(&contextData, data)); data = -3.14159265358979323846; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64(&contextData, data)); data = 0.; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64(&contextData, data)); data = -0.; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64(&contextData, data)); data = DBL_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64(&contextData, data)); data = DBL_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_float64, nullpointer) { DltContext context; double data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_float64 nullpointer")); /* NULL */ data = 1.; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_float64(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_float64_attr */ TEST(t_dlt_user_log_write_float64_attr, normal) { DltContext context; DltContextData contextData; double data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_float64_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 3.14159265358979323846; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_float64_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint */ TEST(t_dlt_user_log_write_uint, normal) { DltContext context; DltContextData contextData; unsigned int data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint(&contextData, data)); data = UINT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint, abnormal) { DltContext context; DltContextData contextData; /* TODO: unsigned int data; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint abnormal")); /* abnormal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* TODO: data = -1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint(&contextData, data)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint, nullpointer) { DltContext context; unsigned int data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint_attr */ TEST(t_dlt_user_log_write_uint_attr, normal) { DltContext context; DltContextData contextData; unsigned int data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 42; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint8 */ TEST(t_dlt_user_log_write_uint8, normal) { DltContext context; DltContextData contextData; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint8 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8(&contextData, data)); data = UINT8_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint8, nullpointer) { DltContext context; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint8 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint8_attr */ TEST(t_dlt_user_log_write_uint8_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint8_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); uint8_t data = 0xaa; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint16 */ TEST(t_dlt_user_log_write_uint16, normal) { DltContext context; DltContextData contextData; uint16_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint16 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16(&contextData, data)); data = UINT16_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint16, nullpointer) { DltContext context; uint16_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint16 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint16_attr */ TEST(t_dlt_user_log_write_uint16_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint16_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); uint16_t data = 0xaa55; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint32 */ TEST(t_dlt_user_log_write_uint32, normal) { DltContext context; DltContextData contextData; uint32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint32 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32(&contextData, data)); data = UINT32_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint32, nullpointer) { DltContext context; uint32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint32 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint32_attr */ TEST(t_dlt_user_log_write_uint32_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint32_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); uint32_t data = 0xaabbccdd; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint64 */ TEST(t_dlt_user_log_write_uint64, normal) { DltContext context; DltContextData contextData; uint64_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint64 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64(&contextData, data)); data = UINT64_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint64, nullpointer) { DltContext context; uint64_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint64 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint64_attr */ TEST(t_dlt_user_log_write_uint64_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint64_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); uint64_t data = 0x11223344aabbccddULL; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint8_formatted */ TEST(t_dlt_user_log_write_uint8_formatted, normal) { DltContext context; DltContextData contextData; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint8_formatted normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = UINT8_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint8_formatted(&contextData, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint8_formatted, abnormal) { DltContext context; DltContextData contextData; /* TODO: uint8_t data; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint8_formatted abnormal")); /* abnormal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* TODO: data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint8_formatted(&contextData, data, (DltFormatType)-100)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint8_formatted(&contextData, data, (DltFormatType)-10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint8_formatted(&contextData, data, (DltFormatType)10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint8_formatted(&contextData, data, (DltFormatType)100)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint8_formatted, nullpointer) { DltContext context; uint8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint8_formatted nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_HEX8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_HEX16)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_HEX32)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_HEX64)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_BIN8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint8_formatted(NULL, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint16_formatted */ TEST(t_dlt_user_log_write_uint16_formatted, normal) { DltContext context; DltContextData contextData; uint16_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint16_formatted normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = UINT16_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint16_formatted(&contextData, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint16_formatted, abnormal) { DltContext context; DltContextData contextData; /* TODO: uint16_t data; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint16_formatted abnormal")); /* abnormal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* TODO: data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint16_formatted(&contextData, data, (DltFormatType)-100)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint16_formatted(&contextData, data, (DltFormatType)-10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint16_formatted(&contextData, data, (DltFormatType)10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint16_formatted(&contextData, data, (DltFormatType)100)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint16_formatted, nullpointer) { DltContext context; uint16_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint16_formatted nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_HEX8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_HEX16)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_HEX32)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_HEX64)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_BIN8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint16_formatted(NULL, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint32_formatted */ TEST(t_dlt_user_log_write_uint32_formatted, normal) { DltContext context; DltContextData contextData; uint32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint32_formatted normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = UINT32_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_formatted(&contextData, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint32_formatted, abnormal) { DltContext context; DltContextData contextData; /* TODO: uint32_t data; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint32_formatted abnormal")); /* abnormal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* TODO: data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint32_formatted(&contextData, data, (DltFormatType)-100)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint32_formatted(&contextData, data, (DltFormatType)-10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint32_formatted(&contextData, data, (DltFormatType)10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint32_formatted(&contextData, data, (DltFormatType)100)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint32_formatted, nullpointer) { DltContext context; uint32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint32_formatted nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_HEX8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_HEX16)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_HEX32)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_HEX64)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_BIN8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint32_formatted(NULL, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_uint64_formatted */ TEST(t_dlt_user_log_write_uint64_formatted, normal) { DltContext context; DltContextData contextData; uint64_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint64_formatted normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_BIN16)); data = UINT64_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint64_formatted(&contextData, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint64_formatted, abnormal) { DltContext context; DltContextData contextData; /* TODO: uint64_t data; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint64_formatted abnormal")); /* abnormal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* TODO: data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint64_formatted(&contextData, data, (DltFormatType)-100)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint64_formatted(&contextData, data, (DltFormatType)-10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint64_formatted(&contextData, data, (DltFormatType)10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_uint64_formatted(&contextData, data, (DltFormatType)100)); */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_uint64_formatted, nullpointer) { DltContext context; uint64_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_uint64_formatted nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_HEX8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_HEX16)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_HEX32)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_HEX64)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_BIN8)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_uint64_formatted(NULL, data, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int */ TEST(t_dlt_user_log_write_int, normal) { DltContext context; DltContextData contextData; int data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = -1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int(&contextData, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int(&contextData, data)); data = INT_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int(&contextData, data)); data = INT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_int, nullpointer) { DltContext context; int data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_int(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int_attr */ TEST(t_dlt_user_log_write_int_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); int data = -42; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int8 */ TEST(t_dlt_user_log_write_int8, normal) { DltContext context; DltContextData contextData; int8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int8 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = -1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8(&contextData, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8(&contextData, data)); data = INT8_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8(&contextData, data)); data = INT8_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_int8, nullpointer) { DltContext context; int8_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int8 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_int8(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int8_attr */ TEST(t_dlt_user_log_write_int8_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int8_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); int8_t data = 0xaa; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int8_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int16 */ TEST(t_dlt_user_log_write_int16, normal) { DltContext context; DltContextData contextData; int16_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int16 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = -1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16(&contextData, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16(&contextData, data)); data = INT16_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16(&contextData, data)); data = INT16_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_int16, nullpointer) { DltContext context; int16_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int16 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_int16(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int16_attr */ TEST(t_dlt_user_log_write_int16_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int16_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); int16_t data = 0xaa55; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int16_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int32 */ TEST(t_dlt_user_log_write_int32, normal) { DltContext context; DltContextData contextData; int32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int32 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = -1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32(&contextData, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32(&contextData, data)); data = INT32_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32(&contextData, data)); data = INT32_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_int32, nullpointer) { DltContext context; int32_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int32 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_int32(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int32_attr */ TEST(t_dlt_user_log_write_int32_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int32_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); int32_t data = 0xffeeddcc; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int32_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int64 */ TEST(t_dlt_user_log_write_int64, normal) { DltContext context; DltContextData contextData; int64_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int64 normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); data = -1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64(&contextData, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64(&contextData, data)); data = 1; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64(&contextData, data)); data = INT64_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64(&contextData, data)); data = INT64_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64(&contextData, data)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_int64, nullpointer) { DltContext context; int64_t data; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int64 nullpointer")); /* NULL */ data = 1; EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_int64(NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_int64_attr */ TEST(t_dlt_user_log_write_int64_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_int64_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); int64_t data = 0xffeeddcc44332211LL; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, "name", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, "", "unit")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, "name", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, "", "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, NULL, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, "", NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_int64_attr(&contextData, data, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_string */ TEST(t_dlt_user_log_write_string, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_string(&contextData, text1)); const char *text2 = ""; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_string(&contextData, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /** * Send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated and appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_string, normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; char *message = NULL; char *expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message exceed buffer length 10 bytes */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } /** * In Non-Verbose mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated and appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_string, normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_non_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; char *message = NULL; char *expected_message = NULL; dlt_nonverbose_mode(); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_non_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message exceed buffer length 10 bytes */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Non-Verbose Mode: * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore verbose mode */ dlt_verbose_mode(); } /** * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated and appended STR_TRUNCATED_MESSAGE at * the end of received message. * Note: dlt_init() will be called after testcase is finished to restore environment for other test cases */ TEST(t_dlt_user_log_write_string, normal_message_truncated_because_exceed_buffer_length_and_reduce_msg_buf_len_by_env_variable) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t user_message_after_truncated_size = 0; const char *message = "$$$$###############################################"; char *expected_message = NULL; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size only available 4 bytes for store user message. * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. */ user_message_after_truncated_size = 4; EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_message_truncated_because_exceed_buffer_length_and_reduce_msg_buf_len_by_env_variable")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ expected_message_length = user_message_after_truncated_size + str_truncate_message_length; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '$'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } /** * Set DLT_USER_ENV_LOG_MSG_BUF_LEN to 35 bytes and send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL because the DLT_USER_ENV_LOG_MSG_BUF_LEN * does not have enough space to store truncate message STR_TRUNCATED_MESSAGE * Note: dlt_init() will be called after testcase is finished to restore environment for other test cases */ TEST(t_dlt_user_log_write_string, normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_does_not_enough_space_for_truncated_message) { DltContext context; DltContextData contextData; uint16_t package_description_size = 0; const char *message = "################################################################################"; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size not enough minimum space to store data even the truncate notice message. * Note: The minimum buffer to store the truncate notice message is 42 bytes. */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "35", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_does_not_enough_space_for_truncated_message")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); ASSERT_STREQ("", (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } /** * Set DLT_USER_ENV_LOG_MSG_BUF_LEN to 42 bytes and send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * receive message will be STR_TRUNCATED_MESSAGE * Note: dlt_init() will be called after testcase is finished to restore environment for other test cases */ TEST(t_dlt_user_log_write_string, normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_fix_truncate_message) { DltContext context; DltContextData contextData; uint16_t package_description_size = 0; const char *message = "################################################################################"; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size just fixed to truncate message STR_TRUNCATED_MESSAGE * Note: 42 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 1 byte NULL terminator. */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "42", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_fix_truncate_message")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); ASSERT_STREQ(STR_TRUNCATED_MESSAGE, (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } TEST(t_dlt_user_log_write_string, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string nullpointer")); /* NULL */ const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_string(NULL, text1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_string(NULL, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_string(&contextData, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_string */ TEST(t_dlt_user_log_write_sized_string, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_string normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); const char text1[] = "TheQuickBrownFox"; const char *arg1_start = strchr(text1, 'Q'); const size_t arg1_len = 5; /* from the above string, send only the substring "Quick" */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_string(&contextData, arg1_start, arg1_len)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_constant_string */ TEST(t_dlt_user_log_write_constant_string, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string(&contextData, text1)); const char *text2 = ""; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string(&contextData, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /** * Send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_constant_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated and appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_constant_string, normal_too_long_message_is_truncated_and_appended_notice_message_in_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; char *message = NULL; char *expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string normal_too_long_message_is_truncated_and_appended_notice_message_in_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the message exceed DLT_USER_ENV_LOG_MSG_BUF_LEN 10 bytes */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_constant_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } /** * In Non-Verbose Mode * Expectation: dlt_user_log_write_constant_string() will not package and send message. Return DLT_RETURN_OK */ TEST(t_dlt_user_log_write_constant_string, normal_do_nothing_in_non_verbose_mode) { DltContext context; DltContextData contextData; const char *message = "message"; dlt_nonverbose_mode(); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string normal_do_nothing_in_non_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_constant_string(&contextData, message)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore verbose mode */ dlt_verbose_mode(); } TEST(t_dlt_user_log_write_constant_string, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string nullpointer")); /* NULL */ const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_constant_string(NULL, text1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_constant_string(NULL, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_constant_string(&contextData, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_constant_string */ TEST(t_dlt_user_log_write_sized_constant_string, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_string normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); const char text1[] = "TheQuickBrownFox"; const char *arg1_start = strchr(text1, 'Q'); const size_t arg1_len = 5; /* from the above string, send only the substring "Quick" */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_string(&contextData, arg1_start, arg1_len)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_utf8_string */ TEST(t_dlt_user_log_write_utf8_string, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_utf8_string(&contextData, text1)); const char *text2 = ""; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_utf8_string(&contextData, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /** * Send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at one byte utf-8 and appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_1byte_in_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; char *message = NULL; char *expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_1byte_in_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message exceed buffer length 10 bytes which have '$' character (utf-8 1 byte) right before truncate position */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /* Fill '$' before truncate position */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - 1); message[index] = '$'; /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length; for (index = 0; index < (user_message_after_truncated_size - 1); index++) { expected_message[index] = '#'; } expected_message[user_message_after_truncated_size - 1] = '$'; strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at one byte utf-8 and appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_1byte_in_non_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; char *message = NULL; char *expected_message = NULL; dlt_nonverbose_mode(); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_1byte_in_non_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message exceed buffer length 10 bytes which have '$' character (utf-8 1 byte) right before truncate position */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /** * In Non-Verbose Mode: * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /* Fill '$' before truncate position */ index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - 1); message[index] = '$'; /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length; for (index = 0; index < (user_message_after_truncated_size - 1); index++) { expected_message[index] = '#'; } expected_message[user_message_after_truncated_size - 1] = '$'; strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore verbose mode */ dlt_verbose_mode(); } /** * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the whole utf-8 1 bytes and appended * STR_TRUNCATED_MESSAGE at the end of received message. * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_1bytes_and_reduce_msg_buf_len_by_env_variable) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t expected_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t user_message_after_truncated_size = 0; const char *message = "$$$$###############################################"; char *expected_message = NULL; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size only available 4 bytes for store user message. * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. */ user_message_after_truncated_size = 4; EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_1bytes_and_reduce_msg_buf_len_by_env_variable")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ expected_message_length = user_message_after_truncated_size + str_truncate_message_length; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '$'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 2 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_2bytes_in_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *utf8_2byte_character = "¢"; char *message = NULL; char *expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_2bytes_in_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message contain the '¢' (2 bytes utf-8 character) and last byte of this character is exceed buffer length */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /** * Fill the "¢" character at the position which the last byte of this character is exceed the buffer length and * expectation is it will be truncated 1 more bytes in the character sequence */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; remaining_byte_truncated_utf8_character = 1; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); strncpy(message + index, utf8_2byte_character, strlen(utf8_2byte_character)); /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 2 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_2bytes_in_non_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *utf8_2byte_character = "¢"; char *message = NULL; char *expected_message = NULL; dlt_nonverbose_mode(); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_2bytes_in_non_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message contain the '¢' (2 bytes utf-8 character) and last byte of this character is exceed buffer length */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Non-Verbose Mode: * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /** * Fill the "¢" character at the position which the last byte of this character is exceed the buffer length and * expectation is it will be truncated 1 more bytes in the character sequence */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; remaining_byte_truncated_utf8_character = 1; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); strncpy(message + index, utf8_2byte_character, strlen(utf8_2byte_character)); /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(DLT_USER_BUF_MAX_SIZE)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore verbose mode */ dlt_verbose_mode(); } /** * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 2 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_2bytes_and_reduce_msg_buf_len_by_env_variable) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *message = "$$$¢###############################################"; char *expected_message = NULL; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size only available 4 bytes for store user message. * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. */ user_message_after_truncated_size = 4; EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_2bytes_and_reduce_msg_buf_len_by_env_variable")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ remaining_byte_truncated_utf8_character = 1; expected_message_length = user_message_after_truncated_size - remaining_byte_truncated_utf8_character + str_truncate_message_length; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size -= remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '$'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 3 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_3bytes_in_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *utf8_3byte_character = "€"; char *message = NULL; char *expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_3bytes_in_verbose_mode")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message contain the '€' (3 bytes utf-8 character) and last byte of this character is exceed buffer length */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /** * Fill the "€" character at the position which the last byte of this character is exceed the buffer length and * expectation is it will be truncated 2 more bytes in the character sequence */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; remaining_byte_truncated_utf8_character = 2; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); strncpy(message + index, utf8_3byte_character, strlen(utf8_3byte_character)); /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 3 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_3bytes_in_non_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *utf8_3byte_character = "€"; char *message = NULL; char *expected_message = NULL; dlt_nonverbose_mode(); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_3bytes_in_non_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message contain the '€' (3 bytes utf-8 character) and last byte of this character is exceed buffer length */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /** * Fill the "€" character at the position which the last byte of this character is exceed the buffer length and * expectation is it will be truncated 2 more bytes in the character sequence */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; remaining_byte_truncated_utf8_character = 2; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); strncpy(message + index, utf8_3byte_character, strlen(utf8_3byte_character)); /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore verbose mode */ dlt_verbose_mode(); } /** * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 3 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_3bytes_and_reduce_msg_buf_len_by_env_variable) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *message = "$$€###############################################"; char *expected_message = NULL; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size only available 4 bytes for store user message. * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. */ user_message_after_truncated_size = 4; EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_3bytes_and_reduce_msg_buf_len_by_env_variable")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ remaining_byte_truncated_utf8_character = 2; expected_message_length = user_message_after_truncated_size - remaining_byte_truncated_utf8_character + str_truncate_message_length; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size -= remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '$'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 4 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_4bytes_in_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *utf8_4byte_character = "𐍈"; char *message = NULL; char *expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_4bytes_in_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message contain the '𐍈' (4 bytes utf-8 character) and last byte of this character is exceed buffer length */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /** * Fill the "𐍈" character at the position which the last byte of this character is exceed the buffer length and * expectation is it will be truncated 3 more bytes in the character sequence */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; remaining_byte_truncated_utf8_character = 3; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); strncpy(message + index, utf8_4byte_character, strlen(utf8_4byte_character)); /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } /** * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 4 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_4bytes_in_non_verbose_mode) { DltContext context; DltContextData contextData; uint16_t index = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t send_message_length = 0; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *utf8_4byte_character = "𐍈"; char *message = NULL; char *expected_message = NULL; dlt_nonverbose_mode(); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_4bytes_in_non_verbose_mode")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); /* Create the message contain the '𐍈' (4 bytes utf-8 character) and last byte of this character is exceed buffer length */ send_message_length = DLT_USER_BUF_MAX_SIZE + 10; message = (char *)(malloc(send_message_length)); ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; for (index = 0; index < send_message_length; index++) { message[index] = '#'; } message[send_message_length - 1] = '\0'; /** * In Non-Verbose Mode: * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); /** * Fill the "𐍈" character at the position which the last byte of this character is exceed the buffer length and * expectation is it will be truncated 3 more bytes in the character sequence */ str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; remaining_byte_truncated_utf8_character = 3; index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); strncpy(message + index, utf8_4byte_character, strlen(utf8_4byte_character)); /* Create the expected message */ expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; for (index = 0; index < user_message_after_truncated_size; index++) { expected_message[index] = '#'; } strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); free(message); message = NULL; free(expected_message); expected_message = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore verbose mode */ dlt_verbose_mode(); } /** * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and * message will be truncated at the middle of utf-8 4 bytes, the rest of this utf-8 character will * be removed completely, after that appended STR_TRUNCATED_MESSAGE at * the end of received message. * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases */ TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_4bytes_and_reduce_msg_buf_len_by_env_variable) { DltContext context; DltContextData contextData; uint16_t str_truncate_message_length = 0; uint16_t expected_message_length = 0; uint16_t package_description_size = 0; uint16_t user_message_after_truncated_size = 0; uint16_t remaining_byte_truncated_utf8_character = 0; const char *message = "$𐍈###############################################"; char *expected_message = NULL; /** * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable * to simulate use case the dlt user buffer size only available 4 bytes for store user message. * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. */ user_message_after_truncated_size = 4; EXPECT_EQ(DLT_RETURN_OK, dlt_free()); setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_4bytes_and_reduce_msg_buf_len_by_env_variable")); /* Normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); /** * In Verbose Mode: * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) */ package_description_size = sizeof(uint32_t) + sizeof(uint16_t); str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; /* Create the expected message */ remaining_byte_truncated_utf8_character = 3; expected_message_length = user_message_after_truncated_size - remaining_byte_truncated_utf8_character + str_truncate_message_length; expected_message = (char *)(malloc(expected_message_length)); ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; expected_message[0] = '$'; strncpy(expected_message + 1, STR_TRUNCATED_MESSAGE, str_truncate_message_length); ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); /* Restore the dlt with dlt user buffer size as default */ EXPECT_EQ(DLT_RETURN_OK, dlt_free()); unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } TEST(t_dlt_user_log_write_utf8_string, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string nullpointer")); /* NULL */ const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_utf8_string(NULL, text1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_utf8_string(NULL, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_utf8_string(&contextData, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_utf8_string */ TEST(t_dlt_user_log_write_sized_utf8_string, partial_string) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_utf8_string normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); const char text1[] = "TheQuickBrownFox"; const char* arg1_start = strchr(text1, 'Q'); const size_t arg1_len = 5; /* from the above string, send only the substring "Quick" */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_utf8_string(&contextData, arg1_start, arg1_len)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_sized_utf8_string, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_utf8_string nullpointer")); /* NULL */ const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_sized_utf8_string(NULL, text1, 5)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_sized_utf8_string(NULL, NULL, 5)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_sized_utf8_string(&contextData, NULL, 5)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_constant_utf8_string*/ TEST(t_dlt_user_log_write_constant_utf8_string, verbose) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_utf8_string verbose")); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string(&contextData, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_constant_utf8_string, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_utf8_string nullpointer")); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_TRUE, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string(NULL, text1)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string(NULL, NULL)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string(&contextData, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_constant_utf8_string, nonverbose) { dlt_nonverbose_mode(); DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_utf8_string nonverbose")); const char *text2 = "test2"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, 42)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string(&contextData, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); dlt_verbose_mode(); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_constant_utf8_string */ TEST(t_dlt_user_log_write_sized_constant_utf8_string, verbose) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_utf8_string verbose")); const char *text1 = "test1text"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string(&contextData, text1, 5)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_sized_constant_utf8_string, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_utf8_string nullpointer")); const char *text1 = "test1text"; EXPECT_LE(DLT_RETURN_TRUE, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string(NULL, text1, 5)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string(NULL, NULL, 5)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string(&contextData, NULL, 5)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_sized_constant_utf8_string, nonverbose) { dlt_nonverbose_mode(); DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_utf8_string nonverbose")); const char *text2 = "test2text"; size_t text2len = 5; // only use a (non-null-terminated) substring EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, 42)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string(&contextData, text2, text2len)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); dlt_verbose_mode(); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_string_attr */ TEST(t_dlt_user_log_write_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_string_attr(&contextData, data, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_string_attr(&contextData, data, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_string_attr(&contextData, data, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_string_attr */ TEST(t_dlt_user_log_write_sized_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_string_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456789"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_string_attr(&contextData, data, 6, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_string_attr(&contextData, data, 6, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_string_attr(&contextData, data, 6, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_constant_string_attr */ TEST(t_dlt_user_log_write_constant_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string_attr(&contextData, data, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string_attr(&contextData, data, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string_attr(&contextData, data, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_constant_string_attr */ TEST(t_dlt_user_log_write_sized_constant_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_string_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456789"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_string_attr(&contextData, data, 6, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_string_attr(&contextData, data, 6, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_string_attr(&contextData, data, 6, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_utf8_string_attr */ TEST(t_dlt_user_log_write_utf8_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_utf8_string_attr(&contextData, data, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_utf8_string_attr(&contextData, data, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_utf8_string_attr(&contextData, data, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_utf8_string_attr */ TEST(t_dlt_user_log_write_sized_utf8_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_utf8_string_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456789"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_utf8_string_attr(&contextData, data, 6, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_utf8_string_attr(&contextData, data, 6, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_utf8_string_attr(&contextData, data, 6, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_constant_utf8_string_attr */ TEST(t_dlt_user_log_write_constant_utf8_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_utf8_string_attr normal")); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string_attr(&contextData, text1, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_constant_utf8_string_attr, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_utf8_string_attr nullpointer")); const char *text1 = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string_attr(NULL, text1, "name")); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string_attr(NULL, NULL, "name")); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_constant_utf8_string_attr(&contextData, NULL, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_sized_constant_utf8_string_attr */ TEST(t_dlt_user_log_write_sized_constant_utf8_string_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_utf8_string_attr normal")); const char *text1 = "test1text"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string_attr(&contextData, text1, 5, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_sized_constant_utf8_string_attr, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_sized_constant_utf8_string_attr nullpointer")); const char *text1 = "test1text"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string_attr(NULL, text1, 5, "name")); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string_attr(NULL, NULL, 5, "name")); EXPECT_GT(DLT_RETURN_OK, dlt_user_log_write_sized_constant_utf8_string_attr(&contextData, NULL, 5, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_raw */ TEST(t_dlt_user_log_write_raw, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char text1[6] = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw(&contextData, text1, 6)); char text2[1] = ""; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw(&contextData, text2, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_raw, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw nullpointer")); /* NULL */ char text1[6] = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_raw(NULL, text1, 6)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_raw(NULL, NULL, 0)); EXPECT_GE(DLT_RETURN_OK, dlt_user_log_write_raw(&contextData, NULL, 0)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_raw(&contextData, NULL, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_raw_attr */ TEST(t_dlt_user_log_write_raw_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_attr(&contextData, data, 6, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_attr(&contextData, data, 6, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_attr(&contextData, data, 6, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_raw_formatted */ TEST(t_dlt_user_log_write_raw_formatted, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw_formatted normal")); /* normal values */ EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char text1[6] = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text1, 6, DLT_FORMAT_BIN16)); char text2[1] = ""; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_HEX8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_HEX16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_HEX32)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_HEX64)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_BIN8)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, text2, 0, DLT_FORMAT_BIN16)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_raw_formatted, abnormal) { DltContext context; DltContextData contextData; uint16_t length = DLT_USER_BUF_MAX_SIZE + 10; char buffer[length]; memset(buffer, '\000', length); for (int i = 0; i < length; i++) buffer[i] = 'X'; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw_formatted abnormal")); EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_raw_formatted(&contextData, buffer, length, DLT_FORMAT_DEFAULT)); /* undefined values for DltFormatType */ /* shouldn't it return -1? */ /* char text1[6] = "test1"; */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_raw_formatted(&contextData, text1, 6, (DltFormatType)-100)); */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_raw_formatted(&contextData, text1, 6, (DltFormatType)-10)); */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_raw_formatted(&contextData, text1, 6, (DltFormatType)10)); */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_user_log_write_raw_formatted(&contextData, text1, 6, (DltFormatType)100)); */ EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_log_write_raw_formatted, nullpointer) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw_formatted nullpointer")); /* NULL */ char text1[6] = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_raw_formatted(NULL, text1, 6, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_raw_formatted(NULL, NULL, 0, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted(&contextData, NULL, 0, DLT_FORMAT_DEFAULT)); EXPECT_GE(DLT_RETURN_ERROR, dlt_user_log_write_raw_formatted(&contextData, NULL, 1, DLT_FORMAT_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_log_write_raw_formatted_attr */ TEST(t_dlt_user_log_write_raw_formatted_attr, normal) { DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_raw_formatted_attr normal")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); char data[] = "123456"; EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted_attr(&contextData, data, 6, DLT_FORMAT_DEFAULT, "name")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted_attr(&contextData, data, 6, DLT_FORMAT_DEFAULT, "")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_raw_formatted_attr(&contextData, data, 6, DLT_FORMAT_DEFAULT, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* * Test sending Verbose and Non-Verbose messages in the same session. */ /*/////////////////////////////////////// */ /* t_dlt_user_nonverbose*/ TEST(t_dlt_user_nonverbose, nonverbosemode) { dlt_nonverbose_mode(); dlt_use_extended_header_for_non_verbose(false); DltContext context; DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_message_modes")); // Send a Verbose message EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string_attr(&contextData, "hello", "msg")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, 0x01020304, "val1", "unit1")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, 0x04030201, "val2", "unit2")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); // Send a Non-Verbose message EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start_id(&context, &contextData, DLT_LOG_DEFAULT, 42)); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_constant_string_attr(&contextData, "hello", "msg")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, 0x01020304, "val1", "unit1")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_uint32_attr(&contextData, 0x04030201, "val2", "unit2")); EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); dlt_use_extended_header_for_non_verbose(true); dlt_verbose_mode(); } /*/////////////////////////////////////// */ /* * int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text); * int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data); * int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data); * int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data); * int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data); * int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length); * int dlt_log_marker(); */ /*/////////////////////////////////////// */ /* t_dlt_log_string */ TEST(t_dlt_log_string, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string normal")); /* normal values */ const char text1[6] = "test1"; EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_DEFAULT, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_OFF, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_FATAL, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_ERROR, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_WARN, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_INFO, text1)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_VERBOSE, text1)); const char text2[1] = ""; EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_DEFAULT, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_OFF, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_FATAL, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_ERROR, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_WARN, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_INFO, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string(&context, DLT_LOG_VERBOSE, text2)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_string, abnormal) { DltContext context; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string abnormal")); uint16_t length = DLT_USER_BUF_MAX_SIZE + 10; char buffer[length]; memset(buffer, '\000', length); for (int i = 0; i < length - 1; i++) buffer[i] = 'X'; EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_log_string(&context, DLT_LOG_INFO, buffer)); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* TODO: const char text1[6] = "test1"; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string(&context, (DltLogLevelType)-100, text1)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string(&context, (DltLogLevelType)-10, text1)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string(&context, (DltLogLevelType)10, text1)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string(&context, (DltLogLevelType)100, text1)); */ EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_string, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string nullpointer")); /* NULL */ char text1[6] = "test1"; EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string(NULL, DLT_LOG_DEFAULT, text1)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string(NULL, DLT_LOG_DEFAULT, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string(&context, DLT_LOG_DEFAULT, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_log_string_int */ TEST(t_dlt_log_string_int, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string_int normal")); /* normal values */ const char text1[6] = "test1"; int data = INT_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_DEFAULT, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_OFF, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_FATAL, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_ERROR, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_WARN, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_INFO, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_VERBOSE, text1, data)); const char text2[1] = ""; data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_DEFAULT, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_OFF, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_FATAL, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_ERROR, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_WARN, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_INFO, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_VERBOSE, text2, data)); data = INT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_DEFAULT, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_OFF, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_FATAL, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_ERROR, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_WARN, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_INFO, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_int(&context, DLT_LOG_VERBOSE, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_string_int, abnormal) { DltContext context; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string_int abnormal")); uint16_t length = DLT_USER_BUF_MAX_SIZE + 10; char buffer[length]; memset(buffer, '\000', length); for (int i = 0; i < length - 1; i++) buffer[i] = 'X'; EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_log_string_int(&context, DLT_LOG_INFO, buffer, 1)); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* TODO: const char text1[6] = "test1"; */ /* TODO: int data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_int(&context, (DltLogLevelType)-100, text1, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_int(&context, (DltLogLevelType)-10, text1, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_int(&context, (DltLogLevelType)10, text1, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_int(&context, (DltLogLevelType)100, text1, data)); */ EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_string_int, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string_int nullpointer")); /* NULL */ char text1[6] = "test1"; int data = 0; EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string_int(NULL, DLT_LOG_DEFAULT, text1, data)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string_int(NULL, DLT_LOG_DEFAULT, NULL, data)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string_int(&context, DLT_LOG_DEFAULT, NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_log_string_uint */ TEST(t_dlt_log_string_uint, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string_uint normal")); /* normal values */ const char text1[6] = "test1"; unsigned int data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_DEFAULT, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_OFF, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_FATAL, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_ERROR, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_WARN, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_INFO, text1, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_VERBOSE, text1, data)); const char text2[1] = ""; data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_DEFAULT, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_OFF, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_FATAL, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_ERROR, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_WARN, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_INFO, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_VERBOSE, text2, data)); data = UINT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_DEFAULT, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_OFF, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_FATAL, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_ERROR, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_WARN, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_INFO, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_string_uint(&context, DLT_LOG_VERBOSE, text2, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_string_uint, abnormal) { DltContext context; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string_uint abnormal")); uint16_t length = DLT_USER_BUF_MAX_SIZE + 10; char buffer[length]; memset(buffer, '\000', DLT_USER_BUF_MAX_SIZE + 10); for (int i = 0; i < length - 1; i++) buffer[i] = 'X'; EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_log_string_uint(&context, DLT_LOG_INFO, buffer, 1)); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* TODO: const char text1[6] = "test1"; */ /* TODO: unsigned int data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_uint(&context, (DltLogLevelType)-100, text1, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_uint(&context, (DltLogLevelType)-10, text1, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_uint(&context, (DltLogLevelType)10, text1, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_string_uint(&context, (DltLogLevelType)100, text1, data)); */ EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_string_uint, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_string_uint nullpointer")); /* NULL */ char text1[6] = "test1"; unsigned int data = 0; EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string_uint(NULL, DLT_LOG_DEFAULT, text1, data)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string_uint(NULL, DLT_LOG_DEFAULT, NULL, data)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_string_uint(&context, DLT_LOG_DEFAULT, NULL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_log_int */ TEST(t_dlt_log_int, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_int normal")); /* normal values */ int data = INT_MIN; EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_OFF, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_FATAL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_ERROR, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_WARN, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_INFO, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_VERBOSE, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_OFF, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_FATAL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_ERROR, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_WARN, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_INFO, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_VERBOSE, data)); data = INT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_OFF, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_FATAL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_ERROR, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_WARN, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_INFO, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_int(&context, DLT_LOG_VERBOSE, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_int, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_int abnormal")); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* TODO: int data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_int(&context, (DltLogLevelType)-100, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_int(&context, (DltLogLevelType)-10, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_int(&context, (DltLogLevelType)10, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_int(&context, (DltLogLevelType)100, data)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_int, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_int nullpointer")); /* NULL */ int data = 0; EXPECT_GE(DLT_RETURN_ERROR, dlt_log_int(NULL, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_log_uint */ TEST(t_dlt_log_uint, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_uint normal")); /* normal values */ unsigned int data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_OFF, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_FATAL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_ERROR, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_WARN, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_INFO, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_VERBOSE, data)); data = 0; EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_OFF, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_FATAL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_ERROR, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_WARN, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_INFO, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_VERBOSE, data)); data = UINT_MAX; EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_OFF, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_FATAL, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_ERROR, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_WARN, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_INFO, data)); EXPECT_LE(DLT_RETURN_OK, dlt_log_uint(&context, DLT_LOG_VERBOSE, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_uint, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_uint abnormal")); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* TODO: unsigned int data = 1; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_uint(&context, (DltLogLevelType)-100, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_uint(&context, (DltLogLevelType)-10, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_uint(&context, (DltLogLevelType)10, data)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_uint(&context, (DltLogLevelType)100, data)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_uint, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_uint nullpointer")); /* NULL */ unsigned int data = 0; EXPECT_GE(DLT_RETURN_ERROR, dlt_log_uint(NULL, DLT_LOG_DEFAULT, data)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_log_raw */ TEST(t_dlt_log_raw, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_raw normal")); /* normal values */ char data[5] = "test"; uint16_t length = 4; EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_DEFAULT, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_OFF, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_FATAL, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_ERROR, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_WARN, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_INFO, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_log_raw(&context, DLT_LOG_VERBOSE, data, length)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_raw, abnormal) { DltContext context; EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_raw abnormal")); uint16_t length = DLT_USER_BUF_MAX_SIZE + 10; char buffer[length]; memset(buffer, '\000', length); for (int i = 0; i < length; i++) buffer[i] = 'X'; EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_log_raw(&context, DLT_LOG_INFO, buffer, length)); /* undefined values for DltLogLevelType */ /* shouldn't it return -1? */ /* char data[5] = "test"; */ /* TODO: uint16_t length = 4; */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, (DltLogLevelType)-100, data, length)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, (DltLogLevelType)-10, data, length)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, (DltLogLevelType)10, data, length)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, (DltLogLevelType)100, data, length)); */ /* zero length */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, DLT_LOG_DEFAULT, data, 0)); */ /* negative length */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, DLT_LOG_DEFAULT, data, -1)); */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_log_raw(&context, DLT_LOG_DEFAULT, data, -100)); */ EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_log_raw, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_raw nullpointer")); /* NULL */ char data[5] = "test"; uint16_t length = 4; EXPECT_GE(DLT_RETURN_ERROR, dlt_log_raw(NULL, DLT_LOG_DEFAULT, data, length)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_raw(NULL, DLT_LOG_DEFAULT, NULL, length)); EXPECT_GE(DLT_RETURN_ERROR, dlt_log_raw(&context, DLT_LOG_DEFAULT, NULL, length)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_log_marker */ TEST(t_dlt_log_marker, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_log_marker normal")); /* normal */ EXPECT_LE(DLT_RETURN_OK, dlt_log_marker()); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_register_app */ TEST(t_dlt_register_app, normal) { EXPECT_LE(DLT_RETURN_OK, dlt_register_app("T", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TU", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUS", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_register_app, abnormal) { EXPECT_GE(DLT_RETURN_ERROR, dlt_register_app("", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_unregister_app()); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR1", "dlt_user.c tests")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_app()); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR123445667", "dlt_user.c tests")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_app()); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_app()); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR", NULL)); */ } TEST(t_dlt_register_app, nullpointer) { EXPECT_GE(DLT_RETURN_ERROR, dlt_register_app(NULL, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_app(NULL, "dlt_user.c tests")); } /*/////////////////////////////////////// */ /* t_dlt_unregister_app */ TEST(t_dlt_unregister_app, normal) { EXPECT_LE(DLT_RETURN_OK, dlt_register_app("T", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TU", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUS", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_unregister_app, abnormal) { EXPECT_GE(DLT_RETURN_ERROR, dlt_unregister_app()); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_app("", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_unregister_app()); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR1", "dlt_user.c tests")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_app()); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR123445667", "dlt_user.c tests")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_app()); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_app("TUSR", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_app()); */ } /*/////////////////////////////////////// */ /* t_dlt_register_context */ TEST(t_dlt_register_context, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_context normal")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_register_context, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, "", "d")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "T", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, "", "")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1", "1")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1234567890", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1234567890", "1")); */ EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_context normal")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", NULL)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_register_context, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, NULL, "dlt_user.c t_dlt_register_context normal")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, NULL, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(NULL, "TEST", NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(NULL, NULL, "dlt_user.c t_dlt_register_context normal")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(NULL, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_register_context_ll_ts */ TEST(t_dlt_register_context_ll_ts, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_FATAL, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_ERROR, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_WARN, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_INFO, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_DEBUG, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_VERBOSE, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_FATAL, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_ERROR, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_WARN, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_INFO, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_DEBUG, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_VERBOSE, DLT_TRACE_STATUS_ON)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_register_context_ll_ts, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(&context, "", "d", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "T", "", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(&context, "", "", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST1", "", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST1", "1", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST1234567890", "", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST1234567890", "1", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_ON)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); /* DLT_LOG_DEFAULT and DLT_TRACE_STATUS_DEFAULT not allowed */ /* TODO: Why not? */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_DEFAULT, DLT_TRACE_STATUS_OFF)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_DEFAULT, DLT_TRACE_STATUS_DEFAULT)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_DEFAULT)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* abnormal values for loglevel and tracestatus */ EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", -3, DLT_TRACE_STATUS_OFF)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", 100, DLT_TRACE_STATUS_OFF)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, -3)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ EXPECT_EQ(DLT_RETURN_WRONG_PARAMETER, dlt_register_context_ll_ts(&context, "TEST", "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, 100)); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context_ll_ts(&context, "TEST", NULL, DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_register_context_ll_ts, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(&context, NULL, "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(&context, NULL, NULL, DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(NULL, "TEST", NULL, DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(NULL, NULL, "dlt_user.c t_dlt_register_context_ll_ts normal", DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context_ll_ts(NULL, NULL, NULL, DLT_LOG_OFF, DLT_TRACE_STATUS_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_unregister_context */ TEST(t_dlt_unregister_context, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_unregister_context normal")); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_unregister_context, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, "", "d")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "T", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, "", "")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1", "1")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1234567890", "")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_unregister_context(&context)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST1234567890", "1")); */ EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_unregister_context normal")); /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_unregister_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_unregister_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_unregister_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_unregister_context normal")); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_register_context(&context, "TEST", NULL)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_unregister_context, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, NULL, "dlt_user.c t_dlt_unregister_context normal")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(&context, NULL, NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(NULL, "TEST", NULL)); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(NULL, NULL, "dlt_user.c t_dlt_unregister_context normal")); EXPECT_GE(DLT_RETURN_ERROR, dlt_register_context(NULL, NULL, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_register_injection_callback */ int dlt_user_injection_callback(uint32_t /*service_id*/, void */*data*/, uint32_t /*length*/) { return 0; } TEST(t_dlt_register_injection_callback, normal) { DltContext context; /* TODO: uint32_t service_id; */ EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_injection_callback normal")); /* TODO: service_id = 0x123; */ /* TODO: EXPECT_LE(DLT_RETURN_OK,dlt_register_injection_callback(&context, service_id, dlt_user_injection_callback)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_register_log_level_changed_callback */ void dlt_user_log_level_changed_callback(char /*context_id*/[DLT_ID_SIZE], uint8_t /*log_level*/, uint8_t /*trace_status*/) {} TEST(t_dlt_register_log_level_changed_callback, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_register_log_level_changed_callback normal")); EXPECT_LE(DLT_RETURN_OK, dlt_register_log_level_changed_callback(&context, dlt_user_log_level_changed_callback)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } #ifdef DLT_NETWORK_TRACE_ENABLE /*/////////////////////////////////////// */ /* t_dlt_user_trace_network */ TEST(t_dlt_user_trace_network, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network normal")); char header[16]; for (char i = 0; i < 16; ++i) header[(int)i] = i; char payload[32]; for (char i = 0; i < 32; ++i) payload[(int)i] = i; EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network(&context, DLT_NW_TRACE_IPC, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network(&context, DLT_NW_TRACE_CAN, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network(&context, DLT_NW_TRACE_FLEXRAY, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network(&context, DLT_NW_TRACE_MOST, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_trace_network, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network abnormal")); /* TODO: char header[16]; */ /* TODO: for(char i = 0; i < 16; ++i) */ /* TODO: { */ /* TODO: header[(int)i] = i; */ /* TODO: } */ /* TODO: char payload[32]; */ /* TODO: for(char i = 0; i < 32; ++i) */ /* TODO: { */ /* TODO: payload[(int)i] = i; */ /* TODO: } */ /* data length = 0. Does this make sense? */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, DLT_NW_TRACE_IPC, 0, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, DLT_NW_TRACE_CAN, 0, header, 0, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, DLT_NW_TRACE_FLEXRAY, 16, header, 0, payload)); */ /* invalid DltNetworkTraceType value */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, (DltNetworkTraceType)-100, 16, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, (DltNetworkTraceType)-10, 16, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, (DltNetworkTraceType)10, 16, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network(&context, (DltNetworkTraceType)100, 16, header, 32, payload)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_trace_network, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network nullpointer")); char header[16]; for (char i = 0; i < 16; ++i) header[(int)i] = i; char payload[32]; for (char i = 0; i < 32; ++i) payload[(int)i] = i; /* what to expect when giving in NULL pointer? */ EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network(&context, DLT_NW_TRACE_IPC, 16, NULL, 32, payload)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_trace_network(&context, DLT_NW_TRACE_CAN, 16, header, 32, NULL)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_trace_network(&context, DLT_NW_TRACE_FLEXRAY, 16, NULL, 32, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_trace_network_truncated */ TEST(t_dlt_user_trace_network_truncated, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network_truncated normal")); char header[16]; for (char i = 0; i < 16; ++i) header[(int)i] = i; char payload[32]; for (char i = 0; i < 32; ++i) payload[(int)i] = i; EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_IPC, 16, header, 32, payload, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_CAN, 16, header, 32, payload, 1)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_FLEXRAY, 16, header, 32, payload, -1)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_MOST, 16, header, 32, payload, 10)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_trace_network_truncated, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network_truncated abnormal")); /* TODO: char header[16]; */ /* TODO: for(char i = 0; i < 16; ++i) */ /* TODO: { */ /* TODO: header[(int)i] = i; */ /* TODO: } */ /* TODO: char payload[32]; */ /* TODO: for(char i = 0; i < 32; ++i) */ /* TODO: { */ /* TODO: payload[(int)i] = i; */ /* TODO: } */ /* data length = 0. Does this make sense? */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_IPC, 0, header, 32, payload, 0)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_CAN, 0, header, 0, payload, 0)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_FLEXRAY, 16, header, 0, payload, 0)); */ /* invalid DltNetworkTraceType value */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, (DltNetworkTraceType)-100, 16, header, 32, payload, 0)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, (DltNetworkTraceType)-10, 16, header, 32, payload, 0)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, (DltNetworkTraceType)10, 16, header, 32, payload, 0)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_truncated(&context, (DltNetworkTraceType)100, 16, header, 32, payload, 0)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_trace_network_truncated, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network_truncated nullpointer")); char header[16]; for (char i = 0; i < 16; ++i) header[(int)i] = i; char payload[32]; for (char i = 0; i < 32; ++i) payload[(int)i] = i; /* what to expect when giving in NULL pointer? */ EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_IPC, 16, NULL, 32, payload, 0)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_CAN, 16, header, 32, NULL, 0)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_trace_network_truncated(&context, DLT_NW_TRACE_FLEXRAY, 16, NULL, 32, NULL, 0)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } /*/////////////////////////////////////// */ /* t_dlt_user_trace_network_segmented */ TEST(t_dlt_user_trace_network_segmented, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network_segmented normal")); char header[16]; for (char i = 0; i < 16; ++i) header[(int)i] = i; char payload[32]; for (char i = 0; i < 32; ++i) payload[(int)i] = i; EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_IPC, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_CAN, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_FLEXRAY, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_MOST, 16, header, 32, payload)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_trace_network_segmented, abnormal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network_segmented abnormal")); /* TODO: char header[16]; */ /* TODO: for(char i = 0; i < 16; ++i) */ /* TODO: { */ /* TODO: header[(int)i] = i; */ /* TODO: } */ /* TODO: char payload[32]; */ /* TODO: for(char i = 0; i < 32; ++i) */ /* TODO: { */ /* TODO: payload[(int)i] = i; */ /* TODO: } */ /* data length = 0. Does this make sense? */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_IPC, 0, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_CAN, 0, header, 0, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_FLEXRAY, 16, header, 0, payload)); */ /* invalid DltNetworkTraceType value */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, (DltNetworkTraceType)-100, 16, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, (DltNetworkTraceType)-10, 16, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, (DltNetworkTraceType)10, 16, header, 32, payload)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_user_trace_network_segmented(&context, (DltNetworkTraceType)100, 16, header, 32, payload)); */ EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_trace_network_segmented, nullpointer) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_trace_network_segmented nullpointer")); char header[16]; for (char i = 0; i < 16; ++i) header[(int)i] = i; char payload[32]; for (char i = 0; i < 32; ++i) payload[(int)i] = i; /* what to expect when giving in NULL pointer? */ EXPECT_LE(DLT_RETURN_OK, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_IPC, 16, NULL, 32, payload)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_CAN, 16, header, 32, NULL)); EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_trace_network_segmented(&context, DLT_NW_TRACE_FLEXRAY, 16, NULL, 32, NULL)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } #endif /* DLT_NETWORK_TRACE_ENABLE */ /*/////////////////////////////////////// */ /* t_dlt_set_log_mode */ TEST(t_dlt_set_log_mode, normal) { EXPECT_LE(DLT_RETURN_OK, dlt_set_log_mode(DLT_USER_MODE_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_set_log_mode(DLT_USER_MODE_EXTERNAL)); EXPECT_LE(DLT_RETURN_OK, dlt_set_log_mode(DLT_USER_MODE_INTERNAL)); EXPECT_LE(DLT_RETURN_OK, dlt_set_log_mode(DLT_USER_MODE_BOTH)); } TEST(t_dlt_set_log_mode, abnormal) { /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_set_log_mode(DLT_USER_MODE_UNDEFINED)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_set_log_mode((DltUserLogMode)-100)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_set_log_mode((DltUserLogMode)-10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_set_log_mode((DltUserLogMode)10)); */ /* TODO: EXPECT_GE(DLT_RETURN_ERROR,dlt_set_log_mode((DltUserLogMode)100)); */ } /*/////////////////////////////////////// */ /* t_dlt_get_log_state */ TEST(t_dlt_get_log_state, normal) { sleep(1); dlt_init_common(); EXPECT_EQ(-1, dlt_get_log_state()); } /*/////////////////////////////////////// */ /* t_dlt_verbose_mode */ TEST(t_dlt_verbose_mode, normal) { EXPECT_LE(DLT_RETURN_OK, dlt_verbose_mode()); } /*/////////////////////////////////////// */ /* t_dlt_nonverbose_mode */ TEST(t_dlt_nonverbose_mode, normal) { EXPECT_LE(DLT_RETURN_OK, dlt_nonverbose_mode()); } /*/////////////////////////////////////// */ /* free dlt */ TEST(t_dlt_free, onetime) { EXPECT_EQ(DLT_RETURN_OK, dlt_free()); } /*/////////////////////////////////////// */ /* dlt_user_is_logLevel_enabled */ TEST(t_dlt_user_is_logLevel_enabled, normal) { DltContext context; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, dlt_register_context_ll_ts(&context, "ILLE", "t_dlt_user_is_logLevel_enabled context", DLT_LOG_INFO, -2)); /* DLT_USER_TRACE_STATUS_NOT_SET */ EXPECT_LE(DLT_RETURN_TRUE, dlt_user_is_logLevel_enabled(&context, DLT_LOG_FATAL)); EXPECT_LE(DLT_RETURN_TRUE, dlt_user_is_logLevel_enabled(&context, DLT_LOG_ERROR)); EXPECT_LE(DLT_RETURN_TRUE, dlt_user_is_logLevel_enabled(&context, DLT_LOG_WARN)); EXPECT_LE(DLT_RETURN_TRUE, dlt_user_is_logLevel_enabled(&context, DLT_LOG_INFO)); EXPECT_LE(DLT_RETURN_LOGGING_DISABLED, dlt_user_is_logLevel_enabled(&context, DLT_LOG_DEBUG)); EXPECT_LE(DLT_RETURN_LOGGING_DISABLED, dlt_user_is_logLevel_enabled(&context, DLT_LOG_VERBOSE)); EXPECT_LE(DLT_RETURN_LOGGING_DISABLED, dlt_user_is_logLevel_enabled(&context, DLT_LOG_OFF)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_context(&context)); EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } TEST(t_dlt_user_is_logLevel_enabled, nullpointer) { EXPECT_LE(DLT_RETURN_WRONG_PARAMETER, dlt_user_is_logLevel_enabled(NULL, DLT_LOG_FATAL)); } /*/////////////////////////////////////// */ /* t_dlt_user_shutdown_while_init_is_running */ struct ShutdownWhileInitParams { ShutdownWhileInitParams() = default; // delete copy constructor ShutdownWhileInitParams(const ShutdownWhileInitParams&) = delete; std::chrono::time_point stop_time; pthread_cond_t dlt_free_done = PTHREAD_COND_INITIALIZER; pthread_mutex_t dlt_free_mtx = PTHREAD_MUTEX_INITIALIZER; bool has_error = false; }; void* dlt_free_call_and_deadlock_detection(void *arg) { auto *params = static_cast(arg); // allow thread to be canceled int old_thread_type; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_thread_type); dlt_free(); // signal that we are done pthread_mutex_lock(¶ms->dlt_free_mtx); pthread_cond_signal(¶ms->dlt_free_done); pthread_mutex_unlock(¶ms->dlt_free_mtx); return nullptr; } void *dlt_free_thread(void *arg) { auto *params = static_cast(arg); while (std::chrono::steady_clock::now() < params->stop_time && !params->has_error) { // pthread cond_timedwait expects an absolute time to wait struct timespec abs_time{}; clock_gettime(CLOCK_REALTIME, &abs_time); abs_time.tv_sec += 3; // wait at most 3 seconds pthread_t dlt_free_deadlock_detection_thread_id; pthread_mutex_lock(¶ms->dlt_free_mtx); pthread_create(&dlt_free_deadlock_detection_thread_id, nullptr, dlt_free_call_and_deadlock_detection, params); const auto err = pthread_cond_timedwait(¶ms->dlt_free_done, ¶ms->dlt_free_mtx, &abs_time); pthread_mutex_unlock(¶ms->dlt_free_mtx); if (err == ETIMEDOUT) { fprintf(stderr, "\n%s: detected DLT-deadlock!\n", __func__); params->has_error = true; // cancel thread after timeout, so join won't block forever. pthread_cancel(dlt_free_deadlock_detection_thread_id); } pthread_join(dlt_free_deadlock_detection_thread_id, nullptr); } return nullptr; } TEST(t_dlt_user_shutdown_while_init_is_running, normal) { const auto max_runtime = std::chrono::seconds(5); const auto stop_time = std::chrono::steady_clock::now() + max_runtime; struct ShutdownWhileInitParams args{}; args.stop_time = stop_time; pthread_t dlt_free_thread_id; pthread_create(&dlt_free_thread_id, nullptr, dlt_free_thread, &args); while (std::chrono::steady_clock::now() < stop_time && !args.has_error) { dlt_init(); } pthread_join(dlt_free_thread_id, nullptr); EXPECT_FALSE(args.has_error); const auto last_init = dlt_init(); const auto last_free = dlt_free(); EXPECT_EQ(last_init, DLT_RETURN_OK); EXPECT_EQ(last_free, DLT_RETURN_OK); } /*/////////////////////////////////////// */ /* main */ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } dlt-daemon-2.18.10/tests/mod_system_logger/000077500000000000000000000000001446635226000206035ustar00rootroot00000000000000dlt-daemon-2.18.10/tests/mod_system_logger/Makefile000066400000000000000000000003021446635226000222360ustar00rootroot00000000000000obj-m := mod_system_logger.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean dlt-daemon-2.18.10/tests/mod_system_logger/mod_system_logger.c000066400000000000000000000015471446635226000245000ustar00rootroot00000000000000#include #include #include int i; static int system_proc_show(struct seq_file *m, void *v) { for (i = 0; i < 1000; i++) seq_printf(m, "Test Systemlogger %i\n", i); return 0; } static int system_proc_open(struct inode *inode, struct file *file) { return single_open(file, system_proc_show, NULL); } static const struct file_operations system_proc_fops = { .owner = THIS_MODULE, .open = system_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int __init system_proc_init(void) { proc_create("systemlogger", 0, NULL, &system_proc_fops); return 0; } static void __exit system_proc_exit(void) { remove_proc_entry("systemlogger", NULL); } MODULE_LICENSE("GPL"); module_init(system_proc_init); module_exit(system_proc_exit); dlt-daemon-2.18.10/tests/start_filetransfer_test.sh000077500000000000000000000010561446635226000223620ustar00rootroot00000000000000#!/bin/bash file="testfile_filetransfer.txt" fullpath="$(pwd)/testfile_filetransfer.txt" #start dlt-daemon dlt-daemon & sleep 1 #start dlt-test-receiver ./../build/tests/dlt_test_receiver -f localhost & sleep 1 #send file to daemon dlt-example-filetransfer $fullpath & sleep 1 #create md5 sum md5_1=($(md5sum $file)) md5_2=($(md5sum /tmp/$file)) echo $md5_1 echo $md5_2 #verify the sums tput setaf 1 if [ $md5_1 == $md5_2 ] then echo "Files are equal. Transfer succuess." else echo "File not equal. Error on transmission" fi tput setaf 7 pkill dlt-daemon dlt-daemon-2.18.10/tests/start_logstorage_test.sh000077500000000000000000000136311446635226000220460ustar00rootroot00000000000000#!/bin/sh ################################################################################ # SPDX license identifier: MPL-2.0 # # Copyright (C) 2016, Advanced Driver Information Technology # This code is developed by Advanced Driver Information Technology. # Copyright of Advanced Driver Information Technology, Bosch and DENSO. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ################################################################################ ################################################################################ #file : dlt_logstorage_test.sh # #Descriptiom : Smoke testing for logstorage feature of DLT # #Author : Onkar Palkar #Email : onkar.palkar@wipro.com # #History : 8/6/2016 ################################################################################ # # Function: -cleanup() # # Description -Delete the tmpDltLog folder if it already present # # Return -Zero on success # -Non zero on failure # cleanup() { pathTmp=/tmp folderName=tmpDltLog ls $pathTmp | grep $folderName > /dev/null if [ $? -eq '0' ] then rm -rf $pathTmp/$folderName fi pidof dlt-daemon > /dev/null if [ $? -eq '0' ] then killall dlt-daemon if [ $? -ne '0' ] then echo "Failed to kill dlt-daemon" return 1 fi fi return 0 } # # Function: -setup() # # Description -Create tmpDltLog folder # -Add dlt.conf file in the tmpDltLog folder # -Add dlt_logstorage.conf file in the tmpDltLog folder # # Return -Zero on success # -Non zero on failure # setup() { which dlt-daemon > /dev/null if [ $? -ne '0' ] then echo "dlt-daemon not available" return 1 fi which dlt-example-user > /dev/null if [ $? -ne '0' ] then echo "dlt-example-user not available" return 1 fi which dlt-convert > /dev/null if [ $? -ne '0' ] then echo "dlt-convert not available" return 1 fi mkdir $pathTmp/$folderName if [ $? -ne '0' ] then echo "Error while creating folder tmpDltLog" return 1 fi touch $pathTmp/$folderName/dlt.conf if [ $? -ne '0' ] then echo "Error while creating dlt.conf file" return 1 fi echo "SendContextRegistration = 1" >>$pathTmp/$folderName/dlt.conf echo "ECUId = ECU1" >>$pathTmp/$folderName/dlt.conf echo "SharedMemorySize = 100000" >>$pathTmp/$folderName/dlt.conf echo "LoggingMode = 0" >>$pathTmp/$folderName/dlt.conf echo "LoggingLevel = 6" >>$pathTmp/$folderName/dlt.conf echo "LoggingFilename = /tmp/dlt.log" >>$pathTmp/$folderName/dlt.conf echo "TimeOutOnSend = 4" >>$pathTmp/$folderName/dlt.conf echo "RingbufferMinSize = 500000" >>$pathTmp/$folderName/dlt.conf echo "RingbufferMaxSize = 10000000" >>$pathTmp/$folderName/dlt.conf echo "RingbufferStepSize = 500000" >>$pathTmp/$folderName/dlt.conf echo "ControlSocketPath = /tmp/dlt-ctrl.sock" >>$pathTmp/$folderName/dlt.conf echo "OfflineLogstorageMaxDevices = 2" >>$pathTmp/$folderName/dlt.conf echo "OfflineLogstorageDirPath = $pathTmp/$folderName" >>$pathTmp/$folderName/dlt.conf echo "OfflineLogstorageTimestamp = 1" >>$pathTmp/$folderName/dlt.conf echo "OfflineLogstorageDelimiter = _" >>$pathTmp/$folderName/dlt.conf echo "OfflineLogstorageMaxCounter = 999" >>$pathTmp/$folderName/dlt.conf echo "OfflineLogstorageCacheSize = 30000" >>$pathTmp/$folderName/dlt.conf touch $pathTmp/$folderName/dlt_logstorage.conf if [ $? -ne '0' ] then echo "Error while creating dlt_logstorage.conf file" return 1 fi echo "[FILTER1]" >>$pathTmp/$folderName/dlt_logstorage.conf echo "LogAppName=LOG" >>$pathTmp/$folderName/dlt_logstorage.conf echo "ContextName=TEST" >>$pathTmp/$folderName/dlt_logstorage.conf echo "LogLevel=DLT_LOG_INFO" >>$pathTmp/$folderName/dlt_logstorage.conf echo "File=Test" >>$pathTmp/$folderName/dlt_logstorage.conf echo "FileSize=10000" >>$pathTmp/$folderName/dlt_logstorage.conf echo "NOFiles=1" >>$pathTmp/$folderName/dlt_logstorage.conf return 0 } # # Function: -startDaemonAndApp() # # Description -Kill daemon if it is already running # -Start dlt-daemon # -Start dlt-example-user # # Return -Zero on success # -Non zero on failure # startDaemonAndApp() { dlt-daemon -c $pathTmp/$folderName/dlt.conf -d > /dev/null dlt-example-user test_msg > /dev/null return 0 } # # Function: -verifyTest() # # Description -Verify count of messages # # Return -Zero on success # -Non zero on failure # verifyTest() { ls $pathTmp/$folderName | grep .dlt > /dev/null if [ $? -ne '0' ] then echo "Log file is not present" return 1 fi msgCount=`dlt-convert -c $pathTmp/$folderName/*.dlt` if [ $? -ne '0' ] then echo "Error while reading count in log file" return 1 fi echo $msgCount | grep 10 > /dev/null if [ $? -ne '0' ] then echo "Message count is incorrect" return 1 fi return 0 } ######################################################################################## #main function ######################################################################################## cleanup setup if [ $? -ne '0' ] then echo "Error in function setup()" cleanup return 1 fi startDaemonAndApp if [ $? -ne '0' ] then echo "Error in function startDaemonAndApp()" cleanup return 1 fi verifyTest if [ $? -eq '0' ] then echo "Test Passed" else echo "Test Failed" fi cleanup dlt-daemon-2.18.10/tests/start_multinode_test.sh000077500000000000000000000234671446635226000217100ustar00rootroot00000000000000#!/bin/sh ################################################################################ # SPDX license identifier: MPL-2.0 # # Copyright (C) 2016, Advanced Driver Information Technology # This code is developed by Advanced Driver Information Technology. # Copyright of Advanced Driver Information Technology, Bosch and DENSO. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. ################################################################################ ################################################################################ #file : dlt_multinode_test.sh # #Description : Smoke testing for multinode feature of DLT # #Author Name : Onkar Palkar # Jeevan Ramakant Nagvekar #Email Id : onkar.palkar@wipro.com # jeevan.nagvekar1@wipro.com # #History : 31/07/2018 ################################################################################ ipaddr=127.0.0.1 # # Function: -getOSname() # # Description -Retrieves OS name # getOSname() { OS="`uname`" } # # Function: -cleanup() # # Description -Delete the dlt_test folder if it already present # -Check weather required binaries are avaiable or not # -Restore dlt_gateway.conf file # # Return -Zero on success # -Non zero on failure # cleanup() { tmpPath=/tmp tmpFolder=dlt_test gatewayFolderName=gateway passiveFolderName=passive tmpPassiveDIR=tmpPassive tmpLogFile=log_multinode.txt tmpLogAsciFile=log_multinode_a.txt if [ "$OS" = "QNX" ] then PIDOF() { slay -p $1 > /dev/null if [ $? -eq '0' ] then return 1 else return 0 fi } KILLALL() { slay -9 -f $1 > /dev/null if [ $? -eq '0' ] then return 1 else return 0 fi } else PIDOF() { pidof $1 > /dev/null return $? } KILLALL() { killall $1 > /dev/null return $? } fi cd $tmpPath PIDOF "dlt-daemon" if [ $? -eq '0' ] then KILLALL "dlt-daemon" if [ $? -ne '0' ] then echo "Failed to kill daemons" return 1 fi fi PIDOF "dlt-receive" if [ $? -eq '0' ] then KILLALL "dlt-receive" if [ $? -ne '0' ] then echo "Failed to kill dlt-receive" return 1 fi fi PIDOF "dlt-convert" if [ $? -eq '0' ] then KILLALL "dlt-convert" if [ $? -ne '0' ] then echo "Failed to kill dlt-convert" return 1 fi fi rm -rf $tmpPath/$tmpFolder >/dev/null return 0 } # # Function: -setupTest() # # Description -Create one gateway and passive folder # -Create and add dlt.conf and dlt_gateway.conf file in the gateway folder # -Create and add dlt.conf file in the passive folder # # Return -Zero on success # -Non zero on failure # setupTest() { which dlt-daemon > /dev/null if [ $? -ne '0' ] then echo "dlt-daemon is not available" return 1 fi which dlt-example-user > /dev/null if [ $? -ne '0' ] then echo "dlt-example-user is not available" return 1 fi which dlt-receive > /dev/null if [ $? -ne '0' ] then echo "dlt-receive is not available" return 1 fi mkdir -p $tmpPath/$tmpFolder if [ $? -ne '0' ] then echo "Error in creating dlt_test folder" return 1 fi mkdir -p $tmpPath/$tmpFolder/$gatewayFolderName if [ $? -ne '0' ] then echo "Error in creating gateway folder" return 1 fi touch $tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf if [ $? -ne '0' ] then echo "Error in creating dlt.conf file" return 1 fi echo "SendContextRegistration = 1" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "ECUId = ECU1" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "GatewayMode = 1" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "SharedMemorySize = 100000" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "LoggingMode = 0" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "LoggingLevel = 6" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "LoggingFilename = /tmp/dlt.log" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "TimeOutOnSend = 4" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "RingbufferMinSize = 500000" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "RingbufferMaxSize = 10000000" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "RingbufferStepSize = 500000" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "ControlSocketPath = /tmp/dlt-ctrl.sock" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf echo "GatewayConfigFile = $tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf" >> $tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf touch $tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf if [ $? -ne '0' ] then echo "Error in creating dlt_gateway file" return 1 fi echo "[PassiveNode1]" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf echo "IPaddress=$ipaddr">>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf echo "Port=3495" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf echo "EcuID=ECU2" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf echo "Connect=OnStartup" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf echo "Timeout=10" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf echo "NOFiles=1" >>$tmpPath/$tmpFolder/$gatewayFolderName/dlt_gateway.conf mkdir -p $tmpPath/$tmpFolder/$passiveFolderName if [ $? -ne '0' ] then echo "Error in creating passive folder" return 1 fi touch $tmpPath/$tmpFolder/$passiveFolderName/dlt.conf if [ $? -ne '0' ] then echo "Error in creating dlt.conf file" return 1 fi echo "SendContextRegistration = 1" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "ECUId = ECU2" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "SharedMemorySize = 100000" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "LoggingMode = 0" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "LoggingLevel = 6" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "LoggingFilename = /tmp/dlt.log" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "TimeOutOnSend = 4" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "RingbufferMinSize = 500000" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "RingbufferMaxSize = 10000000" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "RingbufferStepSize = 500000" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf echo "ControlSocketPath = /tmp/dlt-ctrl.sock" >>$tmpPath/$tmpFolder/$passiveFolderName/dlt.conf mkdir -p $tmpPath/$tmpFolder/$tmpPassiveDIR if [ $? -ne '0' ] then echo "Error while creating tempPassive folder" return 1 fi return 0 } # # Function: -startDaemons() # # Description -Start dlt-daemon as passive node # -Start dlt-daemon as gateway node # # Return -Zero on success # -Non zero on failure # startDaemons() { dlt-daemon -c $tmpPath/$tmpFolder/$passiveFolderName/dlt.conf -p 3495 -t $tmpPath/$tmpFolder/$tmpPassiveDIR -d > /dev/null dlt-daemon -c $tmpPath/$tmpFolder/$gatewayFolderName/dlt.conf -p 3490 -d > /dev/null return 0 } # # Function: -startExample() # # Description -Start dlt-example-user on passive node # # Return -Zero on success # -Non zero on failure # startExample() { export DLT_PIPE_DIR=$tmpPath/$tmpFolder/$tmpPassiveDIR dlt-example-user MultiNodeTesting > /dev/null & return 0 } # # Function: -starReceive() # # Description -Start dlt-receive # # Return -Zero on success # -Non zero on failure # startReceive() { dlt-receive -o $tmpPath/$tmpFolder/$tmpLogFile localhost & return 0 } # # Function: -verifyTest() # # Description -Start dlt-convert # -check weather msg sent by passive node are available in logs or not # # Return -Zero on success # -Non zero on failure # verifyTest() { dlt-convert -a $tmpPath/$tmpFolder/$tmpLogFile > $tmpPath/$tmpFolder/$tmpLogAsciFile cat $tmpPath/$tmpFolder/$tmpLogAsciFile | grep -F "ECU2" > /dev/null if [ $? -eq '0' ] then return 0 else return 1 fi } #main function ######################################################################################## getOSname cleanup if [ $? -ne '0' ] then echo "getIpAdd() failed" cleanup return 1 fi setupTest if [ $? -ne '0' ] then echo "setupTest() failed" cleanup return 1 fi startDaemons if [ $? -ne '0' ] then echo "startDaemons() failed" cleanup return 1 fi startExample if [ $? -ne '0' ] then echo "startExample() failed" cleanup return 1 fi #wait for 1 sec before starting dlt-receive to start dlt-example-user application properly sleep 1 startReceive if [ $? -ne '0' ] then echo "startReceive() failed" cleanup return 1 fi #Wait for 1 sec to collect messages sent by application at gateway sleep 1 verifyTest if [ $? -eq '0' ] then echo "Test Passed" else echo "Test Failed" fi cleanup dlt-daemon-2.18.10/tests/start_qnx_system_test.sh000077500000000000000000000207211446635226000221100ustar00rootroot00000000000000#!/bin/sh ################################################################################ # This software has been developed by Advanced Driver Information Technology. # Copyright(c) 2021 Advanced Driver Information Technology GmbH, # Advanced Driver Information Technology Corporation, Robert Bosch GmbH, # Robert Bosch Car Multimedia GmbH and DENSO Corporation. # All rights reserved. ################################################################################ ################################################################################ # File: start_qnx_system_test.sh # # Description: Test script to verify dlt-qnx-system using dlt-test-qnx-slogger ################################################################################ usage() { cat < "${DLT_RECEIVE_FILTER}" # Start dlt-receive echo "Start dlt-receive" "${DEV_DLT_PATH}"/dlt-receive -a -f "${DLT_RECEIVE_FILTER}" 127.0.0.1 > "${DLT_TEST_RESULT}" & sleep "${SLEEP_TIME}" # Start dlt-qnx-system echo "Start dlt-qnx-system" "${DEV_DLT_PATH}"/dlt-qnx-system > /dev/null & sleep "${SLEEP_TIME}" # Start dlt-test-qnx-slogger and wait until it's done echo "Start dlt-test-qnx-slogger" "${DEV_DLT_PATH}"/dlt-test-qnx-slogger -n "${COUNT}" -d "${DELAY}" -l "${LENGTH}" > /dev/null sleep "${SLEEP_TIME}" } ################################################################################ # Function: dlt_qnx_test_result # # Description: Verify result from dlt_run_app() function ################################################################################ dlt_qnx_test_result() { echo "" echo "Verify test result" TEST_RESULT_1="PASS" TEST_RESULT_2="PASS" TEST_RESULT_3="PASS" BUFFER_NAME="dlt_test_qnx_slogger" ######################################### # 1. Verify if all messages are received ######################################### RESULT_COUNT=$(grep "${BUFFER_NAME}.*slog" -c "${DLT_TEST_RESULT}") if [ "${RESULT_COUNT}" -ne "${COUNT}" ]; then echo "Number of log messages are not matching (Expected: ${COUNT}, Actual: ${RESULT_COUNT})" TEST_RESULT_1="FAIL" fi #### RESULT=$(grep "${BUFFER_NAME}.*slog" "${DLT_TEST_RESULT}") RESULT_TIME_PREV=0 echo "$RESULT"| while read LINE do pr_verbose "$0" "TEST : LINE=${LINE}" RESULT_TIME=$(echo "${LINE}" | awk -F " " '{print $3}') RESULT_PAYLOAD=$(echo "${LINE}" | awk -F " " '{print $17}') ############################################################# # 2. Verify if each log messages have expected time interval # Allow diff between ${DELAY} and ${DELAY}+10 msec ############################################################# pr_verbose "$0" "TEST2: RESULT_TIME=${RESULT_TIME}, RESULT_TIME_PREV=${RESULT_TIME_PREV}" # Compare diff of timestamps from second log message if [ "${RESULT_TIME_PREV}" -ne 0 ]; then RESULT_TIME_DIFF=$((RESULT_TIME - RESULT_TIME_PREV)) RANGE_MIN=$((DELAY * 10)) RANGE_MAX=$(((DELAY + 10) * 10)) if [[ "${RANGE_MIN}" -gt "${RESULT_TIME_DIFF}" ]] | [[ "${RANGE_MAX}" -le "${RESULT_TIME_DIFF}" ]]; then echo "Diff of timestamp is too big (Expected diff: ${RANGE_MIN}-${RANGE_MAX}, Actual diff: ${RESULT_TIME_DIFF}" TEST_RESULT_2="FAIL" fi fi RESULT_TIME_PREV=${RESULT_TIME} ################################################################# # 3. Verify if each log messages receives expected string length ################################################################# pr_verbose "$0" "TEST2: RESULT_PAYLOAD=${RESULT_PAYLOAD}" RESULT_LENGTH=$(echo ${#RESULT_PAYLOAD}) if [ "${RESULT_LENGTH}" -ne "${LENGTH}" ]; then echo "Length is not matching (Excepted:${LENGTH}, Actual:${RESULT_LENGTH})" TEST_RESULT_3="FAIL" fi done # Print test result echo " 1. Verify if all messages are received : ${TEST_RESULT_1}" echo " 2. Verify if each log messages have expected time interval : ${TEST_RESULT_2}" echo " 3. Verify if each log messages receives expected string length: ${TEST_RESULT_3}" } ################################################################################ # Function: dlt_qnx_verify_app # # Description: Verify if necessary binaries are existing on the target and have # execute permission ################################################################################ dlt_qnx_verify_app() { APP=$1 pr_verbose "$0" "Verify ${APP} is existing on the target and have execute permission" if [ ! -e "${APP}" ]; then echo "${APP} is missing!" exit 1 elif [ ! -x "${APP}" ]; then echo "${APP} does not have execute permission!" exit 1 fi } ################################################################################ # Main ################################################################################ VERBOSE=0 SLEEP_TIME=1 COUNT=10 DELAY=500 LENGTH=100 DLT_TEST_RESULT="dlt_qnx_system_test.txt" DLT_RECEIVE_FILTER="dlt_receive_filter.txt" DEV_DLT_PATH="/usr/bin" # OS if [ "$(uname)" != "QNX" ]; then echo "This script can be only run under QNX system!" exit 1 fi # Options while getopts "vn:d:l:h" optKey; do case "${optKey}" in v) VERBOSE=1 ;; n) COUNT=${OPTARG} ;; d) DELAY=${OPTARG} ;; l) LENGTH=${OPTARG} ;; '-h'|'--help'|*) usage ;; esac done echo "*******************************" echo " Run dlt-test-qnx-system with:" echo " Number of logs: ${COUNT}" echo " Delay : ${DELAY} msec" echo " Payload length: ${LENGTH} bytes" echo "*******************************" echo "" # Start dlt-daemon if [ ! "$(pidin u | grep dlt-daemon)" ]; then echo "Start dlt-daemon in daemonized mode" dlt-daemon -d fi # Verify necessary binaries are available under the target dlt_qnx_verify_app ${DEV_DLT_PATH}/dlt-receive dlt_qnx_verify_app ${DEV_DLT_PATH}/dlt-qnx-system dlt_qnx_verify_app ${DEV_DLT_PATH}/dlt-test-qnx-slogger #dlt_qnx_configure_setup dlt_qnx_clean_app dlt_qnx_clean_log dlt_qnx_run_app dlt_qnx_clean_app dlt_qnx_test_result dlt_qnx_clean_log slay dlt-daemon dlt-daemon-2.18.10/tests/start_system_logger_test.sh000077500000000000000000000023401446635226000225560ustar00rootroot00000000000000#!/bin/bash #enable logging of files and setup sudo sed -i 's/LogFileEnable = 0/LogFileEnable = 1/g' /usr/local/etc/dlt-system.conf echo "# TEST LOG TO SYSTEMLOGGER_PROC" | sudo tee -a /usr/local/etc/dlt-system.conf echo "LogFileFilename = /proc/systemlogger" | sudo tee -a /usr/local/etc/dlt-system.conf echo "LogFileMode = 1" | sudo tee -a /usr/local/etc/dlt-system.conf echo "LogFileTimeDelay = 3" | sudo tee -a /usr/local/etc/dlt-system.conf echo "LogFileContextId = PROC" | sudo tee -a /usr/local/etc/dlt-system.conf #comile the kernel module for system logging cd mod_system_logger make cd .. #enable mod sudo insmod mod_system_logger/mod_system_logger.ko #start dlt-daemon dlt-daemon & sleep 1 #start dlt-system dlt-system & sleep 1 #start dlt-receiver ../build/tests/dlt_test_receiver -l localhost & sleep 1 pid=$! wait $pid exitcode=$? #kill processes and remove mod pkill dlt-daemon pkill dlt-system sudo rmmod mod_system_logger cd mod_system_logger make clean cd .. # if exit code == 159 , test successfull tput setaf 1 if [ $exitcode == 159 ]; then echo "System Logger tests successfull." else echo "System Logger tests failed." echo "Maybe missing kernel-heaers" echo "for compiling the test module" fi tput setaf 7 dlt-daemon-2.18.10/tests/start_systemd_journal_test.sh000077500000000000000000000015731446635226000231240ustar00rootroot00000000000000#!/bin/bash #build and install with SYSTEMD_JOURNAL=ON mkdir ../build cd ../build/ cmake -DWITH_SYSTEMD_JOURNAL=ON -DWITH_DLT_UNIT_TESTS=ON .. make sudo make install #enable SYSTEMD_JOURNAL in config file sudo vim -esnc '%s/JournalEnable = 0/JournalEnable = 1/g|:wq' /usr/local/etc/dlt-system.conf #start dlt-daemon dlt-daemon & sleep 1 #start dlt_system sudo dlt-system & sleep 1 #send 10 times "DLT SYSTEM JOURNAL TEST" for i in {1..1000} do logger DLT SYSTEM JOURNAL TEST done #start receiver ./../build/tests/dlt_test_receiver -s localhost & sleep 1 pid=$! wait $pid exitcode=$? # kill processes, receiver automatically killed with daemon pkill dlt-daemon sudo pkill dlt-system # if exit code == 159 , test successfull tput setaf 1 if [ $exitcode == 159 ]; then echo "Systemd Journal tests successfull." else echo "Systemd Journal tests failed." fi tput setaf 7 dlt-daemon-2.18.10/tests/testfile.dlt000066400000000000000000000105721446635226000174120ustar00rootroot00000000000000DLT&,Mآ ECU5ECU?b:APPCONremoDLT&,Mآ ECU5ECU?b:APPCONremoDLT&,Mآ ECU5ECU?b:APPCON DLT&,Mآ ECU5ECU?b:APPCON DLT+,MzECU!ALOGTES1DLT+,MzECU!ALOGTES1BDLT+,MzECU!ALOGTES1 Hello BMWDLT+,MzECU!ALOGTES2AeDLT+,MzECU!ALOGTES2BfDLT+,MzECU!ALOGTES2CgDLT+,MzECU!ALOGTES2DhDLT+,MzECU!ALOGTES2!iDLT+,MzECU!ALOGTES2"jDLT+,MzECU!ALOGTES2#kDLT+,MzECU!ALOGTES2$lDLT+,MzECU!ALOGTES2#mDLT+,MzECU! ALOGTES2CnDLT+,MzECU! ALOGTES2oDLT+,MzECU! 'ALOGTES2STRING 112 messageDLT+,MzECU! (ALOGTES2CSTRING 113 messageDLT+,MzECU! ALOGTES2̌?DLT+,MzECU!ALOGTES2333333?DLT+,MzECU! ALOGTES2 Hello worldDLT,,MHECU!ALOGTES3DLT,,MHECU!ALOGTES3#DLT,,MHECU!ALOGTES3## DLT,,MHECU!&ALOGTES3#)#*#+DLT,,MHECU!.ALOGTES3#3#4#5#6DLT,,MHECU!6ALOGTES3#=#>#?#@#ADLT,,MHECU!>ALOGTES3#G#H#I#J#K#LDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT4,M@ECU5ECU?o&APPCONremoDLT4,M@ECU5ECU?o&APPCONremoDLT4,M@ECU5ECU?o&APPCON DLT4,M@ECU5ECU?o&APPCON DLT7,M1ECU eDLT7,M1ECU  fDLT7,M1ECU g Hello BMWDLT7,M1ECU eDLT7,M1ECU  fDLT7,M1ECU  gDLT7,M1ECU hDLT7,M1ECU  iDLT7,M1ECU  jDLT7,M1ECU  kDLT7,M1ECU lDLT7,M1ECU  mDLT7,M1ECU nDLT7,M1ECU oDLT7,M1ECU STRING 112 messageDLT7,M1ECU CSTRING 113 messageDLT7,M1ECU ̌?DLT7,M1ECU 333333?DLT7,M1ECU  Hello worldDLT8,M3cECU -DLT8,M3cECU  .DLT8,M3cECU / DLT8,M3cECU 0)*+DLT8,M3cECU 13456DLT8,M3cECU 1=>?@ADLT8,M3cECU  1GHIJKLDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worlddlt-daemon-2.18.10/tests/testfile_extended.dlt000066400000000000000000000116241446635226000212710ustar00rootroot00000000000000DLT>_NECU1=AECU10 LOGTEST#Message with log level 1DLTT_] ECU1=AECU10 iq!LOGTEST#Message with log level 2DLT]_8ECU1=AECU10 1LOGTEST#Message with log level 3DLTe_ECU1=AECU10 ALOGTEST#Message with log level 4DLT(_pECU1=vECU10 1APP1CON1#NThis is a long message... This is a long message... This is a long message...DLT$_hECU1=@ECU10 *}1APP1CON1#This is a short messageDLT&,Mآ ECU5ECU?b:APPCONremoDLT&,Mآ ECU5ECU?b:APPCONremoDLT&,Mآ ECU5ECU?b:APPCON DLT&,Mآ ECU5ECU?b:APPCON DLT+,MzECU!ALOGTES1DLT+,MzECU!ALOGTES1BDLT+,MzECU!ALOGTES1 Hello BMWDLT+,MzECU!ALOGTES2AeDLT+,MzECU!ALOGTES2BfDLT+,MzECU!ALOGTES2CgDLT+,MzECU!ALOGTES2DhDLT+,MzECU!ALOGTES2!iDLT+,MzECU!ALOGTES2"jDLT+,MzECU!ALOGTES2#kDLT+,MzECU!ALOGTES2$lDLT+,MzECU!ALOGTES2#mDLT+,MzECU! ALOGTES2CnDLT+,MzECU! ALOGTES2oDLT+,MzECU! 'ALOGTES2STRING 112 messageDLT+,MzECU! (ALOGTES2CSTRING 113 messageDLT+,MzECU! ALOGTES2̌?DLT+,MzECU!ALOGTES2333333?DLT+,MzECU! ALOGTES2 Hello worldDLT,,MHECU!ALOGTES3DLT,,MHECU!ALOGTES3#DLT,,MHECU!ALOGTES3## DLT,,MHECU!&ALOGTES3#)#*#+DLT,,MHECU!.ALOGTES3#3#4#5#6DLT,,MHECU!6ALOGTES3#=#>#?#@#ADLT,,MHECU!>ALOGTES3#G#H#I#J#K#LDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU! (ALOGTES4#  Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT-,MECU!(ALOGTES4# Hello worldDLT4,M@ECU5ECU?o&APPCONremoDLT4,M@ECU5ECU?o&APPCONremoDLT4,M@ECU5ECU?o&APPCON DLT4,M@ECU5ECU?o&APPCON DLT7,M1ECU eDLT7,M1ECU  fDLT7,M1ECU g Hello BMWDLT7,M1ECU eDLT7,M1ECU  fDLT7,M1ECU  gDLT7,M1ECU hDLT7,M1ECU  iDLT7,M1ECU  jDLT7,M1ECU  kDLT7,M1ECU lDLT7,M1ECU  mDLT7,M1ECU nDLT7,M1ECU oDLT7,M1ECU STRING 112 messageDLT7,M1ECU CSTRING 113 messageDLT7,M1ECU ̌?DLT7,M1ECU 333333?DLT7,M1ECU  Hello worldDLT8,M3cECU -DLT8,M3cECU  .DLT8,M3cECU / DLT8,M3cECU 0)*+DLT8,M3cECU 13456DLT8,M3cECU 1=>?@ADLT8,M3cECU  1GHIJKLDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worldDLT9,MECU  Hello worlddlt-daemon-2.18.10/tests/testfile_filetransfer.txt000066400000000000000000000001161446635226000222030ustar00rootroot00000000000000TEST DATEI. 123. qwertzuiopü+ asdfghjklöä# # Description: # <...> # <...> ### END INIT INFO # Author: root # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC=dlt-daemon # Introduce a short description here NAME=dlt-daemon # Introduce the short server's name here DAEMON=@CMAKE_INSTALL_PREFIX@/bin/dlt-daemon # Introduce the server's location here DAEMON_ARGS="-d" # Arguments to run the daemon with PIDFILE=/tmp/dltd.lock # Path is configured with DLT configuration of DLT_USER_DIR/DLT_DAEMON_LOCK_FILE SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x $DAEMON ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready # to handle requests from services started subsequently which depend # on this one. As a last resort, sleep for some time. } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred # default: --retry=TERM/30/KILL/5 start-stop-daemon --stop --quiet --retry=TERM/1/KILL/1 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. # default: --retry=0/30/KILL/5 start-stop-daemon --stop --quiet --oknodo --retry=0/1/KILL/1 --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } # # Function that sends a SIGHUP to the daemon/service # do_reload() { # # If the daemon can reload its configuration without # restarting (for example, when it is sent a SIGHUP), # then implement that here. # start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME return 0 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) if [ -f /var/log/messages ] then log_daemon_msg "------- messages ----------------" cat /var/log/messages | grep -a DLT | tail fi if [ -f /var/log/syslog ] then log_daemon_msg "------- SYSLOG -------------------" cat /var/log/syslog | grep -a DLT | tail fi pidofdlt=`pidof $DESC` if [ $pidofdlt ] then log_daemon_msg "$NAME has the PID:$pidofdlt" fi status_of_proc "$DAEMON" "$NAME" || exit $? ;; #reload|force-reload) # # If do_reload() is not implemented then leave this commented out # and leave 'force-reload' as an alias for 'restart'. # #log_daemon_msg "Reloading $DESC" "$NAME" #do_reload #log_end_msg $? #;; restart|force-reload) # # If the "reload" option is implemented then remove the # 'force-reload' alias # log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 exit 3 ;; esac : dlt-daemon-2.18.10/util/000077500000000000000000000000001446635226000146745ustar00rootroot00000000000000dlt-daemon-2.18.10/util/create_dlt_user_h.py000077500000000000000000000022571446635226000207320ustar00rootroot00000000000000#!/usr/bin/python3 # This software has been developed by Advanced Driver Information Technology. # Copyright(c) 2020 Advanced Driver Information Technology GmbH, # Advanced Driver Information Technology Corporation, Robert Bosch GmbH, # Robert Bosch Car Multimedia GmbH and DENSO Corporation. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. import pathlib import argparse def main(header_in_file, header_out_file): header_in = pathlib.Path(header_in_file) header_out = pathlib.Path(header_out_file) with header_in.open() as hi, header_out.open('w') as ho: for line in hi: if line.startswith("#cmakedefine"): continue ho.write(line) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('header_in') parser.add_argument('header_out') args = parser.parse_args() main(args.header_in, args.header_out) dlt-daemon-2.18.10/util/create_dlt_version_h.py000077500000000000000000000052171446635226000214400ustar00rootroot00000000000000#!/usr/bin/python3 # This software has been developed by Advanced Driver Information Technology. # Copyright(c) 2019 Advanced Driver Information Technology GmbH, # Advanced Driver Information Technology Corporation, Robert Bosch GmbH, # Robert Bosch Car Multimedia GmbH and DENSO Corporation. # # This file is part of COVESA Project DLT - Diagnostic Log and Trace. # # This Source Code Form is subject to the terms of the # Mozilla Public License (MPL), v. 2.0. # If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # # For further information see http://www.covesa.org/. import pathlib import subprocess import argparse import re def get_cmd(cmd, cwd): return subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.STDOUT ).decode().strip() def get_revision(git_dir): try: rev = get_cmd('git describe --tags', git_dir) if not rev.startswith("fatal:"): return rev rev = get_cmd('git rev-parse HEAD', git_dir) if not rev.startswith("fatal:"): return rev except subprocess.CalledProcessError: pass return get_cmd('date +%F', git_dir) def main(cmake_file, header_in_file, header_out_file): cmakelists = pathlib.Path(cmake_file) header_in = pathlib.Path(header_in_file) header_out = pathlib.Path(header_out_file) git_dir = str(header_in.parent) cmake_vars = {} for m in re.finditer( 'project\(\S+ VERSION (?P\d+)\.(?P\d+)\.(?P\d+)(\.(?P\d+))?', cmakelists.open().read()): cmake_vars['PROJECT_VERSION_MAJOR'] = m.group('major') cmake_vars['PROJECT_VERSION_MINOR'] = m.group('minor') cmake_vars['PROJECT_VERSION_PATCH'] = m.group('patch') cmake_vars['PROJECT_VERSION'] = "{}.{}.{}".format(m.group('major'), m.group('minor'), m.group('patch')) cmake_vars['PROJECT_VERSION_TWEAK'] = m.group('tweak') cmake_vars['DLT_REVISION'] = get_revision(git_dir) cmake_vars['DLT_VERSION_STATE'] = 'STABLE' header_out.parent.mkdir(parents=True, exist_ok=True) with header_in.open() as hi, header_out.open('w') as ho: for line in hi: text, _ = re.subn('@(?P\w+)@', lambda x: cmake_vars.get(x.group('var_name'), "NONE"), line) ho.write(text) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('cmakelists') parser.add_argument('header_in') parser.add_argument('header_out') args = parser.parse_args() main(args.cmakelists, args.header_in, args.header_out) dlt-daemon-2.18.10/util/dlt_coverage_report/000077500000000000000000000000001446635226000207255ustar00rootroot00000000000000dlt-daemon-2.18.10/util/dlt_coverage_report/lcov_report_generator.sh000077500000000000000000000006211446635226000256670ustar00rootroot00000000000000#!/bin/bash mkdir dlt_lcov_report lcov --capture --directory $1/src --output-file dlt_lcov_report/dlt_init_coverage.info > /dev/null lcov --remove dlt_lcov_report/dlt_init_coverage.info -o dlt_lcov_report/dlt_final_coverage.info '/usr/*' '*/include/*' > /dev/null rm dlt_lcov_report/dlt_init_coverage.info > /dev/null genhtml dlt_lcov_report/dlt_final_coverage.info --output-directory dlt_lcov_report