LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 53.9 % 2636 1421
Test Date: 2026-08-27 10:11:10 Functions: 75.3 % 170 128

            Line data    Source code
       1              : /*
       2              :  * SPDX license identifier: MPL-2.0
       3              :  *
       4              :  * Copyright (C) 2011-2015, BMW AG
       5              :  *
       6              :  * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
       7              :  *
       8              :  * This Source Code Form is subject to the terms of the
       9              :  * Mozilla Public License (MPL), v. 2.0.
      10              :  * If a copy of the MPL was not distributed with this file,
      11              :  * You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  * For further information see http://www.covesa.org/.
      14              :  */
      15              : 
      16              : /*!
      17              :  * \author
      18              :  * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
      19              :  * Markus Klein <Markus.Klein@esk.fraunhofer.de>
      20              :  * Mikko Rapeli <mikko.rapeli@bmw.de>
      21              :  *
      22              :  * \copyright Copyright © 2011-2015 BMW AG. \n
      23              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      24              :  *
      25              :  * \file dlt_user.c
      26              :  */
      27              : 
      28              : #include <stdlib.h> /* for getenv(), free(), atexit() */
      29              : #include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
      30              : #include <stdarg.h>
      31              : #include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
      32              : 
      33              : #if !defined(__WIN32__)
      34              : #include <syslog.h> /* for LOG_... */
      35              : #include <semaphore.h>
      36              : #include <pthread.h> /* POSIX Threads */
      37              : #endif
      38              : 
      39              : #include <sys/time.h>
      40              : #include <math.h>
      41              : 
      42              : #include <sys/stat.h>
      43              : #include <fcntl.h>
      44              : #include <errno.h>
      45              : 
      46              : #include <sys/uio.h> /* writev() */
      47              : #include <poll.h>
      48              : 
      49              : #include <limits.h>
      50              : #ifdef linux
      51              : #include <sys/prctl.h> /* for PR_SET_NAME */
      52              : #endif
      53              : 
      54              : #include <sys/types.h> /* needed for getpid() */
      55              : #include <unistd.h>
      56              : 
      57              : #include <stdbool.h>
      58              : 
      59              : #include <stdatomic.h>
      60              : #include <stdint.h>
      61              : 
      62              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
      63              : #include <sys/socket.h>
      64              : #endif
      65              : 
      66              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
      67              : #include <sys/un.h>
      68              : #endif
      69              : #ifdef DLT_LIB_USE_VSOCK_IPC
      70              : #ifdef linux
      71              : #include <linux/vm_sockets.h>
      72              : #endif
      73              : #ifdef __QNX__
      74              : #include <vm_sockets.h>
      75              : #endif
      76              : #endif
      77              : 
      78              : #include "dlt_user.h"
      79              : #include "dlt_common.h"
      80              : #include "dlt_log.h"
      81              : #include "dlt_user_shared.h"
      82              : #include "dlt_user_shared_cfg.h"
      83              : #include "dlt_user_cfg.h"
      84              : 
      85              : #ifdef DLT_FATAL_LOG_RESET_ENABLE
      86              : #define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL)                                                                             \
      87              :     do {                                                                                                               \
      88              :         if (LOGLEVEL == DLT_LOG_FATAL) {                                                                               \
      89              :             int* p = NULL;                                                                                             \
      90              :             *p = 0;                                                                                                    \
      91              :         }                                                                                                              \
      92              :     } while (false)
      93              : #else /* DLT_FATAL_LOG_RESET_ENABLE */
      94              : #define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL)
      95              : #endif /* DLT_FATAL_LOG_RESET_ENABLE */
      96              : 
      97              : enum InitState { INIT_UNITIALIZED, INIT_IN_PROGRESS, INIT_ERROR, INIT_DONE };
      98              : 
      99              : static DltUser dlt_user;
     100              : static _Atomic enum InitState dlt_user_init_state = INIT_UNITIALIZED;
     101              : #define DLT_USER_INITIALIZED (dlt_user_init_state == INIT_DONE)
     102              : #define DLT_USER_INIT_ERROR (dlt_user_init_state == INIT_ERROR)
     103              : #define DLT_USER_INITIALIZED_NOT_FREEING (DLT_USER_INITIALIZED && (dlt_user_freeing == 0))
     104              : 
     105              : static _Atomic int dlt_user_freeing = 0;
     106              : static bool dlt_user_file_reach_max = false;
     107              : 
     108              : #ifdef DLT_LIB_USE_FIFO_IPC
     109              : static char dlt_user_dir[DLT_PATH_MAX];
     110              : static char dlt_daemon_fifo[DLT_PATH_MAX];
     111              : #endif
     112              : 
     113              : static pthread_mutex_t dlt_mutex;
     114              : static pthread_mutexattr_t dlt_mutex_attr;
     115              : 
     116        91183 : void dlt_mutex_lock(void)
     117              : {
     118        91183 :     pthread_mutex_lock(&dlt_mutex);
     119        91183 : }
     120              : 
     121       133187 : void dlt_mutex_unlock(void)
     122              : {
     123       133187 :     pthread_mutex_unlock(&dlt_mutex);
     124       133187 : }
     125              : 
     126              : static pthread_t dlt_housekeeperthread_handle;
     127              : static atomic_bool dlt_user_housekeeper_exit_requested = false;
     128              : pthread_mutex_t dlt_housekeeper_running_mutex = PTHREAD_MUTEX_INITIALIZER;
     129              : pthread_cond_t dlt_housekeeper_running_cond;
     130              : 
     131              : /* calling dlt_user_atexit_handler() second time fails with error message */
     132              : static int atexit_registered = 0;
     133              : 
     134              : /* used to disallow DLT usage in fork() child */
     135              : static int g_dlt_is_child = 0;
     136              : 
     137              : /* String truncate message */
     138              : static const char STR_TRUNCATED_MESSAGE[] = "... <<Message truncated, too long>>";
     139              : 
     140              : /* Enum for type of string */
     141              : enum StringType { ASCII_STRING = 0, UTF8_STRING = 1 };
     142              : 
     143              : /* Data type holding "Variable Info" (VARI) properties
     144              :  * Some of the supported data types (eg. bool, string, raw) have only "name", but not "unit".
     145              :  */
     146              : typedef struct VarInfo {
     147              :     const char* name;  // the "name" attribute (can be NULL)
     148              :     const char* unit;  // the "unit" attribute (can be NULL)
     149              :     bool with_unit;    // true if the "unit" field is to be considered
     150              : } VarInfo;
     151              : 
     152              : #define DLT_UNUSED(x) (void)(x)
     153              : 
     154              : /* Network trace */
     155              : #ifdef DLT_NETWORK_TRACE_ENABLE
     156              : #define DLT_USER_SEGMENTED_THREAD (1 << 2)
     157              : 
     158              : /* Segmented Network Trace */
     159              : #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
     160              : #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
     161              : #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
     162              : 
     163              : /* Mutex to wait on while message queue is not initialized */
     164              : pthread_mutex_t mq_mutex = PTHREAD_MUTEX_INITIALIZER;
     165              : pthread_cond_t mq_init_condition;
     166              : #endif /* DLT_NETWORK_TRACE_ENABLE */
     167              : 
     168        42004 : void dlt_lock_mutex(pthread_mutex_t* mutex)
     169              : {
     170        42004 :     int32_t lock_mutex_result = pthread_mutex_lock(mutex);
     171              : 
     172        42004 :     if (lock_mutex_result != 0)
     173            0 :         dlt_vlog(LOG_ERR, "Mutex lock failed unexpected pid=%i with result %i!\n", getpid(), lock_mutex_result);
     174        42004 : }
     175              : 
     176        63006 : void dlt_unlock_mutex(pthread_mutex_t* mutex)
     177              : {
     178        63006 :     pthread_mutex_unlock(mutex);
     179        63006 : }
     180              : 
     181              : /* Structure to pass data to segmented thread */
     182              : typedef struct {
     183              :     DltContext* handle;
     184              :     uint32_t id;
     185              :     DltNetworkTraceType nw_trace_type;
     186              :     uint32_t header_len;
     187              :     void* header;
     188              :     uint32_t payload_len;
     189              :     void* payload;
     190              : } s_segmented_data;
     191              : 
     192              : /* Function prototypes for internally used functions */
     193              : static void* dlt_user_housekeeperthread_function(void* ptr);
     194              : static void dlt_user_atexit_handler(void);
     195              : static DltReturnValue dlt_user_log_init(DltContext* handle, DltContextData* log);
     196              : static DltReturnValue dlt_user_log_send_log(DltContextData* log, int mtype, int* sent_size);
     197              : static DltReturnValue dlt_user_log_send_log_v2(
     198              :     DltContextData* log, const int mtype, DltHtyp2ContentType msgcontent, int* const sent_size);
     199              : static DltReturnValue dlt_user_log_send_register_application(void);
     200              : static DltReturnValue dlt_user_log_send_register_application_v2(void);
     201              : static DltReturnValue dlt_user_log_send_unregister_application(void);
     202              : static DltReturnValue dlt_user_log_send_unregister_application_v2(void);
     203              : static DltReturnValue dlt_user_log_send_register_context(DltContextData* log);
     204              : static DltReturnValue dlt_user_log_send_register_context_v2(DltContextData* log);
     205              : static DltReturnValue dlt_user_log_send_unregister_context(DltContextData* log);
     206              : static DltReturnValue dlt_user_log_send_unregister_context_v2(DltContextData* log);
     207              : static DltReturnValue dlt_send_app_ll_ts_limit(
     208              :     const char* apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
     209              : static DltReturnValue dlt_send_app_ll_ts_limit_v2(
     210              :     const char* apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
     211              : static DltReturnValue dlt_user_log_send_log_mode(DltUserLogMode mode, uint8_t version);
     212              : static DltReturnValue dlt_user_log_send_marker(void);
     213              : static DltReturnValue dlt_user_print_msg(DltMessage* msg, DltContextData* log);
     214              : static DltReturnValue dlt_user_print_msg_v2(DltMessageV2* msg, DltContextData* log);
     215              : static DltReturnValue dlt_user_log_check_user_message(void);
     216              : static void dlt_user_log_reattach_to_daemon(void);
     217              : static DltReturnValue dlt_user_log_send_overflow(void);
     218              : static DltReturnValue dlt_user_log_out_error_handling(
     219              :     void* ptr1, size_t len1, void* ptr2, size_t len2, void* ptr3, size_t len3);
     220              : static void dlt_user_cleanup_handler(void* arg);
     221              : static int dlt_start_threads(void);
     222              : static void dlt_stop_threads(void);
     223              : static void dlt_fork_child_fork_handler(void);
     224              : #ifdef DLT_NETWORK_TRACE_ENABLE
     225              : static void* dlt_user_trace_network_segmented_thread(void* unused);
     226              : static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data* data);
     227              : #endif
     228              : 
     229              : static DltReturnValue dlt_user_log_write_string_utils_attr(
     230              :     DltContextData* log, const char* text, const enum StringType type, const char* name, bool with_var_info);
     231              : static DltReturnValue dlt_user_log_write_sized_string_utils_attr(
     232              :     DltContextData* log, const char* text, size_t length, const enum StringType type, const char* name,
     233              :     bool with_var_info);
     234              : 
     235              : 
     236              : static DltReturnValue dlt_unregister_app_util(bool force_sending_messages);
     237              : static DltReturnValue dlt_unregister_app_util_v2(bool force_sending_messages);
     238              : static int dlt_get_extendedheadersize_v2(DltUser dlt_user_param, int contextIDSize);
     239              : 
     240              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     241              : /* For trace load control feature */
     242              : static DltReturnValue dlt_user_output_internal_msg(DltLogLevelType loglevel, const char* text, void* params);
     243              : DltContext trace_load_context = {0};
     244              : DltTraceLoadSettings* trace_load_settings = NULL;
     245              : uint32_t trace_load_settings_count = 0;
     246              : pthread_rwlock_t trace_load_rw_lock = PTHREAD_RWLOCK_INITIALIZER;
     247              : #endif
     248              : 
     249              : #include <stdint.h>
     250              : 
     251              : /* Safely cast size_t to int32_t, clamp to INT32_MAX if needed */
     252              : static int32_t safe_size_to_int32(size_t val)
     253              : {
     254              :     return (val > (size_t)INT32_MAX) ? INT32_MAX : (int32_t)val;
     255              : }
     256              : 
     257            7 : DltReturnValue dlt_user_check_library_version(const char* user_major_version, const char* user_minor_version)
     258              : {
     259              :     char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
     260              :     char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
     261              : 
     262            7 :     dlt_get_major_version(lib_major_version, DLT_USER_MAX_LIB_VERSION_LENGTH);
     263            7 :     dlt_get_minor_version(lib_minor_version, DLT_USER_MAX_LIB_VERSION_LENGTH);
     264              : 
     265            7 :     if ((strcmp(lib_major_version, user_major_version) != 0) || (strcmp(lib_minor_version, user_minor_version) != 0)) {
     266            0 :         dlt_vnlog(
     267              :             LOG_WARNING, DLT_USER_BUFFER_LENGTH,
     268              :             "DLT Library version check failed! Installed DLT library version is %s.%s - Application using DLT library "
     269              :             "version %s.%s\n",
     270              :             lib_major_version, lib_minor_version, user_major_version, user_minor_version);
     271              : 
     272            0 :         return DLT_RETURN_ERROR;
     273              :     }
     274              : 
     275              :     return DLT_RETURN_OK;
     276              : }
     277              : 
     278              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
     279              : static DltReturnValue dlt_socket_set_nonblock_and_linger(int sockfd)
     280              : {
     281              :     int status;
     282              :     struct linger l_opt;
     283              : 
     284              :     status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
     285              :     if (status == -1) {
     286              :         dlt_log(LOG_INFO, "Socket cannot be changed to NON BLOCK\n");
     287              :         return DLT_RETURN_ERROR;
     288              :     }
     289              : 
     290              :     l_opt.l_onoff = 1;
     291              :     l_opt.l_linger = 10;
     292              : 
     293              :     if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &l_opt, sizeof l_opt) < 0)
     294              :         dlt_log(LOG_WARNING, "Failed to set socket linger option\n");
     295              : 
     296              :     return DLT_RETURN_OK;
     297              : }
     298              : #endif
     299              : 
     300              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
     301              : static DltReturnValue dlt_initialize_socket_connection(void)
     302              : {
     303              :     struct sockaddr_un remote;
     304              :     char dltSockBaseDir[DLT_IPC_PATH_MAX];
     305              : 
     306              :     dlt_mutex_lock();
     307              :     int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
     308              : 
     309              :     if (sockfd == DLT_FD_INIT) {
     310              :         dlt_log(LOG_CRIT, "Failed to create socket\n");
     311              :         dlt_mutex_unlock();
     312              :         return DLT_RETURN_ERROR;
     313              :     }
     314              : 
     315              :     if (dlt_socket_set_nonblock_and_linger(sockfd) != DLT_RETURN_OK) {
     316              :         close(sockfd);
     317              :         dlt_mutex_unlock();
     318              :         return DLT_RETURN_ERROR;
     319              :     }
     320              : 
     321              :     remote.sun_family = AF_UNIX;
     322              :     snprintf(dltSockBaseDir, DLT_IPC_PATH_MAX, "%s/dlt", DLT_USER_IPC_PATH);
     323              :     strncpy(remote.sun_path, dltSockBaseDir, sizeof(remote.sun_path));
     324              : 
     325              :     if (strlen(DLT_USER_IPC_PATH) > DLT_IPC_PATH_MAX)
     326              :         dlt_vlog(LOG_INFO, "Provided path too long...trimming it to path[%s]\n", dltSockBaseDir);
     327              : 
     328              :     if (connect(sockfd, (struct sockaddr*)&remote, sizeof(remote)) == -1) {
     329              :         if (dlt_user.connection_state != DLT_USER_RETRY_CONNECT) {
     330              :             dlt_vlog(LOG_INFO, "Socket %s cannot be opened (errno=%d). Retrying later...\n", dltSockBaseDir, errno);
     331              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
     332              :         }
     333              : 
     334              :         close(sockfd);
     335              :         dlt_user.dlt_log_handle = -1;
     336              :     } else {
     337              :         dlt_user.dlt_log_handle = sockfd;
     338              :         dlt_user.connection_state = DLT_USER_CONNECTED;
     339              : 
     340              :         if (dlt_receiver_init(&(dlt_user.receiver), sockfd, DLT_RECEIVE_SOCKET, DLT_USER_RCVBUF_MAX_SIZE)
     341              :             == DLT_RETURN_ERROR) {
     342              :             dlt_user_init_state = INIT_UNITIALIZED;
     343              :             close(sockfd);
     344              :             dlt_mutex_unlock();
     345              :             return DLT_RETURN_ERROR;
     346              :         }
     347              :     }
     348              : 
     349              :     dlt_mutex_unlock();
     350              :     return DLT_RETURN_OK;
     351              : }
     352              : #elif defined DLT_LIB_USE_VSOCK_IPC
     353              : static DltReturnValue dlt_initialize_vsock_connection()
     354              : {
     355              :     struct sockaddr_vm remote;
     356              : 
     357              :     dlt_mutex_lock();
     358              :     int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
     359              : 
     360              :     if (sockfd == DLT_FD_INIT) {
     361              :         dlt_log(LOG_CRIT, "Failed to create VSOCK socket\n");
     362              :         dlt_mutex_unlock();
     363              :         return DLT_RETURN_ERROR;
     364              :     }
     365              : 
     366              :     memset(&remote, 0, sizeof(remote));
     367              :     remote.svm_family = AF_VSOCK;
     368              :     remote.svm_port = DLT_VSOCK_PORT;
     369              :     remote.svm_cid = VMADDR_CID_HOST;
     370              : 
     371              :     if (connect(sockfd, (struct sockaddr*)&remote, sizeof(remote)) == -1) {
     372              :         if (dlt_user.connection_state != DLT_USER_RETRY_CONNECT) {
     373              :             dlt_vlog(LOG_INFO, "VSOCK socket cannot be opened. Retrying later...\n");
     374              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
     375              :         }
     376              : 
     377              :         close(sockfd);
     378              :         dlt_user.dlt_log_handle = -1;
     379              :     } else {
     380              :         /* Set to non-blocking after connect() to avoid EINPROGRESS. DltUserConntextionState
     381              :            needs "connecting" state if connect() should be non-blocking. */
     382              :         if (dlt_socket_set_nonblock_and_linger(sockfd) != DLT_RETURN_OK) {
     383              :             close(sockfd);
     384              :             dlt_mutex_unlock();
     385              :             return DLT_RETURN_ERROR;
     386              :         }
     387              : 
     388              :         dlt_user.dlt_log_handle = sockfd;
     389              :         dlt_user.connection_state = DLT_USER_CONNECTED;
     390              : 
     391              :         if (dlt_receiver_init(&(dlt_user.receiver), sockfd, DLT_RECEIVE_SOCKET, DLT_USER_RCVBUF_MAX_SIZE)
     392              :             == DLT_RETURN_ERROR) {
     393              :             dlt_user_init_state = INIT_UNITIALIZED;
     394              :             close(sockfd);
     395              :             dlt_mutex_unlock();
     396              :             return DLT_RETURN_ERROR;
     397              :         }
     398              :     }
     399              : 
     400              :     dlt_mutex_unlock();
     401              :     return DLT_RETURN_OK;
     402              : }
     403              : #else /* DLT_LIB_USE_FIFO_IPC */
     404        21002 : static DltReturnValue dlt_initialize_fifo_connection(void)
     405              : {
     406              :     char filename[DLT_PATH_MAX];
     407              :     int ret;
     408              : 
     409        21002 :     size_t base_dir_len = strlen(dltFifoBaseDir);
     410              : 
     411        21002 :     if (base_dir_len > DLT_PATH_MAX - 10) { /* 10 for "/dltpipes\0" */
     412            0 :         dlt_log(LOG_ERR, "FIFO base directory path too long!\n");
     413            0 :         return DLT_RETURN_ERROR;
     414              :     }
     415              : 
     416              :     ret = snprintf(dlt_user_dir, DLT_PATH_MAX, "%s/dltpipes", dltFifoBaseDir);
     417        21002 :     if (ret < 0 || ret >= DLT_PATH_MAX) {
     418            0 :         dlt_log(LOG_ERR, "Failed to construct FIFO user directory path!\n");
     419            0 :         return DLT_RETURN_ERROR;
     420              :     }
     421              : 
     422              :     ret = snprintf(dlt_daemon_fifo, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir);
     423        21002 :     if (ret < 0 || ret >= DLT_PATH_MAX) {
     424            0 :         dlt_log(LOG_ERR, "Failed to construct FIFO daemon path!\n");
     425            0 :         return DLT_RETURN_ERROR;
     426              :     }
     427              : 
     428        21002 :     ret = mkdir(dlt_user_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_ISVTX);
     429              : 
     430        21002 :     if ((ret == -1) && (errno != EEXIST)) {
     431            0 :         dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "FIFO user dir %s cannot be created!\n", dlt_user_dir);
     432            0 :         return DLT_RETURN_ERROR;
     433              :     }
     434              : 
     435              :     /* if dlt pipes directory is created by the application also chmod the directory */
     436        21002 :     if (ret == 0) {
     437              :         /* S_ISGID cannot be set by mkdir, let's reassign right bits */
     438            0 :         ret = chmod(
     439              :             dlt_user_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH
     440              :                               | S_ISGID | S_ISVTX);
     441              : 
     442            0 :         if (ret == -1) {
     443            0 :             dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "FIFO user dir %s cannot be chmoded!\n", dlt_user_dir);
     444            0 :             return DLT_RETURN_ERROR;
     445              :         }
     446              :     }
     447              : 
     448              :     /* create and open DLT user FIFO */
     449        21002 :     ret = snprintf(filename, DLT_PATH_MAX, "%s/dlt%d", dlt_user_dir, getpid());
     450        21002 :     if (ret < 0 || ret >= DLT_PATH_MAX) {
     451            0 :         dlt_log(LOG_ERR, "Failed to construct FIFO filename!\n");
     452            0 :         return DLT_RETURN_ERROR;
     453              :     }
     454              : 
     455              :     /* Try to delete existing pipe, ignore result of unlink */
     456        21002 :     unlink(filename);
     457              : 
     458        21002 :     ret = mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP);
     459              : 
     460        21002 :     if (ret == -1)
     461            0 :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Loging disabled, FIFO user %s cannot be created!\n", filename);
     462              : 
     463              :     /* S_IWGRP cannot be set by mkfifo (???), let's reassign right bits */
     464        21002 :     ret = chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP);
     465              : 
     466        21002 :     if (ret == -1) {
     467            0 :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "FIFO user %s cannot be chmoded!\n", dlt_user_dir);
     468            0 :         return DLT_RETURN_ERROR;
     469              :     }
     470              : 
     471        21002 :     dlt_user.dlt_user_handle = open(filename, O_RDWR | O_NONBLOCK | O_CLOEXEC);
     472              : 
     473        21002 :     if (dlt_user.dlt_user_handle == DLT_FD_INIT) {
     474            0 :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled, FIFO user %s cannot be opened!\n", filename);
     475            0 :         unlink(filename);
     476            0 :         return DLT_RETURN_OK;
     477              :     }
     478              : 
     479              :     /* open DLT output FIFO */
     480        21002 :     dlt_user.dlt_log_handle = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC);
     481              : 
     482        21002 :     if (dlt_user.dlt_log_handle == -1)
     483              :         /* This is a normal usecase. It is OK that the daemon (and thus the FIFO /tmp/dlt)
     484              :          * starts later and some DLT users have already been started before.
     485              :          * Thus it is OK if the FIFO can't be opened. */
     486            1 :         dlt_vnlog(LOG_INFO, DLT_USER_BUFFER_LENGTH, "FIFO %s cannot be opened. Retrying later...\n", dlt_daemon_fifo);
     487              : 
     488              :     return DLT_RETURN_OK;
     489              : }
     490              : #endif
     491              : 
     492     63474347 : DltReturnValue dlt_init(void)
     493              : {
     494              :     /* process is exiting. Do not allocate new resources. */
     495     63474347 :     if (dlt_user_freeing != 0) {
     496              : #ifndef DLT_UNIT_TESTS
     497              :         dlt_vlog(LOG_INFO, "%s logging disabled, process is exiting\n", __func__);
     498              : #endif
     499              :         /* return negative value, to stop the current log */
     500              :         return DLT_RETURN_LOGGING_DISABLED;
     501              :     }
     502              : 
     503              :     /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS.
     504              :      * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED
     505              :      * That way it's no problem, if two threads enter this function, because only the very first one will
     506              :      * pass fully. The other one will immediately return, because when it executes the atomic function
     507              :      * dlt_user_init_state won't be INIT_UNITIALIZED anymore.
     508              :      * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running.
     509              :      * Furthermore, this makes sure we enter some function only when dlt_init is fully done.
     510              :      * */
     511              :     enum InitState expectedInitState = INIT_UNITIALIZED;
     512     13555910 :     if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS))) {
     513              :         return DLT_RETURN_OK;
     514              :     }
     515              : 
     516              :     /* check environment variables */
     517        21002 :     dlt_check_envvar();
     518              : 
     519              :     /* Check logging mode and internal log file is opened or not*/
     520        21002 :     if (logging_mode == DLT_LOG_TO_FILE && logging_handle == NULL) {
     521            0 :         dlt_log_init(logging_mode);
     522              :     }
     523              : 
     524              :     /* Initialize common part of dlt_init()/dlt_init_file() */
     525        21002 :     if (dlt_init_common() == DLT_RETURN_ERROR) {
     526            0 :         dlt_user_init_state = INIT_ERROR;
     527            0 :         dlt_free();
     528            0 :         return DLT_RETURN_ERROR;
     529              :     }
     530              : 
     531        21002 :     dlt_user.dlt_is_file = 0;
     532        21002 :     dlt_user.filesize_max = UINT_MAX;
     533        21002 :     dlt_user_file_reach_max = false;
     534              : 
     535        21002 :     dlt_user.overflow = 0;
     536        21002 :     dlt_user.overflow_counter = 0;
     537              : #ifdef DLT_SHM_ENABLE
     538              :     memset(&(dlt_user.dlt_shm), 0, sizeof(DltShm));
     539              : 
     540              :     /* init shared memory */
     541              :     if (dlt_shm_init_client(&(dlt_user.dlt_shm), dltShmName) < DLT_RETURN_OK)
     542              :         dlt_vnlog(
     543              :             LOG_WARNING, DLT_USER_BUFFER_LENGTH,
     544              :             "Logging disabled,"
     545              :             " Shared memory %s cannot be created!\n",
     546              :             dltShmName);
     547              : 
     548              : #endif
     549              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     550              :     pthread_rwlock_wrlock(&trace_load_rw_lock);
     551              : 
     552              :     trace_load_settings = malloc(sizeof(DltTraceLoadSettings));
     553              :     if (trace_load_settings == NULL) {
     554              :         dlt_vlog(LOG_ERR, "Failed to allocate memory for trace load settings\n");
     555              :         dlt_user_init_state = INIT_DONE;
     556              :         pthread_rwlock_unlock(&trace_load_rw_lock);
     557              :         dlt_free();
     558              :         return DLT_RETURN_ERROR;
     559              :     }
     560              :     memset(trace_load_settings, 0, sizeof(DltTraceLoadSettings));
     561              :     trace_load_settings[0].soft_limit = DLT_TRACE_LOAD_CLIENT_SOFT_LIMIT_DEFAULT;
     562              :     trace_load_settings[0].hard_limit = DLT_TRACE_LOAD_CLIENT_HARD_LIMIT_DEFAULT;
     563              :     strncpy(trace_load_settings[0].apid, dlt_user.appID, DLT_ID_SIZE);
     564              :     trace_load_settings[0].apid2len = dlt_user.appID2len;
     565              :     strncpy(trace_load_settings[0].apid2, dlt_user.appID2, (dlt_user.appID2len) + 1);
     566              :     trace_load_settings_count = 1;
     567              : 
     568              :     pthread_rwlock_unlock(&trace_load_rw_lock);
     569              : 
     570              : #endif
     571              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
     572              : 
     573              :     if (dlt_initialize_socket_connection() != DLT_RETURN_OK) {
     574              :         /* We could connect to the pipe, but not to the socket, which is normally */
     575              :         /* open before by the DLT daemon => bad failure => return error code */
     576              :         /* in case application is started before daemon, it is expected behaviour */
     577              :         dlt_user_init_state = INIT_ERROR;
     578              :         dlt_free();
     579              :         return DLT_RETURN_ERROR;
     580              :     }
     581              : 
     582              : #elif defined DLT_LIB_USE_VSOCK_IPC
     583              : 
     584              :     if (dlt_initialize_vsock_connection() != DLT_RETURN_OK) {
     585              :         dlt_user_init_state = INIT_ERROR;
     586              :         dlt_free();
     587              :         return DLT_RETURN_ERROR;
     588              :     }
     589              : 
     590              : #else /* DLT_LIB_USE_FIFO_IPC */
     591              : 
     592        21002 :     if (dlt_initialize_fifo_connection() != DLT_RETURN_OK) {
     593            0 :         dlt_user_init_state = INIT_ERROR;
     594            0 :         dlt_free();
     595            0 :         return DLT_RETURN_ERROR;
     596              :     }
     597              : 
     598        21002 :     if (dlt_receiver_init(&(dlt_user.receiver), dlt_user.dlt_user_handle, DLT_RECEIVE_FD, DLT_USER_RCVBUF_MAX_SIZE)
     599              :         == DLT_RETURN_ERROR) {
     600            0 :         dlt_user_init_state = INIT_ERROR;
     601            0 :         dlt_free();
     602            0 :         return DLT_RETURN_ERROR;
     603              :     }
     604              : 
     605              : #endif
     606              : 
     607              : #ifdef DLT_NETWORK_TRACE_ENABLE
     608              :     /* These will be lazy initialized only when needed */
     609        21002 :     dlt_user.dlt_segmented_queue_read_handle = -1;
     610        21002 :     dlt_user.dlt_segmented_queue_write_handle = -1;
     611              : 
     612        21002 :     pthread_cond_init(&mq_init_condition, NULL);
     613              : #endif
     614              : 
     615        21002 :     if (dlt_start_threads() < 0) {
     616            0 :         dlt_user_init_state = INIT_ERROR;
     617            0 :         dlt_free();
     618            0 :         return DLT_RETURN_ERROR;
     619              :     }
     620              : 
     621              :     /* prepare for fork() call */
     622        21002 :     pthread_atfork(NULL, NULL, &dlt_fork_child_fork_handler);
     623              : 
     624        21002 :     atomic_store(&dlt_user_init_state, INIT_DONE);
     625              : 
     626        21002 :     return DLT_RETURN_OK;
     627              : }
     628              : 
     629            0 : DltReturnValue dlt_get_appid(char* appid)
     630              : {
     631            0 :     if (appid != NULL) {
     632              :         strncpy(appid, dlt_user.appID, 4);
     633            0 :         return DLT_RETURN_OK;
     634              :     } else {
     635            0 :         dlt_log(LOG_ERR, "Invalid parameter.\n");
     636            0 :         return DLT_RETURN_WRONG_PARAMETER;
     637              :     }
     638              : }
     639              : 
     640            0 : DltReturnValue dlt_get_appid_v2(char** appid)
     641              : {
     642            0 :     if (appid != NULL) {
     643            0 :         strncpy(*appid, dlt_user.appID2, dlt_user.appID2len);
     644            0 :         return DLT_RETURN_OK;
     645              :     } else {
     646            0 :         dlt_log(LOG_ERR, "Invalid parameter.\n");
     647            0 :         return DLT_RETURN_WRONG_PARAMETER;
     648              :     }
     649              : }
     650              : 
     651            0 : DltReturnValue dlt_init_file(const char* name)
     652              : {
     653              :     /* check null pointer */
     654            0 :     if (!name)
     655              :         return DLT_RETURN_WRONG_PARAMETER;
     656              : 
     657              :     /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS.
     658              :      * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED
     659              :      * That way it's no problem, if two threads enter this function, because only the very first one will
     660              :      * pass fully. The other one will immediately return, because when it executes the atomic function
     661              :      * dlt_user_init_state won't be INIT_UNITIALIZED anymore.
     662              :      * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running.
     663              :      * Furthermore, this makes sure we enter some function only when dlt_init is fully done.
     664              :      * */
     665              :     enum InitState expectedInitState = INIT_UNITIALIZED;
     666            0 :     if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS)))
     667              :         return DLT_RETURN_OK;
     668              : 
     669              :     /* Initialize common part of dlt_init()/dlt_init_file() */
     670            0 :     if (dlt_init_common() == DLT_RETURN_ERROR) {
     671              :         expectedInitState = INIT_UNITIALIZED;
     672              :         return DLT_RETURN_ERROR;
     673              :     }
     674              : 
     675            0 :     dlt_user.dlt_is_file = 1;
     676              : 
     677              :     /* open DLT output file */
     678            0 :     dlt_user.dlt_log_handle = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
     679              : 
     680            0 :     if (dlt_user.dlt_log_handle == -1) {
     681            0 :         dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "Log file %s cannot be opened!\n", name);
     682            0 :         dlt_user.dlt_is_file = 0;
     683            0 :         return DLT_RETURN_ERROR;
     684              :     }
     685            0 :     atomic_store(&dlt_user_init_state, INIT_DONE);
     686              : 
     687            0 :     return DLT_RETURN_OK;
     688              : }
     689              : 
     690            0 : DltReturnValue dlt_set_filesize_max(unsigned int filesize)
     691              : {
     692            0 :     if (dlt_user.dlt_is_file == 0) {
     693            0 :         dlt_vlog(LOG_ERR, "%s: Library is not configured to log to file\n", __func__);
     694            0 :         return DLT_RETURN_ERROR;
     695              :     }
     696              : 
     697            0 :     if (filesize == 0) {
     698            0 :         dlt_user.filesize_max = UINT_MAX;
     699              :     } else {
     700            0 :         dlt_user.filesize_max = filesize;
     701              :     }
     702            0 :     dlt_vlog(LOG_DEBUG, "%s: Defined filesize_max is [%d]\n", __func__, dlt_user.filesize_max);
     703              : 
     704            0 :     return DLT_RETURN_OK;
     705              : }
     706              : 
     707              : #ifdef DLT_NETWORK_TRACE_ENABLE
     708            0 : DltReturnValue dlt_init_message_queue(void)
     709              : {
     710            0 :     dlt_lock_mutex(&mq_mutex);
     711              : 
     712            0 :     if ((dlt_user.dlt_segmented_queue_read_handle >= 0) && (dlt_user.dlt_segmented_queue_write_handle >= 0)) {
     713              :         /* Already intialized */
     714            0 :         dlt_unlock_mutex(&mq_mutex);
     715            0 :         return DLT_RETURN_OK;
     716              :     }
     717              : 
     718              :     /* Generate per process name for queue */
     719              :     char queue_name[NAME_MAX];
     720            0 :     snprintf(queue_name, NAME_MAX, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
     721              : 
     722              :     /* Maximum queue size is 10, limit to size of pointers */
     723              :     struct mq_attr mqatr;
     724            0 :     mqatr.mq_flags = 0;
     725            0 :     mqatr.mq_maxmsg = 10;
     726            0 :     mqatr.mq_msgsize = sizeof(s_segmented_data*);
     727            0 :     mqatr.mq_curmsgs = 0;
     728              : 
     729              :     /**
     730              :      * Create the message queue. It must be newly created
     731              :      * if old one was left by a crashing process.
     732              :      * */
     733            0 :     dlt_user.dlt_segmented_queue_read_handle = mq_open(
     734              :         queue_name, O_CREAT | O_RDONLY | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
     735              : 
     736            0 :     if (dlt_user.dlt_segmented_queue_read_handle < 0) {
     737            0 :         if (errno == EEXIST) {
     738            0 :             dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
     739              : 
     740            0 :             if (mq_unlink(queue_name) < 0)
     741            0 :                 dlt_vnlog(LOG_CRIT, 256, "Could not delete existing message queue!: %s \n", strerror(errno));
     742              :             else /* Retry */
     743              : 
     744            0 :                 dlt_user.dlt_segmented_queue_read_handle = mq_open(
     745              :                     queue_name, O_CREAT | O_RDONLY | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
     746              :                     &mqatr);
     747              :         }
     748              : 
     749            0 :         if (dlt_user.dlt_segmented_queue_read_handle < 0) {
     750            0 :             dlt_vnlog(LOG_CRIT, 256, "Can't create message queue read handle!: %s \n", strerror(errno));
     751            0 :             dlt_unlock_mutex(&mq_mutex);
     752            0 :             return DLT_RETURN_ERROR;
     753              :         }
     754              :     }
     755              : 
     756            0 :     dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY | O_NONBLOCK);
     757              : 
     758            0 :     if (dlt_user.dlt_segmented_queue_write_handle < 0) {
     759            0 :         dlt_vnlog(LOG_CRIT, 256, "Can't open message queue write handle!: %s \n", strerror(errno));
     760            0 :         dlt_unlock_mutex(&mq_mutex);
     761            0 :         return DLT_RETURN_ERROR;
     762              :     }
     763              : 
     764            0 :     pthread_cond_signal(&mq_init_condition);
     765            0 :     dlt_unlock_mutex(&mq_mutex);
     766            0 :     return DLT_RETURN_OK;
     767              : }
     768              : #endif /* DLT_NETWORK_TRACE_ENABLE */
     769              : 
     770              : /* Return true if verbose mode is to be used for this DltContextData */
     771              : static inline bool is_verbose_mode(int8_t dltuser_verbose_mode, const DltContextData* log)
     772              : {
     773        11776 :     return (dltuser_verbose_mode == 1) || (log != NULL && log->verbose_mode);
     774              : }
     775              : 
     776        21003 : DltReturnValue dlt_init_common(void)
     777              : {
     778              :     char* env_local_print;
     779              :     char* env_initial_log_level;
     780              :     char* env_buffer_min;
     781              :     uint32_t buffer_min = DLT_USER_RINGBUFFER_MIN_SIZE;
     782              :     char* env_buffer_max;
     783              :     uint32_t buffer_max = DLT_USER_RINGBUFFER_MAX_SIZE;
     784              :     char* env_buffer_step;
     785              :     uint32_t buffer_step = DLT_USER_RINGBUFFER_STEP_SIZE;
     786              :     char* env_disable_extended_header_for_nonverbose;
     787              :     char* env_log_buffer_len;
     788              :     uint32_t buffer_max_configured = 0;
     789              :     uint32_t header_size = 0;
     790              : 
     791              :     // already initialized, nothing to do
     792        21003 :     if (DLT_USER_INITIALIZED) {
     793              :         return DLT_RETURN_OK;
     794              :     }
     795              : 
     796        21002 :     if ((pthread_mutexattr_init(&dlt_mutex_attr) != 0)
     797        21002 :         || (pthread_mutexattr_settype(&dlt_mutex_attr, PTHREAD_MUTEX_RECURSIVE) != 0)
     798        21002 :         || (pthread_mutex_init(&dlt_mutex, &dlt_mutex_attr) != 0)) {
     799            0 :         dlt_user_init_state = INIT_UNITIALIZED;
     800            0 :         return DLT_RETURN_ERROR;
     801              :     }
     802              : 
     803              :     /* set to unknown state of connected client */
     804        21002 :     dlt_user.log_state = -1;
     805              : 
     806              :     /* set pid cache to none until we need it */
     807        21002 :     dlt_user.local_pid = -1;
     808              : 
     809        21002 :     dlt_user.dlt_log_handle = -1;
     810        21002 :     dlt_user.dlt_user_handle = DLT_FD_INIT;
     811              : 
     812              :     size_t ecu_len = strlen(DLT_USER_DEFAULT_ECU_ID);
     813              :     if (ecu_len > UINT8_MAX) {
     814              :         ecu_len = UINT8_MAX;
     815              :     }
     816        21002 :     dlt_set_id(dlt_user.ecuID, DLT_USER_DEFAULT_ECU_ID);
     817        21002 :     dlt_user.ecuID2len = (uint8_t)ecu_len;
     818        21002 :     dlt_set_id_v2(dlt_user.ecuID2, DLT_USER_DEFAULT_ECU_ID, dlt_user.ecuID2len);
     819        21002 :     dlt_set_id(dlt_user.appID, "");
     820        21002 :     dlt_user.appID2len = 0;
     821              :     memset(dlt_user.appID2, 0, DLT_V2_ID_SIZE);
     822        21002 :     dlt_user.application_description = NULL;
     823        21002 :     dlt_user.filenamelen = 0;
     824        21002 :     dlt_user.filename = NULL;
     825        21002 :     dlt_user.linenumber = 0;
     826        21002 :     dlt_user.numberoftags = 0;
     827        21002 :     dlt_user.prlv = 0;
     828        21002 :     dlt_user.tag = NULL;
     829        21002 :     dlt_user.tagbuffersize = 0;
     830              : 
     831              :     /* Verbose mode is enabled by default */
     832        21002 :     dlt_user.verbose_mode = 1;
     833              : 
     834              :     /* header_size is used for resend buffer
     835              :      * so it won't include DltStorageHeader
     836              :      */
     837              :     header_size = sizeof(DltUserHeader) + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra);
     838              : 
     839              :     /* Use extended header for non verbose is enabled by default */
     840        21002 :     dlt_user.use_extended_header_for_non_verbose = DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE;
     841              : 
     842              :     /* Use extended header for non verbose is modified as per environment variable */
     843        21002 :     env_disable_extended_header_for_nonverbose = getenv(DLT_USER_ENV_DISABLE_EXTENDED_HEADER_FOR_NONVERBOSE);
     844              : 
     845        21002 :     if (env_disable_extended_header_for_nonverbose) {
     846            0 :         if (strcmp(env_disable_extended_header_for_nonverbose, "1") == 0)
     847            0 :             dlt_user.use_extended_header_for_non_verbose = DLT_USER_NO_USE_EXTENDED_HEADER_FOR_NONVERBOSE;
     848              :     }
     849              : 
     850        21002 :     if (dlt_user.use_extended_header_for_non_verbose == DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE)
     851              :         header_size += (uint32_t)sizeof(DltExtendedHeader);
     852              : 
     853              :     /* With session id is enabled by default */
     854        21002 :     dlt_user.with_session_id = DLT_USER_WITH_SESSION_ID;
     855              : 
     856              :     /* With timestamp is enabled by default */
     857        21002 :     dlt_user.with_timestamp = DLT_USER_WITH_TIMESTAMP;
     858              : 
     859              :     /* With timestamp is enabled by default */
     860        21002 :     dlt_user.with_ecu_id = DLT_USER_WITH_ECU_ID;
     861              : 
     862              :     /* With app and context id is enabled by default */
     863        21002 :     dlt_user.with_app_and_context_id = DLT_USER_WITH_APP_AND_CONTEXT_ID;
     864              : 
     865              :     /* With filename and line number is disabled by default */
     866        21002 :     dlt_user.with_filename_and_line_number = DLT_USER_WITH_FILENAME_AND_LINE_NUMBER;
     867              : 
     868              :     /* With tags is disabled by default */
     869        21002 :     dlt_user.with_tags = DLT_USER_WITH_TAGS;
     870              : 
     871              :     /* With privacy level is disabled by default */
     872        21002 :     dlt_user.with_privacy_level = DLT_USER_WITH_PRIVACY_LEVEL;
     873              : 
     874              :     /* With segmentation is disabled by default */
     875        21002 :     dlt_user.with_segmentation = DLT_USER_WITH_SEGMENTATION;
     876              : 
     877              :     /* Local print is disabled by default */
     878        21002 :     dlt_user.enable_local_print = 0;
     879              : 
     880        21002 :     dlt_user.local_print_mode = DLT_PM_UNSET;
     881              : 
     882        21002 :     dlt_user.timeout_at_exit_handler = DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
     883              : 
     884        21002 :     env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
     885              : 
     886        21002 :     if (env_local_print) {
     887            0 :         if (strcmp(env_local_print, "AUTOMATIC") == 0)
     888            0 :             dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
     889            0 :         else if (strcmp(env_local_print, "FORCE_ON") == 0)
     890            0 :             dlt_user.local_print_mode = DLT_PM_FORCE_ON;
     891            0 :         else if (strcmp(env_local_print, "FORCE_OFF") == 0)
     892            0 :             dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
     893              :     }
     894              : 
     895        21002 :     env_initial_log_level = getenv("DLT_INITIAL_LOG_LEVEL");
     896              : 
     897        21002 :     if (env_initial_log_level != NULL) {
     898            0 :         if (dlt_env_extract_ll_set(&env_initial_log_level, &dlt_user.initial_ll_set) != 0)
     899            0 :             dlt_vlog(
     900              :                 LOG_WARNING, "Unable to parse initial set of log-levels from environment! Env:\n%s\n",
     901              :                 getenv("DLT_INITIAL_LOG_LEVEL"));
     902              :     }
     903              : 
     904              :     /* Initialize LogLevel/TraceStatus field */
     905        21002 :     dlt_mutex_lock();
     906        21002 :     dlt_user.dlt_ll_ts = NULL;
     907        21002 :     dlt_user.dlt_ll_ts_max_num_entries = 0;
     908        21002 :     dlt_user.dlt_ll_ts_num_entries = 0;
     909              : 
     910        21002 :     env_buffer_min = getenv(DLT_USER_ENV_BUFFER_MIN_SIZE);
     911        21002 :     env_buffer_max = getenv(DLT_USER_ENV_BUFFER_MAX_SIZE);
     912        21002 :     env_buffer_step = getenv(DLT_USER_ENV_BUFFER_STEP_SIZE);
     913              : 
     914        21002 :     if (env_buffer_min != NULL) {
     915            0 :         buffer_min = (uint32_t)strtol(env_buffer_min, NULL, 10);
     916              : 
     917            0 :         if ((errno == EINVAL) || (errno == ERANGE)) {
     918            0 :             dlt_vlog(LOG_ERR, "Wrong value specified for %s. Using default\n", DLT_USER_ENV_BUFFER_MIN_SIZE);
     919              :             buffer_min = DLT_USER_RINGBUFFER_MIN_SIZE;
     920              :         }
     921              :     }
     922              : 
     923        21002 :     if (env_buffer_max != NULL) {
     924            0 :         buffer_max = (uint32_t)strtol(env_buffer_max, NULL, 10);
     925              : 
     926            0 :         if ((errno == EINVAL) || (errno == ERANGE)) {
     927            0 :             dlt_vlog(LOG_ERR, "Wrong value specified for %s. Using default\n", DLT_USER_ENV_BUFFER_MAX_SIZE);
     928              :             buffer_max = DLT_USER_RINGBUFFER_MAX_SIZE;
     929              :         }
     930              :     }
     931              : 
     932        21002 :     if (env_buffer_step != NULL) {
     933            0 :         buffer_step = (uint32_t)strtol(env_buffer_step, NULL, 10);
     934              : 
     935            0 :         if ((errno == EINVAL) || (errno == ERANGE)) {
     936            0 :             dlt_vlog(LOG_ERR, "Wrong value specified for %s. Using default\n", DLT_USER_ENV_BUFFER_STEP_SIZE);
     937              :             buffer_step = DLT_USER_RINGBUFFER_STEP_SIZE;
     938              :         }
     939              :     }
     940              : 
     941              :     /* init log buffer size */
     942        21002 :     dlt_user.log_buf_len = DLT_USER_BUF_MAX_SIZE;
     943        21002 :     env_log_buffer_len = getenv(DLT_USER_ENV_LOG_MSG_BUF_LEN);
     944              : 
     945        21002 :     if (env_log_buffer_len != NULL) {
     946            7 :         buffer_max_configured = (uint32_t)strtol(env_log_buffer_len, NULL, 10);
     947              : 
     948            7 :         if (buffer_max_configured > DLT_LOG_MSG_BUF_MAX_SIZE) {
     949            0 :             dlt_user.log_buf_len = DLT_LOG_MSG_BUF_MAX_SIZE;
     950            0 :             dlt_vlog(LOG_WARNING, "Configured size exceeds maximum allowed size,restricting to max [65535 bytes]\n");
     951              :         } else {
     952            7 :             dlt_user.log_buf_len = (uint16_t)buffer_max_configured;
     953            7 :             dlt_vlog(LOG_INFO, "Configured buffer size to [%u bytes]\n", buffer_max_configured);
     954              :         }
     955              :     }
     956              : 
     957        21002 :     if (dlt_user.resend_buffer == NULL) {
     958        21002 :         dlt_user.resend_buffer = calloc((dlt_user.log_buf_len + header_size), sizeof(unsigned char));
     959              : 
     960        21002 :         if (dlt_user.resend_buffer == NULL) {
     961            0 :             dlt_user_init_state = INIT_UNITIALIZED;
     962            0 :             dlt_vlog(LOG_ERR, "cannot allocate memory for resend buffer\n");
     963            0 :             dlt_mutex_unlock();
     964            0 :             return DLT_RETURN_ERROR;
     965              :         }
     966              :     }
     967              : 
     968        21002 :     dlt_user.disable_injection_msg = 0;
     969        21002 :     if (getenv(DLT_USER_ENV_DISABLE_INJECTION_MSG)) {
     970            0 :         dlt_log(LOG_WARNING, "Injection message is disabled\n");
     971            0 :         dlt_user.disable_injection_msg = 1;
     972              :     }
     973              : 
     974        21002 :     if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer), buffer_min, buffer_max, buffer_step) == DLT_RETURN_ERROR) {
     975            0 :         dlt_user_init_state = INIT_UNITIALIZED;
     976            0 :         dlt_mutex_unlock();
     977            0 :         return DLT_RETURN_ERROR;
     978              :     }
     979              : 
     980        21002 :     dlt_mutex_unlock();
     981        21002 :     signal(SIGPIPE, SIG_IGN); /* ignore pipe signals */
     982              : 
     983        21002 :     if (atexit_registered == 0) {
     984            9 :         atexit_registered = 1;
     985            9 :         atexit(dlt_user_atexit_handler);
     986              :     }
     987              : 
     988              : #ifdef DLT_TEST_ENABLE
     989              :     dlt_user.corrupt_user_header = 0;
     990              :     dlt_user.corrupt_message_size = 0;
     991              :     dlt_user.corrupt_message_size_size = 0;
     992              : #endif
     993              : 
     994              :     return DLT_RETURN_OK;
     995              : }
     996              : 
     997            9 : void dlt_user_atexit_handler(void)
     998              : {
     999              :     /* Signal housekeeper thread to exit */
    1000            9 :     dlt_user_housekeeper_exit_requested = true;
    1001              :     /* parent will do clean-up */
    1002            9 :     if (g_dlt_is_child)
    1003              :         return;
    1004              : 
    1005            9 :     if (!DLT_USER_INITIALIZED) {
    1006            1 :         dlt_vlog(
    1007              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    1008            1 :             dlt_user_init_state, dlt_user_freeing);
    1009              :         /* close file */
    1010            1 :         dlt_log_free();
    1011            1 :         return;
    1012              :     }
    1013              : 
    1014              :     /* Try to resend potential log messages in the user buffer */
    1015            8 :     int count = dlt_user_atexit_blow_out_user_buffer();
    1016              : 
    1017            8 :     if (count != 0)
    1018            2 :         dlt_vnlog(LOG_WARNING, 128, "Lost log messages in user buffer when exiting: %i\n", count);
    1019              : 
    1020              :     /* Unregister app (this also unregisters all contexts in daemon) */
    1021              :     /* Ignore return value */
    1022            8 :     dlt_unregister_app_util(false);
    1023              : 
    1024              :     /* Cleanup */
    1025              :     /* Ignore return value */
    1026            8 :     dlt_free();
    1027              : 
    1028              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1029              :     pthread_rwlock_destroy(&trace_load_rw_lock);
    1030              : #endif
    1031              : }
    1032              : 
    1033            8 : int dlt_user_atexit_blow_out_user_buffer(void)
    1034              : {
    1035              :     int count, ret;
    1036              :     struct timespec ts;
    1037              : 
    1038            8 :     uint32_t exitTime = dlt_uptime() + dlt_user.timeout_at_exit_handler;
    1039              : 
    1040              :     /* Send content of ringbuffer */
    1041            8 :     dlt_mutex_lock();
    1042            8 :     count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1043            8 :     dlt_mutex_unlock();
    1044              : 
    1045            8 :     if (count > 0) {
    1046            2 :         while (dlt_uptime() < exitTime) {
    1047            1 :             if (dlt_user.dlt_log_handle == -1) {
    1048              :                 /* Reattach to daemon if neccesary */
    1049            0 :                 dlt_user_log_reattach_to_daemon();
    1050              : 
    1051            0 :                 if ((dlt_user.dlt_log_handle != -1) && (dlt_user.overflow_counter)) {
    1052            0 :                     if (dlt_user_log_send_overflow() == 0) {
    1053            0 :                         dlt_vnlog(
    1054              :                             LOG_WARNING, DLT_USER_BUFFER_LENGTH, "%u messages discarded!\n", dlt_user.overflow_counter);
    1055            0 :                         dlt_user.overflow_counter = 0;
    1056              :                     }
    1057              :                 }
    1058              :             }
    1059              : 
    1060            1 :             if (dlt_user.dlt_log_handle != -1) {
    1061            1 :                 ret = dlt_user_log_resend_buffer();
    1062              : 
    1063            1 :                 if (ret == 0) {
    1064            1 :                     dlt_mutex_lock();
    1065            1 :                     count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1066            1 :                     dlt_mutex_unlock();
    1067              : 
    1068            1 :                     return count;
    1069              :                 }
    1070              :             }
    1071              : 
    1072            0 :             ts.tv_sec = 0;
    1073            0 :             ts.tv_nsec = DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP;
    1074            0 :             nanosleep(&ts, NULL);
    1075              :         }
    1076              : 
    1077            1 :         dlt_mutex_lock();
    1078            1 :         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1079            1 :         dlt_mutex_unlock();
    1080              :     }
    1081              : 
    1082              :     return count;
    1083              : }
    1084              : 
    1085              : static void dlt_user_free_buffer(unsigned char** buffer)
    1086              : {
    1087        27042 :     if (*buffer) {
    1088           23 :         free(*buffer);
    1089        27022 :         *buffer = NULL;
    1090              :     }
    1091              : }
    1092              : 
    1093        63261 : DltReturnValue dlt_free(void)
    1094              : {
    1095              :     uint32_t i;
    1096              :     int ret = 0;
    1097              :     int expected = 0;
    1098              : #ifdef DLT_LIB_USE_FIFO_IPC
    1099              :     char filename[DLT_PATH_MAX];
    1100              : #endif
    1101              : 
    1102              :     /* library is freeing its resources. Avoid to allocate it in dlt_init() */
    1103        63261 :     if (!(atomic_compare_exchange_strong(&dlt_user_freeing, &expected, 1))) {
    1104              :         /* resources are already being freed. Do nothing and return. */
    1105              :         return DLT_RETURN_ERROR;
    1106              :     }
    1107              : 
    1108              :     // no need to free when not initialized and no error occurred.
    1109              :     // on error some resources might have been allocated, so free them.
    1110        63261 :     if (!DLT_USER_INITIALIZED && !DLT_USER_INIT_ERROR) {
    1111        42259 :         dlt_user_freeing = 0;
    1112        42259 :         return DLT_RETURN_ERROR;
    1113              :     }
    1114              : 
    1115        21002 :     dlt_mutex_lock();
    1116              : 
    1117        21002 :     dlt_stop_threads();
    1118              : 
    1119        21002 :     dlt_user_init_state = INIT_UNITIALIZED;
    1120              : 
    1121              : #ifdef DLT_LIB_USE_FIFO_IPC
    1122              : 
    1123        21002 :     if (dlt_user.dlt_user_handle != DLT_FD_INIT) {
    1124              :         int ret_fifo;
    1125        21002 :         close(dlt_user.dlt_user_handle);
    1126        21002 :         dlt_user.dlt_user_handle = DLT_FD_INIT;
    1127        21002 :         ret_fifo = snprintf(filename, DLT_PATH_MAX, "%s/dlt%d", dlt_user_dir, getpid());
    1128        21002 :         if (ret_fifo >= 0 && ret_fifo < DLT_PATH_MAX) {
    1129        21002 :             unlink(filename);
    1130              :         }
    1131              :     }
    1132              : 
    1133              : #endif
    1134              : 
    1135              : #ifdef DLT_SHM_ENABLE
    1136              :     /* free shared memory */
    1137              :     dlt_shm_free_client(&dlt_user.dlt_shm);
    1138              : #endif
    1139              : 
    1140        21002 :     if (dlt_user.dlt_log_handle != -1) {
    1141              :         /* close log file/output fifo to daemon */
    1142              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    1143              :         ret = shutdown(dlt_user.dlt_log_handle, SHUT_WR);
    1144              : 
    1145              :         if (ret < 0) {
    1146              :             dlt_vlog(LOG_WARNING, "%s: shutdown failed: %s\n", __func__, strerror(errno));
    1147              :         } else {
    1148              :             ssize_t bytes_read = 0;
    1149              :             int prev_errno = 0;
    1150              :             struct pollfd nfd[1];
    1151              :             nfd[0].events = POLLIN;
    1152              :             nfd[0].fd = dlt_user.dlt_log_handle;
    1153              : 
    1154              :             while (1) {
    1155              :                 ret = poll(nfd, 1, DLT_USER_RECEIVE_MDELAY);
    1156              : 
    1157              :                 /* In case failure of polling or reaching timeout,
    1158              :                  * continue to close socket anyway.
    1159              :                  * */
    1160              :                 if (ret < 0) {
    1161              :                     dlt_vlog(LOG_WARNING, "[%s] Failed to poll with error [%s]\n", __func__, strerror(errno));
    1162              :                     break;
    1163              :                 } else if (ret == 0) {
    1164              :                     dlt_vlog(LOG_DEBUG, "[%s] Polling timeout\n", __func__);
    1165              :                     break;
    1166              :                 } else {
    1167              :                     /* It could take some time to get the socket is shutdown
    1168              :                      * So it means there could be some data available to read.
    1169              :                      * Try to consume the data and poll the socket again.
    1170              :                      * If read fails, time to close the socket then.
    1171              :                      */
    1172              :                     dlt_vlog(
    1173              :                         LOG_DEBUG,
    1174              :                         "[%s] polling returns [%d] with revent [0x%x]."
    1175              :                         "There are something to read\n",
    1176              :                         __func__, ret, (unsigned int)nfd[0].revents);
    1177              : 
    1178              :                     bytes_read = read(dlt_user.dlt_log_handle, dlt_user.resend_buffer, dlt_user.log_buf_len);
    1179              :                     prev_errno = errno;
    1180              : 
    1181              :                     if (bytes_read < 0) {
    1182              :                         dlt_vlog(LOG_WARNING, "[%s] Failed to read with error [%s]\n", __func__, strerror(prev_errno));
    1183              : 
    1184              :                         if ((prev_errno == EAGAIN) || (EWOULDBLOCK != EAGAIN && prev_errno == EWOULDBLOCK))
    1185              :                             continue;
    1186              :                         else
    1187              :                             break;
    1188              :                     }
    1189              :                     if (bytes_read >= 0) {
    1190              :                         dlt_vlog(
    1191              :                             LOG_DEBUG, "%s - %d: %d bytes read from resend buffer\n", __func__, __LINE__,
    1192              :                             (int)bytes_read);
    1193              :                         if (!bytes_read)
    1194              :                             break;
    1195              :                         dlt_vlog(LOG_NOTICE, "[%s] data is still readable... [%zd] bytes read\n", __func__, bytes_read);
    1196              :                     }
    1197              :                 }
    1198              :             }
    1199              :         }
    1200              : 
    1201              : #endif
    1202        21001 :         ret = close(dlt_user.dlt_log_handle);
    1203              : 
    1204        21001 :         if (ret < 0)
    1205            0 :             dlt_vlog(LOG_WARNING, "%s: close failed: %s\n", __func__, strerror(errno));
    1206              : 
    1207        21001 :         dlt_user.dlt_log_handle = -1;
    1208              :     }
    1209              : 
    1210        21002 :     dlt_mutex_lock();
    1211        21002 :     (void)dlt_receiver_free(&(dlt_user.receiver));
    1212        21002 :     dlt_mutex_unlock();
    1213              : 
    1214              :     dlt_user_free_buffer(&(dlt_user.resend_buffer));
    1215              : 
    1216        21002 :     dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
    1217              : 
    1218              :     /* Clear and free local stored application information */
    1219        21002 :     if (dlt_user.application_description != NULL)
    1220            0 :         free(dlt_user.application_description);
    1221        21002 :     dlt_user.application_description = NULL;
    1222              : 
    1223              :     /* free filename if set */
    1224        21002 :     if (dlt_user.filename != NULL) {
    1225            0 :         free(dlt_user.filename);
    1226            0 :         dlt_user.filename = NULL;
    1227            0 :         dlt_user.filenamelen = 0;
    1228              :     }
    1229              : 
    1230              :     /* free tags (tag names are stored inside DltTag.fixed-size buffer) */
    1231        21002 :     if (dlt_user.tag != NULL) {
    1232            0 :         free(dlt_user.tag);
    1233            0 :         dlt_user.tag = NULL;
    1234            0 :         dlt_user.numberoftags = 0;
    1235            0 :         dlt_user.tagbuffersize = 0;
    1236              :     }
    1237              : 
    1238        21002 :     if (dlt_user.dlt_ll_ts) {
    1239        11022 :         for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1240        11000 :             if (dlt_user.dlt_ll_ts[i].context_description != NULL) {
    1241            2 :                 free(dlt_user.dlt_ll_ts[i].context_description);
    1242            2 :                 dlt_user.dlt_ll_ts[i].context_description = NULL;
    1243              :             }
    1244              : 
    1245        11000 :             if (dlt_user.dlt_ll_ts[i].log_level_ptr != NULL) {
    1246            2 :                 free(dlt_user.dlt_ll_ts[i].log_level_ptr);
    1247            2 :                 dlt_user.dlt_ll_ts[i].log_level_ptr = NULL;
    1248              :             }
    1249              : 
    1250        11000 :             if (dlt_user.dlt_ll_ts[i].trace_status_ptr != NULL) {
    1251            2 :                 free(dlt_user.dlt_ll_ts[i].trace_status_ptr);
    1252            2 :                 dlt_user.dlt_ll_ts[i].trace_status_ptr = NULL;
    1253              :             }
    1254              : 
    1255        11000 :             if (dlt_user.dlt_ll_ts[i].injection_table != NULL) {
    1256            0 :                 free(dlt_user.dlt_ll_ts[i].injection_table);
    1257            0 :                 dlt_user.dlt_ll_ts[i].injection_table = NULL;
    1258              :             }
    1259              : 
    1260        11000 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1261        11000 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0;
    1262              :         }
    1263              : 
    1264           22 :         free(dlt_user.dlt_ll_ts);
    1265           22 :         dlt_user.dlt_ll_ts = NULL;
    1266           22 :         dlt_user.dlt_ll_ts_max_num_entries = 0;
    1267           22 :         dlt_user.dlt_ll_ts_num_entries = 0;
    1268              :     }
    1269              : 
    1270        21002 :     dlt_env_free_ll_set(&dlt_user.initial_ll_set);
    1271              : 
    1272              : #ifdef DLT_NETWORK_TRACE_ENABLE
    1273              :     char queue_name[NAME_MAX];
    1274        21002 :     snprintf(queue_name, NAME_MAX, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
    1275              : 
    1276              :     /**
    1277              :      * Ignore errors from these, to not to spam user if dlt_free
    1278              :      * is accidentally called multiple times.
    1279              :      */
    1280        21002 :     if (dlt_user.dlt_segmented_queue_write_handle > 0)
    1281            0 :         (void)mq_close(dlt_user.dlt_segmented_queue_write_handle);
    1282              : 
    1283        21002 :     if (dlt_user.dlt_segmented_queue_read_handle > 0)
    1284            0 :         (void)mq_close(dlt_user.dlt_segmented_queue_read_handle);
    1285        21002 :     if ((dlt_user.dlt_segmented_queue_write_handle > 0) || (dlt_user.dlt_segmented_queue_read_handle > 0))
    1286            0 :         (void)mq_unlink(queue_name);
    1287              : 
    1288        21002 :     dlt_user.dlt_segmented_queue_write_handle = DLT_FD_INIT;
    1289        21002 :     dlt_user.dlt_segmented_queue_read_handle = DLT_FD_INIT;
    1290              : 
    1291        21002 :     pthread_cond_destroy(&mq_init_condition);
    1292              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    1293              : 
    1294              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1295              :     if (trace_load_settings != NULL) {
    1296              :         free(trace_load_settings);
    1297              :         trace_load_settings = NULL;
    1298              :     }
    1299              :     trace_load_settings_count = 0;
    1300              : #endif
    1301        21002 :     dlt_mutex_unlock();
    1302        21002 :     pthread_mutex_destroy(&dlt_mutex);
    1303              : 
    1304              :     /* allow the user app to do dlt_init() again. */
    1305              :     /* The flag is unset only to keep almost the same behaviour as before, on EntryNav */
    1306              :     /* This should be removed for other projects (see documentation of dlt_free() */
    1307        21002 :     dlt_user_freeing = 0;
    1308              : 
    1309        21002 :     return DLT_RETURN_OK;
    1310              : }
    1311              : 
    1312            7 : DltReturnValue dlt_check_library_version(const char* user_major_version, const char* user_minor_version)
    1313              : {
    1314            7 :     return dlt_user_check_library_version(user_major_version, user_minor_version);
    1315              : }
    1316              : 
    1317          176 : DltReturnValue dlt_register_app(const char* apid, const char* description)
    1318              : {
    1319              :     DltReturnValue ret = DLT_RETURN_OK;
    1320              : 
    1321              :     /* forbid dlt usage in child after fork */
    1322          176 :     if (g_dlt_is_child)
    1323              :         return DLT_RETURN_ERROR;
    1324              : 
    1325          176 :     if (!DLT_USER_INITIALIZED) {
    1326            8 :         if (dlt_init() < 0) {
    1327            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    1328            0 :             return DLT_RETURN_ERROR;
    1329              :         }
    1330              :     }
    1331              : 
    1332          176 :     if ((apid == NULL) || (apid[0] == '\0'))
    1333              :         return DLT_RETURN_WRONG_PARAMETER;
    1334              : 
    1335              :     /* check if application already registered */
    1336              :     /* if yes do not register again */
    1337          172 :     if (apid[1] == 0) {
    1338            2 :         if (apid[0] == dlt_user.appID[0])
    1339              :             return DLT_RETURN_OK;
    1340          170 :     } else if (apid[2] == 0) {
    1341            2 :         if ((apid[0] == dlt_user.appID[0]) && (apid[1] == dlt_user.appID[1]))
    1342              :             return DLT_RETURN_OK;
    1343          168 :     } else if (apid[3] == 0) {
    1344            2 :         if ((apid[0] == dlt_user.appID[0]) && (apid[1] == dlt_user.appID[1]) && (apid[2] == dlt_user.appID[2]))
    1345              :             return DLT_RETURN_OK;
    1346          166 :     } else if (
    1347          166 :         (apid[0] == dlt_user.appID[0]) && (apid[1] == dlt_user.appID[1]) && (apid[2] == dlt_user.appID[2])
    1348            1 :         && (apid[3] == dlt_user.appID[3])) {
    1349              :         return DLT_RETURN_OK;
    1350              :     }
    1351              : 
    1352          171 :     dlt_mutex_lock();
    1353              : 
    1354              :     /* Store locally application id and application description */
    1355          171 :     dlt_set_id(dlt_user.appID, apid);
    1356              : 
    1357          171 :     if (dlt_user.application_description != NULL)
    1358            0 :         free(dlt_user.application_description);
    1359              : 
    1360          171 :     dlt_user.application_description = NULL;
    1361              : 
    1362          171 :     if (description != NULL) {
    1363          171 :         size_t desc_len = strlen(description);
    1364          171 :         dlt_user.application_description = malloc(desc_len + 1);
    1365              : 
    1366          171 :         if (dlt_user.application_description) {
    1367              :             strncpy(dlt_user.application_description, description, desc_len + 1);
    1368              :         } else {
    1369            0 :             dlt_mutex_unlock();
    1370            0 :             return DLT_RETURN_ERROR;
    1371              :         }
    1372              :     }
    1373              : 
    1374          171 :     dlt_mutex_unlock();
    1375              : 
    1376              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1377              :     pthread_rwlock_wrlock(&trace_load_rw_lock);
    1378              :     strncpy(trace_load_settings[0].apid, dlt_user.appID, DLT_ID_SIZE);
    1379              :     pthread_rwlock_unlock(&trace_load_rw_lock);
    1380              :     if (!trace_load_context.contextID[0]) {
    1381              :         // Register Special Context ID for output DLT library internal message
    1382              :         ret = dlt_register_context(&trace_load_context, DLT_TRACE_LOAD_CONTEXT_ID, "DLT user library internal context");
    1383              :         if (ret < DLT_RETURN_OK) {
    1384              :             return ret;
    1385              :         }
    1386              :     }
    1387              : #endif
    1388              : 
    1389          171 :     ret = dlt_user_log_send_register_application();
    1390              : 
    1391          171 :     if ((ret == DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1))
    1392          171 :         ret = dlt_user_log_resend_buffer();
    1393              : 
    1394              :     return ret;
    1395              : }
    1396              : 
    1397           25 : DltReturnValue dlt_register_app_v2(const char* apid, const char* description)
    1398              : {
    1399              :     DltReturnValue ret = DLT_RETURN_OK;
    1400              :     /* forbid dlt usage in child after fork */
    1401           25 :     if (g_dlt_is_child)
    1402              :         return DLT_RETURN_ERROR;
    1403              : 
    1404           25 :     if (!DLT_USER_INITIALIZED) {
    1405            0 :         if (dlt_init() < 0) {
    1406            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    1407            0 :             return DLT_RETURN_ERROR;
    1408              :         }
    1409              :     }
    1410              : 
    1411              :     /* validate apid pointer and length before using it */
    1412           25 :     if (apid == NULL)
    1413              :         return DLT_RETURN_WRONG_PARAMETER;
    1414              : 
    1415           25 :     size_t apidlen_sz = strlen(apid);
    1416           25 :     if (apidlen_sz == 0)
    1417              :         return DLT_RETURN_WRONG_PARAMETER;
    1418           25 :     if (apidlen_sz > INT8_MAX) {
    1419              :         return DLT_RETURN_WRONG_PARAMETER;
    1420              :     }
    1421           25 :     uint8_t apidlen = (uint8_t)apidlen_sz;
    1422              : 
    1423           25 :     if (dlt_user.appID2len != 0) {
    1424            1 :         if (!strncmp(apid, dlt_user.appID2, (size_t)apidlen)) {
    1425              :             return DLT_RETURN_OK;
    1426              :         }
    1427              :     }
    1428              : 
    1429           24 :     dlt_mutex_lock();
    1430              : 
    1431              :     /* Store locally application id and application description */
    1432           24 :     dlt_set_id_v2(dlt_user.appID2, apid, apidlen);
    1433           24 :     dlt_user.appID2len = apidlen;
    1434           24 :     if (dlt_user.application_description != NULL)
    1435            0 :         free(dlt_user.application_description);
    1436              : 
    1437           24 :     dlt_user.application_description = NULL;
    1438              : 
    1439           24 :     if (description != NULL) {
    1440           24 :         size_t desc_len = strlen(description);
    1441           24 :         dlt_user.application_description = malloc(desc_len + 1);
    1442           24 :         if (dlt_user.application_description) {
    1443              :             strncpy(dlt_user.application_description, description, desc_len + 1);
    1444              :         } else {
    1445            0 :             dlt_mutex_unlock();
    1446            0 :             return DLT_RETURN_ERROR;
    1447              :         }
    1448              :     }
    1449              : 
    1450           24 :     dlt_mutex_unlock();
    1451              : 
    1452              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1453              :     strncpy(trace_load_settings[0].apid2, dlt_user.appID2, dlt_user.appID2len);
    1454              :     trace_load_settings[0].apid2len = dlt_user.appID2len;
    1455              : #endif
    1456              : 
    1457           24 :     ret = dlt_user_log_send_register_application_v2();
    1458              : 
    1459           24 :     if ((ret == DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1))
    1460            0 :         ret = dlt_user_log_resend_buffer();
    1461              : 
    1462              :     return ret;
    1463              : }
    1464              : 
    1465          203 : DltReturnValue dlt_register_context(DltContext* handle, const char* contextid, const char* description)
    1466              : {
    1467              :     /* check nullpointer */
    1468          203 :     if (handle == NULL)
    1469              :         return DLT_RETURN_WRONG_PARAMETER;
    1470              : 
    1471              :     /* forbid dlt usage in child after fork */
    1472          197 :     if (g_dlt_is_child)
    1473              :         return DLT_RETURN_ERROR;
    1474              : 
    1475          197 :     if (!DLT_USER_INITIALIZED) {
    1476            0 :         if (dlt_init() < 0) {
    1477            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    1478            0 :             return DLT_RETURN_ERROR;
    1479              :         }
    1480              :     }
    1481              : 
    1482          197 :     if ((contextid == NULL) || (contextid[0] == '\0'))
    1483              :         return DLT_RETURN_WRONG_PARAMETER;
    1484              : 
    1485          189 :     return dlt_register_context_ll_ts(
    1486              :         handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
    1487              : }
    1488              : 
    1489           27 : DltReturnValue dlt_register_context_v2(DltContext* handle, const char* contextid, const char* description)
    1490              : {
    1491              :     /* check nullpointer */
    1492           27 :     if (handle == NULL)
    1493              :         return DLT_RETURN_WRONG_PARAMETER;
    1494              : 
    1495              :     /* forbid dlt usage in child after fork */
    1496           24 :     if (g_dlt_is_child)
    1497              :         return DLT_RETURN_ERROR;
    1498              : 
    1499           24 :     if (!DLT_USER_INITIALIZED) {
    1500            0 :         if (dlt_init() < 0) {
    1501            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    1502            0 :             return DLT_RETURN_ERROR;
    1503              :         }
    1504              :     }
    1505              : 
    1506           24 :     if (contextid == NULL) {
    1507              :         return DLT_RETURN_WRONG_PARAMETER;
    1508              :     }
    1509           22 :     size_t contextidlen_sz = strlen(contextid);
    1510           22 :     if (contextidlen_sz > INT8_MAX) {
    1511              :         return DLT_RETURN_WRONG_PARAMETER;
    1512              :     }
    1513              : 
    1514           22 :     return dlt_register_context_ll_ts_v2(
    1515              :         handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
    1516              : }
    1517              : 
    1518          216 : DltReturnValue dlt_register_context_ll_ts_llccb(
    1519              :     DltContext* handle, const char* contextid, const char* description, int loglevel, int tracestatus,
    1520              :     void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status))
    1521              : {
    1522              :     DltContextData log;
    1523              :     uint32_t i;
    1524              :     int envLogLevel = DLT_USER_LOG_LEVEL_NOT_SET;
    1525              : 
    1526              :     /*check nullpointer */
    1527          216 :     if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0'))
    1528              :         return DLT_RETURN_WRONG_PARAMETER;
    1529              : 
    1530              :     /* forbid dlt usage in child after fork */
    1531          209 :     if (g_dlt_is_child)
    1532              :         return DLT_RETURN_ERROR;
    1533              : 
    1534          209 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    1535            2 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    1536            2 :         return DLT_RETURN_WRONG_PARAMETER;
    1537              :     }
    1538              : 
    1539          207 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    1540            2 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    1541            2 :         return DLT_RETURN_WRONG_PARAMETER;
    1542              :     }
    1543              : 
    1544          205 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    1545              :         return DLT_RETURN_ERROR;
    1546              : 
    1547              :     /* Reset message counter */
    1548          205 :     handle->mcnt = 0;
    1549              : 
    1550              :     /* Store context id in log level/trace status field */
    1551              : 
    1552              :     /* Check if already registered, else register context */
    1553          205 :     dlt_mutex_lock();
    1554              : 
    1555              :     /* Check of double context registration removed */
    1556              :     /* Double registration is already checked by daemon */
    1557              : 
    1558              :     /* Allocate or expand context array */
    1559          205 :     if (dlt_user.dlt_ll_ts == NULL) {
    1560           21 :         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*)malloc(sizeof(dlt_ll_ts_type) * DLT_USER_CONTEXT_ALLOC_SIZE);
    1561              : 
    1562           21 :         if (dlt_user.dlt_ll_ts == NULL) {
    1563            0 :             dlt_mutex_unlock();
    1564            0 :             return DLT_RETURN_ERROR;
    1565              :         }
    1566              : 
    1567           21 :         dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
    1568              : 
    1569              :         /* Initialize new entries */
    1570        10521 :         for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1571        10500 :             dlt_set_id(dlt_user.dlt_ll_ts[i].contextID, "");
    1572              : 
    1573              :             /* At startup, logging and tracing is locally enabled */
    1574              :             /* the correct log level/status is set after received from daemon */
    1575        10500 :             dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1576        10500 :             dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1577              : 
    1578        10500 :             dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
    1579        10500 :             dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
    1580              : 
    1581        10500 :             dlt_user.dlt_ll_ts[i].context_description = 0;
    1582              : 
    1583        10500 :             dlt_user.dlt_ll_ts[i].injection_table = 0;
    1584        10500 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1585        10500 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0;
    1586              :         }
    1587          184 :     } else if ((dlt_user.dlt_ll_ts_num_entries % DLT_USER_CONTEXT_ALLOC_SIZE) == 0) {
    1588              :         /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
    1589              :         dlt_ll_ts_type* old_ll_ts;
    1590              :         uint32_t old_max_entries;
    1591              : 
    1592              :         old_ll_ts = dlt_user.dlt_ll_ts;
    1593            0 :         old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
    1594              : 
    1595            0 :         dlt_user.dlt_ll_ts_max_num_entries =
    1596            0 :             ((dlt_user.dlt_ll_ts_num_entries / DLT_USER_CONTEXT_ALLOC_SIZE) + 1) * DLT_USER_CONTEXT_ALLOC_SIZE;
    1597            0 :         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*)malloc(sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_max_num_entries);
    1598              : 
    1599            0 :         if (dlt_user.dlt_ll_ts == NULL) {
    1600            0 :             dlt_user.dlt_ll_ts = old_ll_ts;
    1601            0 :             dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
    1602            0 :             dlt_mutex_unlock();
    1603            0 :             return DLT_RETURN_ERROR;
    1604              :         }
    1605              : 
    1606            0 :         memcpy(dlt_user.dlt_ll_ts, old_ll_ts, sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_num_entries);
    1607            0 :         free(old_ll_ts);
    1608              : 
    1609              :         /* Initialize new entries */
    1610            0 :         for (i = dlt_user.dlt_ll_ts_num_entries; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1611            0 :             dlt_set_id(dlt_user.dlt_ll_ts[i].contextID, "");
    1612              : 
    1613              :             /* At startup, logging and tracing is locally enabled */
    1614              :             /* the correct log level/status is set after received from daemon */
    1615            0 :             dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1616            0 :             dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1617              : 
    1618            0 :             dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
    1619            0 :             dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
    1620              : 
    1621            0 :             dlt_user.dlt_ll_ts[i].context_description = 0;
    1622              : 
    1623            0 :             dlt_user.dlt_ll_ts[i].injection_table = 0;
    1624            0 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1625            0 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0;
    1626              :         }
    1627              :     }
    1628              : 
    1629              :     /* New context entry to be initialized */
    1630              :     dlt_ll_ts_type* ctx_entry;
    1631          205 :     ctx_entry = &dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries];
    1632              : 
    1633              :     /* Store locally context id and context description */
    1634          205 :     dlt_set_id(ctx_entry->contextID, contextid);
    1635              : 
    1636          205 :     if (ctx_entry->context_description != 0)
    1637            0 :         free(ctx_entry->context_description);
    1638              : 
    1639          205 :     ctx_entry->context_description = 0;
    1640              : 
    1641          205 :     if (description != 0) {
    1642          205 :         size_t desc_len = strlen(description);
    1643          205 :         ctx_entry->context_description = malloc(desc_len + 1);
    1644              : 
    1645          205 :         if (ctx_entry->context_description == 0) {
    1646            0 :             dlt_mutex_unlock();
    1647            0 :             return DLT_RETURN_ERROR;
    1648              :         }
    1649              : 
    1650              :         strncpy(ctx_entry->context_description, description, desc_len + 1);
    1651              :     }
    1652              : 
    1653          205 :     if (ctx_entry->log_level_ptr == 0) {
    1654          205 :         ctx_entry->log_level_ptr = malloc(sizeof(int8_t));
    1655              : 
    1656          205 :         if (ctx_entry->log_level_ptr == 0) {
    1657            0 :             dlt_mutex_unlock();
    1658            0 :             return DLT_RETURN_ERROR;
    1659              :         }
    1660              :     }
    1661              : 
    1662          205 :     if (ctx_entry->trace_status_ptr == 0) {
    1663          205 :         ctx_entry->trace_status_ptr = malloc(sizeof(int8_t));
    1664              : 
    1665          205 :         if (ctx_entry->trace_status_ptr == 0) {
    1666            0 :             dlt_mutex_unlock();
    1667            0 :             return DLT_RETURN_ERROR;
    1668              :         }
    1669              :     }
    1670              : 
    1671              :     /* check if the log level is set in the environement */
    1672              :     envLogLevel =
    1673          205 :         dlt_env_adjust_ll_from_env(&dlt_user.initial_ll_set, dlt_user.appID, contextid, DLT_USER_LOG_LEVEL_NOT_SET);
    1674              : 
    1675          205 :     if (envLogLevel != DLT_USER_LOG_LEVEL_NOT_SET) {
    1676            0 :         ctx_entry->log_level = (int8_t)envLogLevel;
    1677              :         loglevel = envLogLevel;
    1678          205 :     } else if (loglevel != DLT_USER_LOG_LEVEL_NOT_SET) {
    1679           16 :         ctx_entry->log_level = (int8_t)loglevel;
    1680              :     }
    1681              : 
    1682          205 :     if (tracestatus != DLT_USER_TRACE_STATUS_NOT_SET)
    1683           15 :         ctx_entry->trace_status = (int8_t)tracestatus;
    1684              : 
    1685              :     /* Prepare transfer struct */
    1686          205 :     dlt_set_id(handle->contextID, contextid);
    1687          205 :     handle->log_level_pos = (int32_t)dlt_user.dlt_ll_ts_num_entries;
    1688              : 
    1689          205 :     handle->log_level_ptr = ctx_entry->log_level_ptr;
    1690          205 :     handle->trace_status_ptr = ctx_entry->trace_status_ptr;
    1691              : 
    1692          205 :     log.context_description = ctx_entry->context_description;
    1693              : 
    1694          205 :     *(ctx_entry->log_level_ptr) = ctx_entry->log_level;
    1695          205 :     *(ctx_entry->trace_status_ptr) = ctx_entry->trace_status = (int8_t)tracestatus;
    1696          205 :     ctx_entry->log_level_changed_callback = dlt_log_level_changed_callback;
    1697              : 
    1698          205 :     log.log_level = loglevel;
    1699          205 :     log.trace_status = tracestatus;
    1700              : 
    1701          205 :     dlt_user.dlt_ll_ts_num_entries++;
    1702          205 :     dlt_mutex_unlock();
    1703              : 
    1704              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1705              :     /* Compute runtime trace-load settings under the rwlock,
    1706              :      * then publish the pointer while holding the DLT mutex
    1707              :      * to avoid races with other threads that may reallocate
    1708              :      * the context array. This avoids holding both locks at
    1709              :      * the same time.
    1710              :      */
    1711              :     pthread_rwlock_rdlock(&trace_load_rw_lock);
    1712              :     DltTraceLoadSettings* settings = dlt_find_runtime_trace_load_settings(
    1713              :         trace_load_settings, trace_load_settings_count, dlt_user.appID, ctx_entry->contextID);
    1714              :     pthread_rwlock_unlock(&trace_load_rw_lock);
    1715              : 
    1716              :     dlt_mutex_lock();
    1717              :     /* ctx_entry points into dlt_user.dlt_ll_ts which is protected by dlt_mutex */
    1718              :     ctx_entry->trace_load_settings = settings;
    1719              :     dlt_mutex_unlock();
    1720              : #endif
    1721              : 
    1722          205 :     return dlt_user_log_send_register_context(&log);
    1723              : }
    1724              : 
    1725          216 : DltReturnValue dlt_register_context_ll_ts(
    1726              :     DltContext* handle, const char* contextid, const char* description, int loglevel, int tracestatus)
    1727              : {
    1728          216 :     return dlt_register_context_ll_ts_llccb(handle, contextid, description, loglevel, tracestatus, NULL);
    1729              : }
    1730              : 
    1731            0 : DltReturnValue dlt_register_context_llccb(
    1732              :     DltContext* handle, const char* contextid, const char* description,
    1733              :     void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status))
    1734              : {
    1735            0 :     if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0'))
    1736              :         return DLT_RETURN_WRONG_PARAMETER;
    1737              : 
    1738              :     /* forbid dlt usage in child after fork */
    1739            0 :     if (g_dlt_is_child)
    1740              :         return DLT_RETURN_ERROR;
    1741              : 
    1742            0 :     if (!DLT_USER_INITIALIZED) {
    1743            0 :         if (dlt_init() < 0) {
    1744            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    1745            0 :             return DLT_RETURN_ERROR;
    1746              :         }
    1747              :     }
    1748              : 
    1749            0 :     return dlt_register_context_ll_ts_llccb(
    1750              :         handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET,
    1751              :         dlt_log_level_changed_callback);
    1752              : }
    1753              : 
    1754           49 : DltReturnValue dlt_register_context_ll_ts_llccb_v2(
    1755              :     DltContext* handle, const char* contextid, const char* description, int loglevel, int tracestatus,
    1756              :     void (*dlt_log_level_changed_callback_v2)(char* context_id, uint8_t log_level, uint8_t trace_status))
    1757              : {
    1758              :     DltContextData log;
    1759              :     uint32_t i;
    1760              :     int envLogLevel = DLT_USER_LOG_LEVEL_NOT_SET;
    1761              : 
    1762              :     /*check nullpointer */
    1763           49 :     if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0'))
    1764              :         return DLT_RETURN_WRONG_PARAMETER;
    1765              : 
    1766           40 :     size_t contextidlen_sz = strlen(contextid);
    1767           40 :     if (contextidlen_sz > INT8_MAX) {
    1768              :         return DLT_RETURN_WRONG_PARAMETER;
    1769              :     }
    1770           40 :     uint8_t contextidlen = (uint8_t)contextidlen_sz;
    1771              : 
    1772              :     /* forbid dlt usage in child after fork */
    1773           40 :     if (g_dlt_is_child)
    1774              :         return DLT_RETURN_ERROR;
    1775              : 
    1776           40 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    1777            2 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    1778            2 :         return DLT_RETURN_WRONG_PARAMETER;
    1779              :     }
    1780              : 
    1781           38 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    1782            2 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    1783            2 :         return DLT_RETURN_WRONG_PARAMETER;
    1784              :     }
    1785              : 
    1786           36 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    1787              :         return DLT_RETURN_ERROR;
    1788              : 
    1789              :     /* Reset message counter */
    1790           36 :     handle->mcnt = 0;
    1791              : 
    1792              :     /* Store context id in log level/trace status field */
    1793              : 
    1794              :     /* Check if already registered, else register context */
    1795           36 :     dlt_mutex_lock();
    1796              : 
    1797              :     /* Check of double context registration removed */
    1798              :     /* Double registration is already checked by daemon */
    1799              : 
    1800              :     /* Allocate or expand context array */
    1801           36 :     if (dlt_user.dlt_ll_ts == NULL) {
    1802            1 :         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*)malloc(sizeof(dlt_ll_ts_type) * DLT_USER_CONTEXT_ALLOC_SIZE);
    1803              : 
    1804            1 :         if (dlt_user.dlt_ll_ts == NULL) {
    1805            0 :             dlt_mutex_unlock();
    1806            0 :             return DLT_RETURN_ERROR;
    1807              :         }
    1808              : 
    1809            1 :         dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
    1810              : 
    1811              :         /* Initialize new entries */
    1812          501 :         for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1813              :             /* At startup, logging and tracing is locally enabled */
    1814              :             /* the correct log level/status is set after received from daemon */
    1815          500 :             memset(dlt_user.dlt_ll_ts[i].contextID2, 0, DLT_V2_ID_SIZE);
    1816          500 :             dlt_user.dlt_ll_ts[i].contextID2len = 0;
    1817          500 :             dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1818          500 :             dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1819              : 
    1820          500 :             dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
    1821          500 :             dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
    1822              : 
    1823          500 :             dlt_user.dlt_ll_ts[i].context_description = 0;
    1824              : 
    1825          500 :             dlt_user.dlt_ll_ts[i].injection_table = 0;
    1826          500 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1827          500 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback_v2 = 0;
    1828              :         }
    1829           35 :     } else if ((dlt_user.dlt_ll_ts_num_entries % DLT_USER_CONTEXT_ALLOC_SIZE) == 0) {
    1830              :         /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
    1831              :         dlt_ll_ts_type* old_ll_ts;
    1832              :         uint32_t old_max_entries;
    1833              : 
    1834              :         old_ll_ts = dlt_user.dlt_ll_ts;
    1835            0 :         old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
    1836              : 
    1837            0 :         dlt_user.dlt_ll_ts_max_num_entries =
    1838            0 :             ((dlt_user.dlt_ll_ts_num_entries / DLT_USER_CONTEXT_ALLOC_SIZE) + 1) * DLT_USER_CONTEXT_ALLOC_SIZE;
    1839            0 :         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*)malloc(sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_max_num_entries);
    1840              : 
    1841            0 :         if (dlt_user.dlt_ll_ts == NULL) {
    1842            0 :             dlt_user.dlt_ll_ts = old_ll_ts;
    1843            0 :             dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
    1844            0 :             dlt_mutex_unlock();
    1845            0 :             return DLT_RETURN_ERROR;
    1846              :         }
    1847              : 
    1848            0 :         memcpy(dlt_user.dlt_ll_ts, old_ll_ts, sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_num_entries);
    1849            0 :         free(old_ll_ts);
    1850              : 
    1851              :         /* Initialize new entries */
    1852            0 :         for (i = dlt_user.dlt_ll_ts_num_entries; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1853              :             /* At startup, logging and tracing is locally enabled */
    1854              :             /* the correct log level/status is set after received from daemon */
    1855            0 :             memset(dlt_user.dlt_ll_ts[i].contextID2, 0, DLT_V2_ID_SIZE);
    1856            0 :             dlt_user.dlt_ll_ts[i].contextID2len = 0;
    1857            0 :             dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1858            0 :             dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1859              : 
    1860            0 :             dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
    1861            0 :             dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
    1862              : 
    1863            0 :             dlt_user.dlt_ll_ts[i].context_description = 0;
    1864              : 
    1865            0 :             dlt_user.dlt_ll_ts[i].injection_table = 0;
    1866            0 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1867            0 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback_v2 = 0;
    1868              :         }
    1869              :     }
    1870              : 
    1871              :     /* New context entry to be initialized */
    1872              :     dlt_ll_ts_type* ctx_entry;
    1873           36 :     ctx_entry = &dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries];
    1874              : 
    1875              :     /* Store locally context id and context description */
    1876           36 :     if ((contextid != NULL) && (contextidlen > 0)) {
    1877           36 :         memset(ctx_entry->contextID2, 0, DLT_V2_ID_SIZE);
    1878           36 :         dlt_set_id_v2(ctx_entry->contextID2, contextid, contextidlen);
    1879           36 :         ctx_entry->contextID2len = (uint8_t)contextidlen;
    1880              :     } else {
    1881            0 :         memset(ctx_entry->contextID2, 0, DLT_V2_ID_SIZE);
    1882            0 :         ctx_entry->contextID2len = 0;
    1883              :     }
    1884              : 
    1885           36 :     if (ctx_entry->context_description != 0)
    1886            0 :         free(ctx_entry->context_description);
    1887              : 
    1888           36 :     ctx_entry->context_description = 0;
    1889              : 
    1890           36 :     if (description != 0) {
    1891           36 :         size_t desc_len = strlen(description);
    1892           36 :         ctx_entry->context_description = malloc(desc_len + 1);
    1893              : 
    1894           36 :         if (ctx_entry->context_description == 0) {
    1895            0 :             dlt_mutex_unlock();
    1896            0 :             return DLT_RETURN_ERROR;
    1897              :         }
    1898              : 
    1899              :         strncpy(ctx_entry->context_description, description, desc_len + 1);
    1900              :     }
    1901              : 
    1902           36 :     if (ctx_entry->log_level_ptr == 0) {
    1903           36 :         ctx_entry->log_level_ptr = malloc(sizeof(int8_t));
    1904              : 
    1905           36 :         if (ctx_entry->log_level_ptr == 0) {
    1906            0 :             dlt_mutex_unlock();
    1907            0 :             return DLT_RETURN_ERROR;
    1908              :         }
    1909              :     }
    1910              : 
    1911           36 :     if (ctx_entry->trace_status_ptr == 0) {
    1912           36 :         ctx_entry->trace_status_ptr = malloc(sizeof(int8_t));
    1913              : 
    1914           36 :         if (ctx_entry->trace_status_ptr == 0) {
    1915            0 :             dlt_mutex_unlock();
    1916            0 :             return DLT_RETURN_ERROR;
    1917              :         }
    1918              :     }
    1919              : 
    1920              :     /* check if the log level is set in the environement */
    1921           36 :     envLogLevel = dlt_env_adjust_ll_from_env_v2(
    1922           36 :         &dlt_user.initial_ll_set, dlt_user.appID2, dlt_user.appID2len, contextid, contextidlen,
    1923              :         DLT_USER_LOG_LEVEL_NOT_SET);
    1924              : 
    1925           36 :     if (envLogLevel != DLT_USER_LOG_LEVEL_NOT_SET) {
    1926            0 :         ctx_entry->log_level = (int8_t)envLogLevel;
    1927              :         loglevel = envLogLevel;
    1928           36 :     } else if (loglevel != DLT_USER_LOG_LEVEL_NOT_SET) {
    1929           16 :         ctx_entry->log_level = (int8_t)loglevel;
    1930              :     }
    1931              : 
    1932           36 :     if (tracestatus != DLT_USER_TRACE_STATUS_NOT_SET)
    1933           15 :         ctx_entry->trace_status = (int8_t)tracestatus;
    1934              : 
    1935              :     /* Prepare transfer struct */
    1936           36 :     handle->contextID2 = ctx_entry->contextID2;
    1937           36 :     dlt_set_id_v2(handle->contextID2, contextid, contextidlen);
    1938           36 :     handle->contextID2len = (uint8_t)contextidlen;
    1939           36 :     handle->log_level_pos = (int32_t)dlt_user.dlt_ll_ts_num_entries;
    1940              : 
    1941           36 :     handle->log_level_ptr = ctx_entry->log_level_ptr;
    1942           36 :     handle->trace_status_ptr = ctx_entry->trace_status_ptr;
    1943              : 
    1944           36 :     log.context_description = ctx_entry->context_description;
    1945              : 
    1946           36 :     *(ctx_entry->log_level_ptr) = ctx_entry->log_level;
    1947           36 :     *(ctx_entry->trace_status_ptr) = ctx_entry->trace_status = (int8_t)tracestatus;
    1948           36 :     ctx_entry->log_level_changed_callback_v2 = dlt_log_level_changed_callback_v2;
    1949              : 
    1950           36 :     log.log_level = loglevel;
    1951           36 :     log.trace_status = tracestatus;
    1952              : 
    1953           36 :     dlt_user.dlt_ll_ts_num_entries++;
    1954              : 
    1955           36 :     dlt_mutex_unlock();
    1956              : 
    1957           36 :     return dlt_user_log_send_register_context_v2(&log);
    1958              : }
    1959              : 
    1960           49 : DltReturnValue dlt_register_context_ll_ts_v2(
    1961              :     DltContext* handle, const char* contextid, const char* description, int loglevel, int tracestatus)
    1962              : {
    1963           49 :     return dlt_register_context_ll_ts_llccb_v2(handle, contextid, description, loglevel, tracestatus, NULL);
    1964              : }
    1965              : 
    1966            0 : DltReturnValue dlt_register_context_llccb_v2(
    1967              :     DltContext* handle, const char* contextid, const char* description,
    1968              :     void (*dlt_log_level_changed_callback_v2)(char* context_id, uint8_t log_level, uint8_t trace_status))
    1969              : {
    1970            0 :     size_t contextidlen_sz = strlen(contextid);
    1971            0 :     if ((handle == NULL) || (contextid == NULL) || (contextidlen_sz == 0) || (contextidlen_sz > INT8_MAX))
    1972              :         return DLT_RETURN_WRONG_PARAMETER;
    1973              : 
    1974              :     /* forbid dlt usage in child after fork */
    1975            0 :     if (g_dlt_is_child)
    1976              :         return DLT_RETURN_ERROR;
    1977              : 
    1978            0 :     if (!DLT_USER_INITIALIZED) {
    1979            0 :         if (dlt_init() < 0) {
    1980            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    1981            0 :             return DLT_RETURN_ERROR;
    1982              :         }
    1983              :     }
    1984              : 
    1985            0 :     return dlt_register_context_ll_ts_llccb_v2(
    1986              :         handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET,
    1987              :         dlt_log_level_changed_callback_v2);
    1988              : }
    1989              : 
    1990              : /* If force_sending_messages is set to true, do not clean appIDs when there are
    1991              :  * still data in startup_buffer. atexit_handler will free the appIDs */
    1992          182 : DltReturnValue dlt_unregister_app_util(bool force_sending_messages)
    1993              : {
    1994              :     DltReturnValue ret = DLT_RETURN_OK;
    1995              : 
    1996              :     /* forbid dlt usage in child after fork */
    1997          182 :     if (g_dlt_is_child) {
    1998              :         return DLT_RETURN_ERROR;
    1999              :     }
    2000              : 
    2001          182 :     if (!DLT_USER_INITIALIZED) {
    2002            0 :         dlt_vlog(
    2003              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2004            0 :             dlt_user_init_state, dlt_user_freeing);
    2005            0 :         return DLT_RETURN_ERROR;
    2006              :     }
    2007              : 
    2008              :     /* Inform daemon to unregister application and all of its contexts */
    2009          182 :     ret = dlt_user_log_send_unregister_application();
    2010              : 
    2011          182 :     dlt_mutex_lock();
    2012              : 
    2013          182 :     int count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    2014              : 
    2015          182 :     if (!force_sending_messages || (force_sending_messages && (count == 0))) {
    2016              :         /* Clear and free local stored application information */
    2017          181 :         dlt_set_id(dlt_user.appID, "");
    2018              : 
    2019          181 :         if (dlt_user.application_description != NULL) {
    2020          171 :             free(dlt_user.application_description);
    2021              :         }
    2022              : 
    2023          181 :         dlt_user.application_description = NULL;
    2024              :     }
    2025              : 
    2026          182 :     dlt_mutex_unlock();
    2027              : 
    2028          182 :     return ret;
    2029              : }
    2030              : 
    2031              : /* If force_sending_messages is set to true, do not clean appIDs when there are
    2032              :  * still data in startup_buffer. atexit_handler will free the appIDs */
    2033           24 : DltReturnValue dlt_unregister_app_util_v2(bool force_sending_messages)
    2034              : {
    2035              :     DltReturnValue ret = DLT_RETURN_OK;
    2036              : 
    2037              :     /* forbid dlt usage in child after fork */
    2038           24 :     if (g_dlt_is_child) {
    2039              :         return DLT_RETURN_ERROR;
    2040              :     }
    2041              : 
    2042           24 :     if (!DLT_USER_INITIALIZED) {
    2043            0 :         dlt_vlog(
    2044              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2045            0 :             dlt_user_init_state, dlt_user_freeing);
    2046            0 :         return DLT_RETURN_ERROR;
    2047              :     }
    2048              : 
    2049              :     /* Inform daemon to unregister application and all of its contexts */
    2050           24 :     ret = dlt_user_log_send_unregister_application_v2();
    2051              : 
    2052           24 :     dlt_mutex_lock();
    2053              : 
    2054           24 :     int count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    2055              : 
    2056           24 :     if (!force_sending_messages || (force_sending_messages && (count == 0))) {
    2057              :         /* Clear and free local stored application information */
    2058              :         memset(dlt_user.appID2, 0, DLT_V2_ID_SIZE);
    2059           24 :         dlt_user.appID2len = 0;
    2060              : 
    2061           24 :         if (dlt_user.application_description != NULL) {
    2062           24 :             free(dlt_user.application_description);
    2063              :         }
    2064              : 
    2065           24 :         dlt_user.application_description = NULL;
    2066              :     }
    2067              : 
    2068           24 :     dlt_mutex_unlock();
    2069              : 
    2070           24 :     return ret;
    2071              : }
    2072              : 
    2073          167 : DltReturnValue dlt_unregister_app(void)
    2074              : {
    2075          167 :     return dlt_unregister_app_util(false);
    2076              : }
    2077              : 
    2078           24 : DltReturnValue dlt_unregister_app_v2(void)
    2079              : {
    2080           24 :     return dlt_unregister_app_util_v2(false);
    2081              : }
    2082              : 
    2083            7 : DltReturnValue dlt_unregister_app_flush_buffered_logs(void)
    2084              : {
    2085              :     DltReturnValue ret = DLT_RETURN_OK;
    2086              : 
    2087              :     /* forbid dlt usage in child after fork */
    2088            7 :     if (g_dlt_is_child)
    2089              :         return DLT_RETURN_ERROR;
    2090              : 
    2091            7 :     if (!DLT_USER_INITIALIZED) {
    2092            0 :         dlt_vlog(
    2093              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2094            0 :             dlt_user_init_state, dlt_user_freeing);
    2095            0 :         return DLT_RETURN_ERROR;
    2096              :     }
    2097              : 
    2098            7 :     if (dlt_user.dlt_log_handle != -1) {
    2099              :         do
    2100            7 :             ret = dlt_user_log_resend_buffer();
    2101            7 :         while ((ret != DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1));
    2102              :     }
    2103              : 
    2104            7 :     return dlt_unregister_app_util(true);
    2105              : }
    2106              : 
    2107          204 : DltReturnValue dlt_unregister_context(DltContext* handle)
    2108              : {
    2109              :     DltContextData log;
    2110              :     DltReturnValue ret = DLT_RETURN_OK;
    2111              : 
    2112              :     /* forbid dlt usage in child after fork */
    2113          204 :     if (g_dlt_is_child) {
    2114              :         return DLT_RETURN_ERROR;
    2115              :     }
    2116              : 
    2117          204 :     log.handle = NULL;
    2118          204 :     log.context_description = NULL;
    2119              : 
    2120          204 :     if (dlt_user_log_init(handle, &log) <= DLT_RETURN_ERROR) {
    2121              :         return DLT_RETURN_ERROR;
    2122              :     }
    2123              : 
    2124          204 :     dlt_mutex_lock();
    2125          204 :     handle->log_level_ptr = NULL;
    2126          204 :     handle->trace_status_ptr = NULL;
    2127              : 
    2128          204 :     if (dlt_user.dlt_ll_ts != NULL) {
    2129              :         /* Clear and free local stored context information */
    2130          204 :         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
    2131              : 
    2132          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    2133          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    2134              : 
    2135          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description != NULL) {
    2136          204 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
    2137              :         }
    2138              : 
    2139          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr != NULL) {
    2140          204 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
    2141          204 :             dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = NULL;
    2142              :         }
    2143              : 
    2144          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr != NULL) {
    2145          204 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
    2146          204 :             dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = NULL;
    2147              :         }
    2148              : 
    2149          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = NULL;
    2150              : 
    2151          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table != NULL) {
    2152            0 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
    2153            0 :             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = NULL;
    2154              :         }
    2155              : 
    2156          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0;
    2157          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_changed_callback = 0;
    2158              :     }
    2159          204 :     dlt_mutex_unlock();
    2160              : 
    2161              :     /* Inform daemon to unregister context */
    2162          204 :     ret = dlt_user_log_send_unregister_context(&log);
    2163              : 
    2164          204 :     return ret;
    2165              : }
    2166              : 
    2167           35 : DltReturnValue dlt_unregister_context_v2(DltContext* handle)
    2168              : {
    2169              :     DltContextData log;
    2170              :     DltReturnValue ret = DLT_RETURN_OK;
    2171              : 
    2172              :     /* forbid dlt usage in child after fork */
    2173           35 :     if (g_dlt_is_child) {
    2174              :         return DLT_RETURN_ERROR;
    2175              :     }
    2176              : 
    2177           35 :     log.handle = NULL;
    2178           35 :     log.context_description = NULL;
    2179              : 
    2180           35 :     if (dlt_user_log_init(handle, &log) <= DLT_RETURN_ERROR) {
    2181              :         return DLT_RETURN_ERROR;
    2182              :     }
    2183              : 
    2184           35 :     dlt_mutex_lock();
    2185              : 
    2186           35 :     handle->log_level_ptr = NULL;
    2187           35 :     handle->trace_status_ptr = NULL;
    2188              : 
    2189           35 :     if (dlt_user.dlt_ll_ts != NULL) {
    2190              :         /* Clear and free local stored context information */
    2191           35 :         dlt_user.dlt_ll_ts[handle->log_level_pos].contextID2len = 0;
    2192              : 
    2193           35 :         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    2194           35 :         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    2195              : 
    2196           35 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description != NULL) {
    2197           35 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
    2198              :         }
    2199              : 
    2200           35 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr != NULL) {
    2201           35 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
    2202           35 :             dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = NULL;
    2203              :         }
    2204              : 
    2205           35 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr != NULL) {
    2206           35 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
    2207           35 :             dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = NULL;
    2208              :         }
    2209              : 
    2210           35 :         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = NULL;
    2211              : 
    2212           35 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table != NULL) {
    2213            0 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
    2214            0 :             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = NULL;
    2215              :         }
    2216              : 
    2217           35 :         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0;
    2218           35 :         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_changed_callback_v2 = 0;
    2219              :     }
    2220              : 
    2221           35 :     dlt_mutex_unlock();
    2222              :     /* Inform daemon to unregister context */
    2223           35 :     ret = dlt_user_log_send_unregister_context_v2(&log);
    2224              : 
    2225           35 :     return ret;
    2226              : }
    2227              : 
    2228            0 : DltReturnValue dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
    2229              : {
    2230              :     uint32_t i;
    2231              : 
    2232              :     /* forbid dlt usage in child after fork */
    2233            0 :     if (g_dlt_is_child)
    2234              :         return DLT_RETURN_ERROR;
    2235              : 
    2236            0 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    2237            0 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    2238            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2239              :     }
    2240              : 
    2241            0 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    2242            0 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    2243            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2244              :     }
    2245              : 
    2246            0 :     if (!DLT_USER_INITIALIZED) {
    2247            0 :         if (dlt_init() < 0) {
    2248            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    2249            0 :             return DLT_RETURN_ERROR;
    2250              :         }
    2251              :     }
    2252              : 
    2253            0 :     dlt_mutex_lock();
    2254              : 
    2255            0 :     if (dlt_user.dlt_ll_ts == NULL) {
    2256            0 :         dlt_mutex_unlock();
    2257            0 :         return DLT_RETURN_ERROR;
    2258              :     }
    2259              : 
    2260              :     /* Update local structures */
    2261            0 :     for (i = 0; i < dlt_user.dlt_ll_ts_num_entries; i++) {
    2262            0 :         dlt_user.dlt_ll_ts[i].log_level = loglevel;
    2263            0 :         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
    2264              : 
    2265            0 :         if (dlt_user.dlt_ll_ts[i].log_level_ptr)
    2266            0 :             *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
    2267              : 
    2268            0 :         if (dlt_user.dlt_ll_ts[i].trace_status_ptr)
    2269            0 :             *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
    2270              :     }
    2271              : 
    2272            0 :     dlt_mutex_unlock();
    2273              : 
    2274              :     /* Inform DLT Daemon about update */
    2275            0 :     if (dlt_user.appID[0] != '\0') {
    2276            0 :         return dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
    2277            0 :     } else if (dlt_user.appID2len != 0) {
    2278            0 :         return dlt_send_app_ll_ts_limit_v2(dlt_user.appID2, loglevel, tracestatus);
    2279              :     } else {
    2280              :         return DLT_RETURN_ERROR;
    2281              :     }
    2282              : }
    2283              : 
    2284            1 : int dlt_get_log_state()
    2285              : {
    2286            1 :     return dlt_user.log_state;
    2287              : }
    2288              : 
    2289            4 : DltReturnValue dlt_set_log_mode(DltUserLogMode mode)
    2290              : {
    2291              :     DLT_UNUSED(mode);
    2292              : 
    2293              :     /* forbid dlt usage in child after fork */
    2294            4 :     if (g_dlt_is_child)
    2295              :         return DLT_RETURN_ERROR;
    2296              : 
    2297            4 :     if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) {
    2298            0 :         dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode);
    2299            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2300              :     }
    2301              : 
    2302            4 :     if (!DLT_USER_INITIALIZED) {
    2303            0 :         if (dlt_init() < 0) {
    2304            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    2305            0 :             return DLT_RETURN_ERROR;
    2306              :         }
    2307              :     }
    2308              : 
    2309            4 :     return dlt_user_log_send_log_mode(mode, DLTProtocolV1);
    2310              : }
    2311              : 
    2312            0 : DltReturnValue dlt_set_log_mode_v2(DltUserLogMode mode)
    2313              : {
    2314              :     DLT_UNUSED(mode);
    2315              : 
    2316              :     /* forbid dlt usage in child after fork */
    2317            0 :     if (g_dlt_is_child)
    2318              :         return DLT_RETURN_ERROR;
    2319              : 
    2320            0 :     if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) {
    2321            0 :         dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode);
    2322            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2323              :     }
    2324              : 
    2325            0 :     if (!DLT_USER_INITIALIZED) {
    2326            0 :         if (dlt_init() < 0) {
    2327            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    2328            0 :             return DLT_RETURN_ERROR;
    2329              :         }
    2330              :     }
    2331              : 
    2332            0 :     return dlt_user_log_send_log_mode(mode, DLTProtocolV2);
    2333              : }
    2334              : 
    2335            2 : int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds)
    2336              : {
    2337              :     /* forbid dlt usage in child after fork */
    2338            2 :     if (g_dlt_is_child)
    2339              :         return DLT_RETURN_ERROR;
    2340              : 
    2341            2 :     if (DLT_USER_INITIALIZED == 0)
    2342            2 :         if (dlt_init() < 0)
    2343              :             return -1;
    2344              : 
    2345            2 :     dlt_user.timeout_at_exit_handler = timeout_in_milliseconds * 10;
    2346            2 :     return 0;
    2347              : }
    2348              : 
    2349              : /* ********************************************************************************************* */
    2350              : 
    2351         6022 : DltReturnValue dlt_user_log_write_start_init(
    2352              :     DltContext* handle, DltContextData* log, DltLogLevelType loglevel, bool is_verbose)
    2353              : {
    2354              :     DLT_LOG_FATAL_RESET_TRAP(loglevel);
    2355              : 
    2356              :     /* initialize values */
    2357         6022 :     if ((dlt_user_log_init(handle, log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL))
    2358              :         return DLT_RETURN_ERROR;
    2359              : 
    2360         6022 :     log->args_num = 0;
    2361         6022 :     log->log_level = loglevel;
    2362         6022 :     log->size = 0;
    2363         6022 :     log->use_timestamp = DLT_AUTO_TIMESTAMP;
    2364         6022 :     log->verbose_mode = is_verbose;
    2365              : 
    2366         6022 :     return DLT_RETURN_TRUE;
    2367              : }
    2368              : 
    2369              : static DltReturnValue dlt_user_log_write_start_internal(
    2370              :     DltContext* handle, DltContextData* log, DltLogLevelType loglevel, uint32_t messageid, bool is_verbose);
    2371              : 
    2372         5942 : inline DltReturnValue dlt_user_log_write_start(DltContext* handle, DltContextData* log, DltLogLevelType loglevel)
    2373              : {
    2374         6052 :     return dlt_user_log_write_start_internal(handle, log, loglevel, DLT_USER_DEFAULT_MSGID, true);
    2375              : }
    2376              : 
    2377           43 : DltReturnValue dlt_user_log_write_start_id(
    2378              :     DltContext* handle, DltContextData* log, DltLogLevelType loglevel, uint32_t messageid)
    2379              : {
    2380           43 :     return dlt_user_log_write_start_internal(handle, log, loglevel, messageid, false);
    2381              : }
    2382              : 
    2383         6095 : DltReturnValue dlt_user_log_write_start_internal(
    2384              :     DltContext* handle, DltContextData* log, DltLogLevelType loglevel, uint32_t messageid, bool is_verbose)
    2385              : {
    2386              :     int ret = DLT_RETURN_TRUE;
    2387              : 
    2388              :     /* check nullpointer */
    2389         6095 :     if ((handle == NULL) || (log == NULL))
    2390              :         return DLT_RETURN_WRONG_PARAMETER;
    2391              : 
    2392              :     /* forbid dlt usage in child after fork */
    2393         6083 :     if (g_dlt_is_child)
    2394              :         return DLT_RETURN_ERROR;
    2395              : 
    2396              :     /* check log levels */
    2397         6083 :     ret = dlt_user_is_logLevel_enabled(handle, loglevel);
    2398              : 
    2399         6083 :     if (ret == DLT_RETURN_WRONG_PARAMETER) {
    2400              :         return DLT_RETURN_WRONG_PARAMETER;
    2401         6070 :     } else if (ret == DLT_RETURN_LOGGING_DISABLED) {
    2402           48 :         log->handle = NULL;
    2403           48 :         return DLT_RETURN_OK;
    2404              :     }
    2405              : 
    2406         6022 :     ret = dlt_user_log_write_start_init(handle, log, loglevel, is_verbose);
    2407         6022 :     if (ret == DLT_RETURN_TRUE) {
    2408              :         /* initialize values */
    2409         6022 :         if ((NULL != log->buffer)) {
    2410            0 :             free(log->buffer);
    2411            0 :             log->buffer = NULL;
    2412              :         } else {
    2413         6022 :             log->buffer = calloc(dlt_user.log_buf_len, sizeof(unsigned char));
    2414              :         }
    2415              : 
    2416         6022 :         if (log->buffer == NULL) {
    2417            0 :             dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    2418            0 :             return DLT_RETURN_ERROR;
    2419              :         } else {
    2420              :             /* In non-verbose mode, insert message id */
    2421        12044 :             if (!is_verbose_mode(dlt_user.verbose_mode, log)) {
    2422            3 :                 if ((sizeof(uint32_t)) > dlt_user.log_buf_len)
    2423              :                     return DLT_RETURN_USER_BUFFER_FULL;
    2424              : 
    2425              :                 /* Write message id */
    2426              :                 memcpy(log->buffer, &(messageid), sizeof(uint32_t));
    2427            3 :                 log->size = sizeof(uint32_t);
    2428              : 
    2429              :                 /* as the message id is part of each message in non-verbose mode,
    2430              :                  * it doesn't increment the argument counter in extended header (if used) */
    2431              : 
    2432            3 :                 log->msid = messageid;
    2433              :                 /* TODO: For non verbose mode in Version 2, following should be uncommented
    2434              :                  * and above copying should be commented */
    2435              :                 // log->size = 0;
    2436              :             }
    2437              :         }
    2438              :     }
    2439              : 
    2440              :     return ret;
    2441              : }
    2442              : 
    2443            0 : DltReturnValue dlt_user_log_write_start_w_given_buffer(
    2444              :     DltContext* handle, DltContextData* log, DltLogLevelType loglevel, char* buffer, size_t size, int32_t args_num)
    2445              : {
    2446              :     int ret = DLT_RETURN_TRUE;
    2447              : 
    2448              :     /* check nullpointer */
    2449            0 :     if ((handle == NULL) || (log == NULL) || (buffer == NULL))
    2450              :         return DLT_RETURN_WRONG_PARAMETER;
    2451              : 
    2452              :     /* discard unexpected parameters */
    2453            0 :     if ((size <= 0) || (size > dlt_user.log_buf_len) || (args_num <= 0))
    2454              :         return DLT_RETURN_WRONG_PARAMETER;
    2455              : 
    2456              :     /* forbid dlt usage in child after fork */
    2457            0 :     if (g_dlt_is_child)
    2458              :         return DLT_RETURN_ERROR;
    2459              : 
    2460              :     /* discard non-verbose mode */
    2461            0 :     if (dlt_user.verbose_mode == 0)
    2462              :         return DLT_RETURN_ERROR;
    2463              : 
    2464            0 :     ret = dlt_user_log_write_start_init(handle, log, loglevel, true);
    2465            0 :     if (ret == DLT_RETURN_TRUE) {
    2466            0 :         log->buffer = (unsigned char*)buffer;
    2467            0 :         log->size = (int32_t)size;
    2468            0 :         log->args_num = args_num;
    2469              :     }
    2470              : 
    2471              :     return ret;
    2472              : }
    2473              : 
    2474         6008 : DltReturnValue dlt_user_log_write_finish(DltContextData* log)
    2475              : {
    2476              :     int ret = DLT_RETURN_ERROR;
    2477              : 
    2478         6008 :     if (log == NULL)
    2479              :         return DLT_RETURN_WRONG_PARAMETER;
    2480              : 
    2481         6008 :     ret = dlt_user_log_send_log(log, DLT_TYPE_LOG, NULL);
    2482              : 
    2483              :     dlt_user_free_buffer(&(log->buffer));
    2484              : 
    2485              :     return ret;
    2486              : }
    2487              : 
    2488           30 : DltReturnValue dlt_user_log_write_finish_v2(DltContextData* log)
    2489              : {
    2490              :     int ret = DLT_RETURN_ERROR;
    2491              : 
    2492           30 :     if (log == NULL)
    2493              :         return DLT_RETURN_WRONG_PARAMETER;
    2494           30 :     ret = dlt_user_log_send_log_v2(log, DLT_TYPE_LOG, DLT_VERBOSE_DATA_MSG, NULL);
    2495              : 
    2496              :     dlt_user_free_buffer(&(log->buffer));
    2497              : 
    2498              :     return ret;
    2499              : }
    2500              : 
    2501            0 : DltReturnValue dlt_user_log_write_finish_w_given_buffer(DltContextData* log)
    2502              : {
    2503              :     int ret = DLT_RETURN_ERROR;
    2504              : 
    2505            0 :     if (log == NULL)
    2506              :         return DLT_RETURN_WRONG_PARAMETER;
    2507              : 
    2508            0 :     ret = dlt_user_log_send_log(log, DLT_TYPE_LOG, NULL);
    2509              : 
    2510            0 :     return ret;
    2511              : }
    2512              : 
    2513            0 : DltReturnValue dlt_user_log_write_finish_w_given_buffer_v2(DltContextData* log)
    2514              : {
    2515              :     int ret = DLT_RETURN_ERROR;
    2516              : 
    2517            0 :     if (log == NULL)
    2518              :         return DLT_RETURN_WRONG_PARAMETER;
    2519              : 
    2520            0 :     ret = dlt_user_log_send_log_v2(log, DLT_TYPE_LOG, DLT_VERBOSE_DATA_MSG, NULL);
    2521              : 
    2522            0 :     return ret;
    2523              : }
    2524              : 
    2525           38 : static DltReturnValue dlt_user_log_write_raw_internal(
    2526              :     DltContextData* log, const void* data, uint16_t length, DltFormatType type, const char* name, bool with_var_info)
    2527              : {
    2528              :     /* check nullpointer */
    2529           38 :     if ((log == NULL) || ((data == NULL) && (length != 0)))
    2530              :         return DLT_RETURN_WRONG_PARAMETER;
    2531              : 
    2532              :     /* Have to cast type to signed type because some compilers assume that DltFormatType is unsigned and issue a warning
    2533              :      */
    2534           31 :     if (((int16_t)type < DLT_FORMAT_DEFAULT) || (type >= DLT_FORMAT_MAX)) {
    2535            0 :         dlt_vlog(LOG_ERR, "Format type %u is outside valid range", type);
    2536            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2537              :     }
    2538              : 
    2539           31 :     if (!DLT_USER_INITIALIZED) {
    2540            0 :         dlt_vlog(
    2541              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2542            0 :             dlt_user_init_state, dlt_user_freeing);
    2543            0 :         return DLT_RETURN_ERROR;
    2544              :     }
    2545              : 
    2546           31 :     const uint16_t name_size = (name != NULL) ? (uint16_t)(strlen(name) + 1) : 0;
    2547              : 
    2548           31 :     size_t needed_size = length + sizeof(uint16_t);
    2549           31 :     if ((size_t)log->size + needed_size > dlt_user.log_buf_len)
    2550              :         return DLT_RETURN_USER_BUFFER_FULL;
    2551              : 
    2552           29 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2553           29 :         uint32_t type_info = DLT_TYPE_INFO_RAWD;
    2554              : 
    2555           29 :         needed_size += sizeof(uint32_t);  // Type Info field
    2556           29 :         if (with_var_info) {
    2557            6 :             needed_size += sizeof(uint16_t);  // length of name
    2558            6 :             needed_size += name_size;         // the name itself
    2559              : 
    2560            6 :             type_info |= DLT_TYPE_INFO_VARI;
    2561              :         }
    2562           29 :         if ((size_t)log->size + needed_size > dlt_user.log_buf_len)
    2563            0 :             return DLT_RETURN_USER_BUFFER_FULL;
    2564              : 
    2565              :         // Genivi extension: put formatting hints into the unused (for RAWD) TYLE + SCOD fields.
    2566              :         // The SCOD field holds the base (hex or bin); the TYLE field holds the column width (8bit..64bit).
    2567           29 :         if ((type >= DLT_FORMAT_HEX8) && (type <= DLT_FORMAT_HEX64)) {
    2568            8 :             type_info |= DLT_SCOD_HEX;
    2569            8 :             type_info += type;
    2570           21 :         } else if ((type >= DLT_FORMAT_BIN8) && (type <= DLT_FORMAT_BIN16)) {
    2571            4 :             type_info |= DLT_SCOD_BIN;
    2572            4 :             type_info += type - DLT_FORMAT_BIN8 + 1;
    2573              :         }
    2574              : 
    2575           29 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2576           29 :         log->size += (int32_t)sizeof(uint32_t);
    2577              :     }
    2578              : 
    2579           29 :     memcpy(log->buffer + log->size, &length, sizeof(uint16_t));
    2580           29 :     log->size += (int32_t)sizeof(uint16_t);
    2581              : 
    2582           29 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2583           29 :         if (with_var_info) {
    2584              :             // Write length of "name" attribute.
    2585              :             // We assume that the protocol allows zero-sized strings here (which this code will create
    2586              :             // when the input pointer is NULL).
    2587            6 :             memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t));
    2588            6 :             log->size += (int32_t)sizeof(uint16_t);
    2589              : 
    2590              :             // Write name string itself.
    2591              :             // Must not use NULL as source pointer for memcpy. This check assures that.
    2592            6 :             if (name_size != 0) {
    2593            4 :                 memcpy(log->buffer + log->size, name, name_size);
    2594            4 :                 log->size += name_size;
    2595              :             }
    2596              :         }
    2597              :     }
    2598              : 
    2599           29 :     if (data != NULL) {
    2600           27 :         memcpy(log->buffer + log->size, data, length);
    2601           27 :         log->size += length;
    2602           27 :         log->args_num++;
    2603              :     }
    2604              : 
    2605              :     return DLT_RETURN_OK;
    2606              : }
    2607              : 
    2608           13 : DltReturnValue dlt_user_log_write_raw(DltContextData* log, void* data, uint16_t length)
    2609              : {
    2610           13 :     return dlt_user_log_write_raw_internal(log, data, length, DLT_FORMAT_DEFAULT, NULL, false);
    2611              : }
    2612              : 
    2613           19 : DltReturnValue dlt_user_log_write_raw_formatted(DltContextData* log, void* data, uint16_t length, DltFormatType type)
    2614              : {
    2615           19 :     return dlt_user_log_write_raw_internal(log, data, length, type, NULL, false);
    2616              : }
    2617              : 
    2618            3 : DltReturnValue dlt_user_log_write_raw_attr(DltContextData* log, const void* data, uint16_t length, const char* name)
    2619              : {
    2620            3 :     return dlt_user_log_write_raw_internal(log, data, length, DLT_FORMAT_DEFAULT, name, true);
    2621              : }
    2622              : 
    2623            3 : DltReturnValue dlt_user_log_write_raw_formatted_attr(
    2624              :     DltContextData* log, const void* data, uint16_t length, DltFormatType type, const char* name)
    2625              : {
    2626            3 :     return dlt_user_log_write_raw_internal(log, data, length, type, name, true);
    2627              : }
    2628              : 
    2629              : // Generic implementation for all "simple" types, possibly with attributes
    2630        11763 : static DltReturnValue dlt_user_log_write_generic_attr(
    2631              :     DltContextData* log, const void* datap, size_t datalen, uint32_t type_info, const VarInfo* varinfo)
    2632              : {
    2633        11763 :     if (log == NULL)
    2634              :         return DLT_RETURN_WRONG_PARAMETER;
    2635              : 
    2636        11751 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2637            0 :         dlt_vlog(
    2638              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2639            0 :             dlt_user_init_state, dlt_user_freeing);
    2640            0 :         return DLT_RETURN_ERROR;
    2641              :     }
    2642              : 
    2643              :     size_t needed_size = datalen;
    2644        11751 :     if ((size_t)log->size + needed_size > dlt_user.log_buf_len)
    2645              :         return DLT_RETURN_USER_BUFFER_FULL;
    2646              : 
    2647        11749 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2648              :         bool with_var_info = (varinfo != NULL);
    2649              : 
    2650              :         uint16_t name_size;
    2651              :         uint16_t unit_size;
    2652              : 
    2653        11747 :         needed_size += sizeof(uint32_t);  // Type Info field
    2654        11747 :         if (with_var_info) {
    2655           89 :             name_size = (varinfo->name != NULL) ? (uint16_t)(strlen(varinfo->name) + 1) : 0;
    2656           89 :             unit_size = (varinfo->unit != NULL) ? (uint16_t)(strlen(varinfo->unit) + 1) : 0;
    2657              : 
    2658           89 :             needed_size += sizeof(uint16_t);  // length of name
    2659           89 :             needed_size += name_size;         // the name itself
    2660           89 :             if (varinfo->with_unit) {
    2661           86 :                 needed_size += sizeof(uint16_t);  // length of unit
    2662           86 :                 needed_size += unit_size;         // the unit itself
    2663              :             }
    2664              : 
    2665           89 :             type_info |= DLT_TYPE_INFO_VARI;
    2666              :         }
    2667              : 
    2668        11747 :         if ((size_t)log->size + needed_size > dlt_user.log_buf_len)
    2669            0 :             return DLT_RETURN_USER_BUFFER_FULL;
    2670              : 
    2671        11747 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2672        11747 :         log->size += (int32_t)sizeof(uint32_t);
    2673              : 
    2674        11747 :         if (with_var_info) {
    2675              :             // Write lengths of name/unit strings
    2676              :             // We assume here that the protocol allows zero-sized strings here (which occur
    2677              :             // when the input pointers are NULL).
    2678           89 :             memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t));
    2679           89 :             log->size += (int32_t)sizeof(uint16_t);
    2680           89 :             if (varinfo->with_unit) {
    2681           86 :                 memcpy(log->buffer + log->size, &unit_size, sizeof(uint16_t));
    2682           86 :                 log->size += (int32_t)sizeof(uint16_t);
    2683              :             }
    2684              : 
    2685              :             // Write name/unit strings themselves
    2686              :             // Must not use NULL as source pointer for memcpy.
    2687           89 :             if (name_size != 0) {
    2688           64 :                 memcpy(log->buffer + log->size, varinfo->name, name_size);
    2689           64 :                 log->size += (int32_t)name_size;
    2690              :             }
    2691           89 :             if (unit_size != 0) {
    2692           62 :                 memcpy(log->buffer + log->size, varinfo->unit, unit_size);
    2693           62 :                 log->size += (int32_t)unit_size;
    2694              :             }
    2695              :         }
    2696              :     }
    2697              : 
    2698        11749 :     memcpy(log->buffer + log->size, datap, datalen);
    2699        11749 :     log->size += (int32_t)datalen;
    2700              : 
    2701        11749 :     log->args_num++;
    2702              : 
    2703        11749 :     return DLT_RETURN_OK;
    2704              : }
    2705              : 
    2706              : // Generic implementation for all "simple" types
    2707          112 : static DltReturnValue dlt_user_log_write_generic_formatted(
    2708              :     DltContextData* log, const void* datap, size_t datalen, uint32_t type_info, DltFormatType type)
    2709              : {
    2710          112 :     if (log == NULL)
    2711              :         return DLT_RETURN_WRONG_PARAMETER;
    2712              : 
    2713              :     /* Have to cast type to signed type because some compilers assume that DltFormatType is unsigned and issue a warning
    2714              :      */
    2715           84 :     if (((int16_t)type < DLT_FORMAT_DEFAULT) || (type >= DLT_FORMAT_MAX)) {
    2716            0 :         dlt_vlog(LOG_ERR, "Format type %d is outside valid range", type);
    2717            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2718              :     }
    2719              : 
    2720           84 :     if (!DLT_USER_INITIALIZED) {
    2721            0 :         dlt_vlog(
    2722              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2723            0 :             dlt_user_init_state, dlt_user_freeing);
    2724            0 :         return DLT_RETURN_ERROR;
    2725              :     }
    2726              : 
    2727              :     size_t needed_size = datalen;
    2728           84 :     if ((size_t)log->size + needed_size > dlt_user.log_buf_len)
    2729              :         return DLT_RETURN_USER_BUFFER_FULL;
    2730              : 
    2731           84 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2732           84 :         needed_size += sizeof(uint32_t);  // Type Info field
    2733           84 :         if ((size_t)log->size + needed_size > dlt_user.log_buf_len)
    2734              :             return DLT_RETURN_USER_BUFFER_FULL;
    2735              : 
    2736              :         // Genivi extension: put formatting hints into the unused (for SINT/UINT/FLOA) SCOD field.
    2737           84 :         if ((type >= DLT_FORMAT_HEX8) && (type <= DLT_FORMAT_HEX64))
    2738           48 :             type_info |= DLT_SCOD_HEX;
    2739              : 
    2740           36 :         else if ((type >= DLT_FORMAT_BIN8) && (type <= DLT_FORMAT_BIN16))
    2741           24 :             type_info |= DLT_SCOD_BIN;
    2742              : 
    2743           84 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2744           84 :         log->size += (int32_t)sizeof(uint32_t);
    2745              :     }
    2746              : 
    2747           84 :     memcpy(log->buffer + log->size, datap, datalen);
    2748           84 :     log->size += (int32_t)datalen;
    2749           84 :     log->args_num++;
    2750              : 
    2751           84 :     return DLT_RETURN_OK;
    2752              : }
    2753              : 
    2754            7 : DltReturnValue dlt_user_log_write_float32(DltContextData* log, float32_t data)
    2755              : {
    2756              :     if (sizeof(float32_t) != 4)
    2757              :         return DLT_RETURN_ERROR;
    2758              : 
    2759              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
    2760            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float32_t), type_info, NULL);
    2761              : }
    2762              : 
    2763            7 : DltReturnValue dlt_user_log_write_float64(DltContextData* log, float64_t data)
    2764              : {
    2765              :     if (sizeof(float64_t) != 8)
    2766              :         return DLT_RETURN_ERROR;
    2767              : 
    2768              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
    2769            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float64_t), type_info, NULL);
    2770              : }
    2771              : 
    2772            7 : DltReturnValue dlt_user_log_write_float32_attr(DltContextData* log, float32_t data, const char* name, const char* unit)
    2773              : {
    2774              :     if (sizeof(float32_t) != 4)
    2775              :         return DLT_RETURN_ERROR;
    2776              : 
    2777              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
    2778            7 :     const VarInfo var_info = {name, unit, true};
    2779            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float32_t), type_info, &var_info);
    2780              : }
    2781              : 
    2782            7 : DltReturnValue dlt_user_log_write_float64_attr(DltContextData* log, float64_t data, const char* name, const char* unit)
    2783              : {
    2784              :     if (sizeof(float64_t) != 8)
    2785              :         return DLT_RETURN_ERROR;
    2786              : 
    2787              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
    2788            7 :     const VarInfo var_info = {name, unit, true};
    2789            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float64_t), type_info, &var_info);
    2790              : }
    2791              : 
    2792           35 : DltReturnValue dlt_user_log_write_uint(DltContextData* log, unsigned int data)
    2793              : {
    2794           35 :     if (log == NULL)
    2795              :         return DLT_RETURN_WRONG_PARAMETER;
    2796              : 
    2797           34 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2798            0 :         dlt_vlog(
    2799              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2800            0 :             dlt_user_init_state, dlt_user_freeing);
    2801            0 :         return DLT_RETURN_ERROR;
    2802              :     }
    2803              : 
    2804              :     switch (sizeof(unsigned int)) {
    2805              :     case 1: {
    2806              :         return dlt_user_log_write_uint8(log, (uint8_t)data);
    2807              :         break;
    2808              :     }
    2809              :     case 2: {
    2810              :         return dlt_user_log_write_uint16(log, (uint16_t)data);
    2811              :         break;
    2812              :     }
    2813           34 :     case 4: {
    2814           34 :         return dlt_user_log_write_uint32(log, (uint32_t)data);
    2815              :         break;
    2816              :     }
    2817              :     case 8: {
    2818              :         return dlt_user_log_write_uint64(log, (uint64_t)data);
    2819              :         break;
    2820              :     }
    2821              :     default: {
    2822              :         return DLT_RETURN_ERROR;
    2823              :         break;
    2824              :     }
    2825              :     }
    2826              : 
    2827              :     return DLT_RETURN_OK;
    2828              : }
    2829              : 
    2830            4 : DltReturnValue dlt_user_log_write_uint8(DltContextData* log, uint8_t data)
    2831              : {
    2832              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
    2833            4 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, NULL);
    2834              : }
    2835              : 
    2836            4 : DltReturnValue dlt_user_log_write_uint16(DltContextData* log, uint16_t data)
    2837              : {
    2838              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
    2839            4 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint16_t), type_info, NULL);
    2840              : }
    2841              : 
    2842        11580 : DltReturnValue dlt_user_log_write_uint32(DltContextData* log, uint32_t data)
    2843              : {
    2844              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
    2845        11580 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint32_t), type_info, NULL);
    2846              : }
    2847              : 
    2848            4 : DltReturnValue dlt_user_log_write_uint64(DltContextData* log, uint64_t data)
    2849              : {
    2850              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
    2851            4 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint64_t), type_info, NULL);
    2852              : }
    2853              : 
    2854            7 : DltReturnValue dlt_user_log_write_uint_attr(DltContextData* log, unsigned int data, const char* name, const char* unit)
    2855              : {
    2856            7 :     if (log == NULL)
    2857              :         return DLT_RETURN_WRONG_PARAMETER;
    2858              : 
    2859            7 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2860            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __func__);
    2861            0 :         return DLT_RETURN_ERROR;
    2862              :     }
    2863              : 
    2864              :     switch (sizeof(unsigned int)) {
    2865              :     case 1: {
    2866              :         return dlt_user_log_write_uint8_attr(log, (uint8_t)data, name, unit);
    2867              :         break;
    2868              :     }
    2869              :     case 2: {
    2870              :         return dlt_user_log_write_uint16_attr(log, (uint16_t)data, name, unit);
    2871              :         break;
    2872              :     }
    2873            7 :     case 4: {
    2874            7 :         return dlt_user_log_write_uint32_attr(log, (uint32_t)data, name, unit);
    2875              :         break;
    2876              :     }
    2877              :     case 8: {
    2878              :         return dlt_user_log_write_uint64_attr(log, (uint64_t)data, name, unit);
    2879              :         break;
    2880              :     }
    2881              :     default: {
    2882              :         return DLT_RETURN_ERROR;
    2883              :         break;
    2884              :     }
    2885              :     }
    2886              : 
    2887              :     return DLT_RETURN_OK;
    2888              : }
    2889              : 
    2890            7 : DltReturnValue dlt_user_log_write_uint8_attr(DltContextData* log, uint8_t data, const char* name, const char* unit)
    2891              : {
    2892              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
    2893            7 :     const VarInfo var_info = {name, unit, true};
    2894            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, &var_info);
    2895              : }
    2896              : 
    2897            7 : DltReturnValue dlt_user_log_write_uint16_attr(DltContextData* log, uint16_t data, const char* name, const char* unit)
    2898              : {
    2899              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
    2900            7 :     const VarInfo var_info = {name, unit, true};
    2901            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint16_t), type_info, &var_info);
    2902              : }
    2903              : 
    2904           18 : DltReturnValue dlt_user_log_write_uint32_attr(DltContextData* log, uint32_t data, const char* name, const char* unit)
    2905              : {
    2906              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
    2907           18 :     const VarInfo var_info = {name, unit, true};
    2908           18 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint32_t), type_info, &var_info);
    2909              : }
    2910              : 
    2911            7 : DltReturnValue dlt_user_log_write_uint64_attr(DltContextData* log, uint64_t data, const char* name, const char* unit)
    2912              : {
    2913              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
    2914            7 :     const VarInfo var_info = {name, unit, true};
    2915            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint64_t), type_info, &var_info);
    2916              : }
    2917              : 
    2918           28 : DltReturnValue dlt_user_log_write_uint8_formatted(DltContextData* log, uint8_t data, DltFormatType type)
    2919              : {
    2920              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
    2921           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint8_t), type_info, type);
    2922              : }
    2923              : 
    2924           28 : DltReturnValue dlt_user_log_write_uint16_formatted(DltContextData* log, uint16_t data, DltFormatType type)
    2925              : {
    2926              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
    2927           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint16_t), type_info, type);
    2928              : }
    2929              : 
    2930           28 : DltReturnValue dlt_user_log_write_uint32_formatted(DltContextData* log, uint32_t data, DltFormatType type)
    2931              : {
    2932              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
    2933           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint32_t), type_info, type);
    2934              : }
    2935              : 
    2936           28 : DltReturnValue dlt_user_log_write_uint64_formatted(DltContextData* log, uint64_t data, DltFormatType type)
    2937              : {
    2938              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
    2939           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint64_t), type_info, type);
    2940              : }
    2941              : 
    2942            0 : DltReturnValue dlt_user_log_write_ptr(DltContextData* log, void* data)
    2943              : {
    2944            0 :     if (log == NULL)
    2945              :         return DLT_RETURN_WRONG_PARAMETER;
    2946              : 
    2947            0 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2948            0 :         dlt_vlog(LOG_WARNING, "%s user_initialised false\n", __func__);
    2949            0 :         return DLT_RETURN_ERROR;
    2950              :     }
    2951              : 
    2952              :     switch (sizeof(void*)) {
    2953              :     case 4:
    2954              :         return dlt_user_log_write_uint32_formatted(log, (uint32_t)(uintptr_t)data, DLT_FORMAT_HEX32);
    2955              :         break;
    2956            0 :     case 8:
    2957            0 :         return dlt_user_log_write_uint64_formatted(log, (uintptr_t)data, DLT_FORMAT_HEX64);
    2958              :         break;
    2959              :     default:; /* skip */
    2960              :     }
    2961              : 
    2962              :     return DLT_RETURN_OK;
    2963              : }
    2964              : 
    2965           37 : DltReturnValue dlt_user_log_write_int(DltContextData* log, int data)
    2966              : {
    2967           37 :     if (log == NULL)
    2968              :         return DLT_RETURN_WRONG_PARAMETER;
    2969              : 
    2970           36 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2971            0 :         dlt_vlog(
    2972              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    2973            0 :             dlt_user_init_state, dlt_user_freeing);
    2974            0 :         return DLT_RETURN_ERROR;
    2975              :     }
    2976              : 
    2977              :     switch (sizeof(int)) {
    2978              :     case 1: {
    2979              :         return dlt_user_log_write_int8(log, (int8_t)data);
    2980              :         break;
    2981              :     }
    2982              :     case 2: {
    2983              :         return dlt_user_log_write_int16(log, (int16_t)data);
    2984              :         break;
    2985              :     }
    2986           36 :     case 4: {
    2987           36 :         return dlt_user_log_write_int32(log, (int32_t)data);
    2988              :         break;
    2989              :     }
    2990              :     case 8: {
    2991              :         return dlt_user_log_write_int64(log, (int64_t)data);
    2992              :         break;
    2993              :     }
    2994              :     default: {
    2995              :         return DLT_RETURN_ERROR;
    2996              :         break;
    2997              :     }
    2998              :     }
    2999              : 
    3000              :     return DLT_RETURN_OK;
    3001              : }
    3002              : 
    3003            6 : DltReturnValue dlt_user_log_write_int8(DltContextData* log, int8_t data)
    3004              : {
    3005              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
    3006            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int8_t), type_info, NULL);
    3007              : }
    3008              : 
    3009            6 : DltReturnValue dlt_user_log_write_int16(DltContextData* log, int16_t data)
    3010              : {
    3011              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
    3012            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int16_t), type_info, NULL);
    3013              : }
    3014              : 
    3015           42 : DltReturnValue dlt_user_log_write_int32(DltContextData* log, int32_t data)
    3016              : {
    3017              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
    3018           42 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int32_t), type_info, NULL);
    3019              : }
    3020              : 
    3021            6 : DltReturnValue dlt_user_log_write_int64(DltContextData* log, int64_t data)
    3022              : {
    3023              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
    3024            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int64_t), type_info, NULL);
    3025              : }
    3026              : 
    3027            7 : DltReturnValue dlt_user_log_write_int_attr(DltContextData* log, int data, const char* name, const char* unit)
    3028              : {
    3029            7 :     if (log == NULL)
    3030              :         return DLT_RETURN_WRONG_PARAMETER;
    3031              : 
    3032            7 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    3033            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __func__);
    3034            0 :         return DLT_RETURN_ERROR;
    3035              :     }
    3036              : 
    3037              :     switch (sizeof(int)) {
    3038              :     case 1: {
    3039              :         return dlt_user_log_write_int8_attr(log, (int8_t)data, name, unit);
    3040              :         break;
    3041              :     }
    3042              :     case 2: {
    3043              :         return dlt_user_log_write_int16_attr(log, (int16_t)data, name, unit);
    3044              :         break;
    3045              :     }
    3046            7 :     case 4: {
    3047            7 :         return dlt_user_log_write_int32_attr(log, (int32_t)data, name, unit);
    3048              :         break;
    3049              :     }
    3050              :     case 8: {
    3051              :         return dlt_user_log_write_int64_attr(log, (int64_t)data, name, unit);
    3052              :         break;
    3053              :     }
    3054              :     default: {
    3055              :         return DLT_RETURN_ERROR;
    3056              :         break;
    3057              :     }
    3058              :     }
    3059              : 
    3060              :     return DLT_RETURN_OK;
    3061              : }
    3062              : 
    3063            7 : DltReturnValue dlt_user_log_write_int8_attr(DltContextData* log, int8_t data, const char* name, const char* unit)
    3064              : {
    3065              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
    3066            7 :     const VarInfo var_info = {name, unit, true};
    3067            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int8_t), type_info, &var_info);
    3068              : }
    3069              : 
    3070            7 : DltReturnValue dlt_user_log_write_int16_attr(DltContextData* log, int16_t data, const char* name, const char* unit)
    3071              : {
    3072              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
    3073            7 :     const VarInfo var_info = {name, unit, true};
    3074            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int16_t), type_info, &var_info);
    3075              : }
    3076              : 
    3077           14 : DltReturnValue dlt_user_log_write_int32_attr(DltContextData* log, int32_t data, const char* name, const char* unit)
    3078              : {
    3079              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
    3080           14 :     const VarInfo var_info = {name, unit, true};
    3081           14 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int32_t), type_info, &var_info);
    3082              : }
    3083              : 
    3084            7 : DltReturnValue dlt_user_log_write_int64_attr(DltContextData* log, int64_t data, const char* name, const char* unit)
    3085              : {
    3086              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
    3087            7 :     const VarInfo var_info = {name, unit, true};
    3088            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int64_t), type_info, &var_info);
    3089              : }
    3090              : 
    3091            6 : DltReturnValue dlt_user_log_write_bool(DltContextData* log, uint8_t data)
    3092              : {
    3093              :     uint32_t type_info = DLT_TYPE_INFO_BOOL | DLT_TYLE_8BIT;
    3094            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, NULL);
    3095              : }
    3096              : 
    3097            3 : DltReturnValue dlt_user_log_write_bool_attr(DltContextData* log, uint8_t data, const char* name)
    3098              : {
    3099              :     uint32_t type_info = DLT_TYPE_INFO_BOOL | DLT_TYLE_8BIT;
    3100            3 :     const VarInfo var_info = {name, NULL, false};
    3101            3 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, &var_info);
    3102              : }
    3103              : 
    3104        11686 : DltReturnValue dlt_user_log_write_string(DltContextData* log, const char* text)
    3105              : {
    3106        11686 :     return dlt_user_log_write_string_utils_attr(log, text, ASCII_STRING, NULL, false);
    3107              : }
    3108              : 
    3109            7 : DltReturnValue dlt_user_log_write_string_attr(DltContextData* log, const char* text, const char* name)
    3110              : {
    3111            7 :     return dlt_user_log_write_string_utils_attr(log, text, ASCII_STRING, name, true);
    3112              : }
    3113              : 
    3114            2 : DltReturnValue dlt_user_log_write_sized_string(DltContextData* log, const char* text, uint16_t length)
    3115              : {
    3116            2 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, ASCII_STRING, NULL, false);
    3117              : }
    3118              : 
    3119            6 : DltReturnValue dlt_user_log_write_sized_string_attr(
    3120              :     DltContextData* log, const char* text, uint16_t length, const char* name)
    3121              : {
    3122            6 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, ASCII_STRING, name, true);
    3123              : }
    3124              : 
    3125            7 : DltReturnValue dlt_user_log_write_constant_string(DltContextData* log, const char* text)
    3126              : {
    3127              :     /* Send parameter only in verbose mode */
    3128            8 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_string(log, text) : DLT_RETURN_OK;
    3129              : }
    3130              : 
    3131            5 : DltReturnValue dlt_user_log_write_constant_string_attr(DltContextData* log, const char* text, const char* name)
    3132              : {
    3133              :     /* Send parameter only in verbose mode */
    3134            6 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_string_attr(log, text, name) :
    3135              :                                                          DLT_RETURN_OK;
    3136              : }
    3137              : 
    3138            1 : DltReturnValue dlt_user_log_write_sized_constant_string(DltContextData* log, const char* text, uint16_t length)
    3139              : {
    3140              :     /* Send parameter only in verbose mode */
    3141            1 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_string(log, text, length) :
    3142              :                                                          DLT_RETURN_OK;
    3143              : }
    3144              : 
    3145            3 : DltReturnValue dlt_user_log_write_sized_constant_string_attr(
    3146              :     DltContextData* log, const char* text, uint16_t length, const char* name)
    3147              : {
    3148              :     /* Send parameter only in verbose mode */
    3149            3 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_string_attr(log, text, length, name) :
    3150              :                                                          DLT_RETURN_OK;
    3151              : }
    3152              : 
    3153           21 : DltReturnValue dlt_user_log_write_utf8_string(DltContextData* log, const char* text)
    3154              : {
    3155           21 :     return dlt_user_log_write_string_utils_attr(log, text, UTF8_STRING, NULL, false);
    3156              : }
    3157              : 
    3158            7 : DltReturnValue dlt_user_log_write_utf8_string_attr(DltContextData* log, const char* text, const char* name)
    3159              : {
    3160            7 :     return dlt_user_log_write_string_utils_attr(log, text, UTF8_STRING, name, true);
    3161              : }
    3162              : 
    3163            8 : DltReturnValue dlt_user_log_write_sized_utf8_string(DltContextData* log, const char* text, uint16_t length)
    3164              : {
    3165            8 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, UTF8_STRING, NULL, false);
    3166              : }
    3167              : 
    3168            7 : DltReturnValue dlt_user_log_write_sized_utf8_string_attr(
    3169              :     DltContextData* log, const char* text, uint16_t length, const char* name)
    3170              : {
    3171            7 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, UTF8_STRING, name, true);
    3172              : }
    3173              : 
    3174            5 : DltReturnValue dlt_user_log_write_constant_utf8_string(DltContextData* log, const char* text)
    3175              : {
    3176              :     /* Send parameter only in verbose mode */
    3177            5 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_utf8_string(log, text) : DLT_RETURN_OK;
    3178              : }
    3179              : 
    3180            4 : DltReturnValue dlt_user_log_write_constant_utf8_string_attr(DltContextData* log, const char* text, const char* name)
    3181              : {
    3182              :     /* Send parameter only in verbose mode */
    3183            4 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_utf8_string_attr(log, text, name) :
    3184              :                                                          DLT_RETURN_OK;
    3185              : }
    3186              : 
    3187            5 : DltReturnValue dlt_user_log_write_sized_constant_utf8_string(DltContextData* log, const char* text, uint16_t length)
    3188              : {
    3189              :     /* Send parameter only in verbose mode */
    3190            5 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_utf8_string(log, text, length) :
    3191              :                                                          DLT_RETURN_OK;
    3192              : }
    3193              : 
    3194            4 : DltReturnValue dlt_user_log_write_sized_constant_utf8_string_attr(
    3195              :     DltContextData* log, const char* text, uint16_t length, const char* name)
    3196              : {
    3197              :     /* Send parameter only in verbose mode */
    3198            4 :     return is_verbose_mode(dlt_user.verbose_mode, log) ?
    3199            4 :                dlt_user_log_write_sized_utf8_string_attr(log, text, length, name) :
    3200              :                DLT_RETURN_OK;
    3201              : }
    3202              : 
    3203        11729 : static DltReturnValue dlt_user_log_write_sized_string_utils_attr(
    3204              :     DltContextData* log, const char* text, size_t length, const enum StringType type, const char* name,
    3205              :     bool with_var_info)
    3206              : {
    3207        11729 :     if ((log == NULL) || (text == NULL))
    3208              :         return DLT_RETURN_WRONG_PARAMETER;
    3209              : 
    3210        11720 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    3211            0 :         dlt_vlog(
    3212              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    3213            0 :             dlt_user_init_state, dlt_user_freeing);
    3214            0 :         return DLT_RETURN_ERROR;
    3215              :     }
    3216              : 
    3217        11720 :     const uint16_t name_size = (name != NULL) ? (uint16_t)(strlen(name) + 1) : 0;
    3218              : 
    3219        11720 :     size_t arg_size = (size_t)(length + 1);
    3220              : 
    3221        11720 :     size_t new_log_size = (size_t)log->size + arg_size + sizeof(uint16_t);
    3222              : 
    3223        11720 :     uint32_t type_info = 0;
    3224              : 
    3225        11720 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    3226        11720 :         new_log_size += sizeof(uint32_t);
    3227        11720 :         if (with_var_info) {
    3228           21 :             new_log_size += sizeof(uint16_t);  // length of "name" attribute
    3229           21 :             new_log_size += name_size;         // the "name" attribute itself
    3230              : 
    3231           21 :             type_info |= DLT_TYPE_INFO_VARI;
    3232              :         }
    3233              :     }
    3234              : 
    3235              :     size_t str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1;
    3236              :     size_t max_payload_str_msg;
    3237              :     DltReturnValue ret = DLT_RETURN_OK;
    3238              : 
    3239              :     /* Check log size condition */
    3240        11720 :     if (new_log_size > dlt_user.log_buf_len) {
    3241              :         ret = DLT_RETURN_USER_BUFFER_FULL;
    3242              : 
    3243              :         /* Re-calculate arg_size */
    3244           21 :         arg_size = (size_t)(dlt_user.log_buf_len - (size_t)log->size - sizeof(uint16_t));
    3245              : 
    3246           21 :         size_t min_payload_str_truncate_msg = (size_t)log->size + str_truncate_message_length + sizeof(uint16_t);
    3247              : 
    3248              :         if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    3249           21 :             min_payload_str_truncate_msg += sizeof(uint32_t);
    3250           21 :             arg_size -= (size_t)sizeof(uint32_t);
    3251           21 :             if (with_var_info) {
    3252            0 :                 min_payload_str_truncate_msg += sizeof(uint16_t) + name_size;
    3253            0 :                 arg_size -= sizeof(uint16_t) + name_size;
    3254              :             }
    3255              :         }
    3256              : 
    3257              :         /* Return when dlt_user.log_buf_len does not have enough space for min_payload_str_truncate_msg */
    3258           21 :         if (min_payload_str_truncate_msg > dlt_user.log_buf_len) {
    3259            1 :             dlt_vlog(LOG_WARNING, "%s not enough minimum space to store data\n", __func__);
    3260            1 :             return ret;
    3261              :         }
    3262              : 
    3263              :         /* Calculate the maximum size of string will be copied after truncate */
    3264           20 :         max_payload_str_msg = dlt_user.log_buf_len - min_payload_str_truncate_msg;
    3265              : 
    3266           20 :         if (type == UTF8_STRING) {
    3267              :             /**
    3268              :              * Adjust the lengh to truncate one utf8 character corectly
    3269              :              * refer: https://en.wikipedia.org/wiki/UTF-8
    3270              :              * one utf8 character will have maximum 4 bytes then maximum bytes will be truncate additional is 3
    3271              :              */
    3272           12 :             const char* tmp = (text + max_payload_str_msg - 3);
    3273              :             uint16_t reduce_size = 0;
    3274              : 
    3275           12 :             if (tmp[2] & 0x80) {
    3276              :                 /* Is the last byte of truncated text is the first byte in multi-byte sequence (utf8 2 bytes) */
    3277            9 :                 if (tmp[2] & 0x40)
    3278              :                     reduce_size = 1;
    3279              :                 /* Is the next to last byte of truncated text is the first byte in multi-byte sequence (utf8 3 bytes) */
    3280            6 :                 else if ((tmp[1] & 0xe0) == 0xe0)
    3281              :                     reduce_size = 2;
    3282              :                 /* utf8 4 bytes */
    3283            3 :                 else if ((tmp[0] & 0xf0) == 0xf0)
    3284              :                     reduce_size = 3;
    3285              :             }
    3286              : 
    3287           12 :             max_payload_str_msg -= reduce_size;
    3288           12 :             arg_size -= (size_t)reduce_size;
    3289              :         }
    3290              :     }
    3291              : 
    3292              :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    3293        11719 :         switch (type) {
    3294        11694 :         case ASCII_STRING:
    3295        11694 :             type_info |= DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
    3296        11694 :             break;
    3297           25 :         case UTF8_STRING:
    3298           25 :             type_info |= DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
    3299           25 :             break;
    3300              :         default:
    3301              :             /* Do nothing */
    3302              :             break;
    3303              :         }
    3304              : 
    3305        11719 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    3306        11719 :         log->size += (int32_t)sizeof(uint32_t);
    3307              :     }
    3308              : 
    3309        11719 :     memcpy(log->buffer + log->size, &arg_size, sizeof(uint16_t));
    3310        11719 :     log->size += (int32_t)sizeof(uint16_t);
    3311              : 
    3312        11719 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    3313        11719 :         if (with_var_info) {
    3314              :             // Write length of "name" attribute.
    3315              :             // We assume that the protocol allows zero-sized strings here (which this code will create
    3316              :             // when the input pointer is NULL).
    3317           21 :             memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t));
    3318           21 :             log->size += (int32_t)sizeof(uint16_t);
    3319              : 
    3320              :             // Write name string itself.
    3321              :             // Must not use NULL as source pointer for memcpy. This check assures that.
    3322           21 :             if (name_size != 0) {
    3323           15 :                 memcpy(log->buffer + log->size, name, name_size);
    3324           15 :                 log->size += name_size;
    3325              :             }
    3326              :         }
    3327              :     }
    3328              : 
    3329        11719 :     switch (ret) {
    3330        11699 :     case DLT_RETURN_OK: {
    3331              :         /* Whole string will be copied */
    3332        11699 :         memcpy(log->buffer + log->size, text, length);
    3333              :         /* The input string might not be null-terminated, so we're doing that by ourselves */
    3334        11699 :         log->buffer[(size_t)log->size + length] = '\0';
    3335        11699 :         log->size += (int32_t)arg_size;
    3336        11699 :         break;
    3337              :     }
    3338           20 :     case DLT_RETURN_USER_BUFFER_FULL: {
    3339              :         /* Only copy partial string */
    3340           20 :         memcpy(log->buffer + log->size, text, max_payload_str_msg);
    3341           20 :         log->size += (int32_t)max_payload_str_msg;
    3342              : 
    3343              :         /* Append string truncate the input string */
    3344           20 :         memcpy(log->buffer + log->size, STR_TRUNCATED_MESSAGE, str_truncate_message_length);
    3345           20 :         log->size += (int32_t)str_truncate_message_length;
    3346           20 :         break;
    3347              :     }
    3348              :     default:
    3349              :         /* Do nothing */
    3350              :         break;
    3351              :     }
    3352              : 
    3353        11719 :     log->args_num++;
    3354              : 
    3355        11719 :     return ret;
    3356              : }
    3357              : 
    3358        11721 : static DltReturnValue dlt_user_log_write_string_utils_attr(
    3359              :     DltContextData* log, const char* text, const enum StringType type, const char* name, bool with_var_info)
    3360              : {
    3361        11721 :     if ((log == NULL) || (text == NULL))
    3362              :         return DLT_RETURN_WRONG_PARAMETER;
    3363              : 
    3364        11706 :     size_t length = strlen(text);
    3365        11706 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, type, name, with_var_info);
    3366              : }
    3367              : 
    3368            0 : DltReturnValue dlt_register_injection_callback_with_id(
    3369              :     DltContext* handle, uint32_t service_id, dlt_injection_callback_id dlt_injection_cbk, void* priv)
    3370              : {
    3371              :     DltContextData log;
    3372              :     uint32_t i, j, k;
    3373              :     int found = 0;
    3374              : 
    3375              :     DltUserInjectionCallback* old;
    3376              : 
    3377            0 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3378              :         return DLT_RETURN_ERROR;
    3379              : 
    3380            0 :     if (service_id < DLT_USER_INJECTION_MIN)
    3381              :         return DLT_RETURN_WRONG_PARAMETER;
    3382              : 
    3383              :     /* This function doesn't make sense storing to local file is choosen;
    3384              :      * so terminate this function */
    3385            0 :     if (dlt_user.dlt_is_file)
    3386              :         return DLT_RETURN_OK;
    3387              : 
    3388            0 :     dlt_mutex_lock();
    3389              : 
    3390            0 :     if (dlt_user.dlt_ll_ts == NULL) {
    3391            0 :         dlt_mutex_unlock();
    3392            0 :         return DLT_RETURN_OK;
    3393              :     }
    3394              : 
    3395              :     /* Insert callback in corresponding table */
    3396            0 :     i = (uint32_t)handle->log_level_pos;
    3397              : 
    3398              :     /* Insert each service_id only once */
    3399            0 :     for (k = 0; k < dlt_user.dlt_ll_ts[i].nrcallbacks; k++)
    3400            0 :         if ((dlt_user.dlt_ll_ts[i].injection_table)
    3401            0 :             && (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id)) {
    3402              :             found = 1;
    3403              :             break;
    3404              :         }
    3405              : 
    3406            0 :     if (found) {
    3407              :         j = k;
    3408              :     } else {
    3409              :         j = dlt_user.dlt_ll_ts[i].nrcallbacks;
    3410              : 
    3411              :         /* Allocate or expand injection table */
    3412            0 :         if (dlt_user.dlt_ll_ts[i].injection_table == NULL) {
    3413            0 :             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*)malloc(sizeof(DltUserInjectionCallback));
    3414              : 
    3415            0 :             if (dlt_user.dlt_ll_ts[i].injection_table == NULL) {
    3416            0 :                 dlt_mutex_unlock();
    3417            0 :                 return DLT_RETURN_ERROR;
    3418              :             }
    3419              :         } else {
    3420              :             old = dlt_user.dlt_ll_ts[i].injection_table;
    3421            0 :             dlt_user.dlt_ll_ts[i].injection_table =
    3422            0 :                 (DltUserInjectionCallback*)malloc(sizeof(DltUserInjectionCallback) * (j + 1));
    3423              : 
    3424            0 :             if (dlt_user.dlt_ll_ts[i].injection_table == NULL) {
    3425            0 :                 dlt_user.dlt_ll_ts[i].injection_table = old;
    3426            0 :                 dlt_mutex_unlock();
    3427            0 :                 return DLT_RETURN_ERROR;
    3428              :             }
    3429              : 
    3430            0 :             memcpy(dlt_user.dlt_ll_ts[i].injection_table, old, sizeof(DltUserInjectionCallback) * j);
    3431            0 :             free(old);
    3432              :         }
    3433              : 
    3434            0 :         dlt_user.dlt_ll_ts[i].nrcallbacks++;
    3435              :     }
    3436              : 
    3437              :     /* Store service_id and corresponding function pointer for callback function */
    3438            0 :     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
    3439              : 
    3440            0 :     if (priv == NULL) {
    3441              :         /* Use union to convert between function pointer types without violating ISO C */
    3442              :         dlt_injection_callback_internal callback_internal;
    3443              :         callback_internal.with_id = dlt_injection_cbk;
    3444            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = callback_internal.without_id;
    3445            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback_with_id = NULL;
    3446            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].data = NULL;
    3447              :     } else {
    3448            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = NULL;
    3449            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback_with_id = dlt_injection_cbk;
    3450            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].data = priv;
    3451              :     }
    3452              : 
    3453            0 :     dlt_mutex_unlock();
    3454              : 
    3455            0 :     return DLT_RETURN_OK;
    3456              : }
    3457              : 
    3458            0 : DltReturnValue dlt_register_injection_callback(
    3459              :     DltContext* handle, uint32_t service_id,
    3460              :     int (*dlt_injection_callback_fn)(uint32_t service_id, void* data, uint32_t length))
    3461              : {
    3462              :     /* Convert dlt_injection_callback to dlt_injection_callback_id using union */
    3463              :     dlt_injection_callback_internal callback_internal;
    3464              :     callback_internal.without_id = dlt_injection_callback_fn;
    3465            0 :     return dlt_register_injection_callback_with_id(handle, service_id, callback_internal.with_id, NULL);
    3466              : }
    3467              : 
    3468            1 : DltReturnValue dlt_register_log_level_changed_callback(
    3469              :     DltContext* handle,
    3470              :     void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE], uint8_t log_level, uint8_t trace_status))
    3471              : {
    3472              :     DltContextData log;
    3473              :     uint32_t i;
    3474              : 
    3475            1 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3476              :         return DLT_RETURN_ERROR;
    3477              : 
    3478              :     /* This function doesn't make sense storing to local file is choosen;
    3479              :      * so terminate this function */
    3480            1 :     if (dlt_user.dlt_is_file)
    3481              :         return DLT_RETURN_OK;
    3482              : 
    3483            1 :     dlt_mutex_lock();
    3484              : 
    3485            1 :     if (dlt_user.dlt_ll_ts == NULL) {
    3486            0 :         dlt_mutex_unlock();
    3487            0 :         return DLT_RETURN_OK;
    3488              :     }
    3489              : 
    3490              :     /* Insert callback in corresponding table */
    3491            1 :     i = (uint32_t)handle->log_level_pos;
    3492              : 
    3493              :     /* Store new callback function */
    3494            1 :     dlt_user.dlt_ll_ts[i].log_level_changed_callback = dlt_log_level_changed_callback;
    3495              : 
    3496            1 :     dlt_mutex_unlock();
    3497              : 
    3498            1 :     return DLT_RETURN_OK;
    3499              : }
    3500              : 
    3501            0 : DltReturnValue dlt_register_log_level_changed_callback_v2(
    3502              :     DltContext* handle,
    3503              :     void (*dlt_log_level_changed_callback_v2)(char* context_id, uint8_t log_level, uint8_t trace_status))
    3504              : {
    3505              :     DltContextData log;
    3506              :     uint32_t i;
    3507              : 
    3508            0 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3509              :         return DLT_RETURN_ERROR;
    3510              : 
    3511              :     /* This function doesn't make sense storing to local file is choosen;
    3512              :      * so terminate this function */
    3513            0 :     if (dlt_user.dlt_is_file)
    3514              :         return DLT_RETURN_OK;
    3515              : 
    3516            0 :     dlt_mutex_lock();
    3517              : 
    3518            0 :     if (dlt_user.dlt_ll_ts == NULL) {
    3519            0 :         dlt_mutex_unlock();
    3520            0 :         return DLT_RETURN_OK;
    3521              :     }
    3522              : 
    3523              :     /* Insert callback in corresponding table */
    3524            0 :     i = (uint32_t)handle->log_level_pos;
    3525              : 
    3526              :     /* Store new callback function */
    3527            0 :     dlt_user.dlt_ll_ts[i].log_level_changed_callback_v2 = dlt_log_level_changed_callback_v2;
    3528              : 
    3529            0 :     dlt_mutex_unlock();
    3530              : 
    3531            0 :     return DLT_RETURN_OK;
    3532              : }
    3533              : 
    3534              : /**
    3535              :  * NW Trace related
    3536              :  */
    3537              : 
    3538              : #ifdef DLT_NETWORK_TRACE_ENABLE
    3539            0 : int check_buffer(void)
    3540              : {
    3541              :     int total_size, used_size;
    3542            0 :     dlt_user_check_buffer(&total_size, &used_size);
    3543              : 
    3544            0 :     return (total_size - used_size < total_size / 2) ? -1 : 1;
    3545              : }
    3546              : 
    3547              : /**
    3548              :  * Send the start of a segment chain.
    3549              :  * Returns DLT_RETURN_ERROR on failure
    3550              :  */
    3551            0 : DltReturnValue dlt_user_trace_network_segmented_start(
    3552              :     uint32_t* id, DltContext* handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void* header,
    3553              :     uint16_t payload_len)
    3554              : {
    3555            0 :     DltContextData log = {0};
    3556              :     struct timeval tv;
    3557              :     int ret = DLT_RETURN_ERROR;
    3558              : 
    3559              :     /* check null pointer */
    3560            0 :     if (id == NULL)
    3561              :         return DLT_RETURN_WRONG_PARAMETER;
    3562              : 
    3563            0 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3564            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3565            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3566              :     }
    3567              : 
    3568            0 :     if (dlt_user.dlt_ll_ts == NULL)
    3569              :         return DLT_RETURN_ERROR;
    3570              : 
    3571            0 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3572              :         /* initialize values */
    3573            0 :         if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3574              :             return DLT_RETURN_ERROR;
    3575              : 
    3576            0 :         if (log.buffer == NULL) {
    3577            0 :             log.buffer = calloc(dlt_user.log_buf_len, sizeof(unsigned char));
    3578              : 
    3579            0 :             if (log.buffer == NULL) {
    3580            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3581            0 :                 return DLT_RETURN_ERROR;
    3582              :             }
    3583              :         }
    3584              : 
    3585            0 :         log.args_num = 0;
    3586            0 :         log.trace_status = nw_trace_type;
    3587            0 :         log.size = 0;
    3588              : 
    3589            0 :         gettimeofday(&tv, NULL);
    3590            0 :         *id = (uint32_t)tv.tv_usec;
    3591              : 
    3592              :         /* Write identifier */
    3593            0 :         if (dlt_user_log_write_string(&log, DLT_TRACE_NW_START) < 0) {
    3594              :             dlt_user_free_buffer(&(log.buffer));
    3595            0 :             return DLT_RETURN_ERROR;
    3596              :         }
    3597              : 
    3598              :         /* Write stream handle */
    3599            0 :         if (dlt_user_log_write_uint32(&log, *id) < 0) {
    3600              :             dlt_user_free_buffer(&(log.buffer));
    3601            0 :             return DLT_RETURN_ERROR;
    3602              :         }
    3603              : 
    3604              :         /* Write header */
    3605            0 :         if (dlt_user_log_write_raw(&log, header, header_len) < 0) {
    3606              :             dlt_user_free_buffer(&(log.buffer));
    3607            0 :             return DLT_RETURN_ERROR;
    3608              :         }
    3609              : 
    3610              :         /* Write size of payload */
    3611            0 :         if (dlt_user_log_write_uint32(&log, payload_len) < 0) {
    3612              :             dlt_user_free_buffer(&(log.buffer));
    3613            0 :             return DLT_RETURN_ERROR;
    3614              :         }
    3615              : 
    3616              :         /* Write expected segment count */
    3617            0 :         uint16_t segment_count = (uint16_t)(payload_len / DLT_MAX_TRACE_SEGMENT_SIZE + 1);
    3618              : 
    3619              :         /* If segments align perfectly with segment size, avoid sending empty segment */
    3620            0 :         if ((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
    3621              :             segment_count--;
    3622              : 
    3623            0 :         if (dlt_user_log_write_uint16(&log, segment_count) < 0) {
    3624              :             dlt_user_free_buffer(&(log.buffer));
    3625            0 :             return DLT_RETURN_ERROR;
    3626              :         }
    3627              : 
    3628              :         /* Write length of one segment */
    3629            0 :         if (dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0) {
    3630              :             dlt_user_free_buffer(&(log.buffer));
    3631            0 :             return DLT_RETURN_ERROR;
    3632              :         }
    3633              : 
    3634              :         /* Send log */
    3635            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3636              : 
    3637              :         dlt_user_free_buffer(&(log.buffer));
    3638              : 
    3639            0 :         return ret;
    3640              :     }
    3641              : 
    3642              :     return DLT_RETURN_OK;
    3643              : }
    3644              : 
    3645            0 : DltReturnValue dlt_user_trace_network_segmented_segment(
    3646              :     uint32_t id, DltContext* handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len,
    3647              :     void* payload)
    3648              : {
    3649              :     int ret = DLT_RETURN_ERROR;
    3650              :     struct timespec ts;
    3651              : 
    3652            0 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3653            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3654            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3655              :     }
    3656              : 
    3657            0 :     while (check_buffer() < 0) {
    3658              :         /* Wait 50ms */
    3659            0 :         ts.tv_sec = 0;
    3660            0 :         ts.tv_nsec = 1000000 * 50;
    3661            0 :         nanosleep(&ts, NULL);
    3662            0 :         dlt_user_log_resend_buffer();
    3663              :     }
    3664              : 
    3665            0 :     if (dlt_user.dlt_ll_ts == NULL)
    3666              :         return DLT_RETURN_ERROR;
    3667              : 
    3668            0 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3669            0 :         DltContextData log = {0};
    3670              : 
    3671            0 :         if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3672              :             return DLT_RETURN_ERROR;
    3673              : 
    3674              :         /* initialize values */
    3675            0 :         if (log.buffer == NULL) {
    3676            0 :             log.buffer = calloc(dlt_user.log_buf_len, sizeof(unsigned char));
    3677              : 
    3678            0 :             if (log.buffer == NULL) {
    3679            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3680            0 :                 return DLT_RETURN_ERROR;
    3681              :             }
    3682              :         }
    3683              : 
    3684            0 :         log.args_num = 0;
    3685            0 :         log.trace_status = nw_trace_type;
    3686            0 :         log.size = 0;
    3687              : 
    3688              :         /* Write identifier */
    3689            0 :         if (dlt_user_log_write_string(&log, DLT_TRACE_NW_SEGMENT) < DLT_RETURN_OK) {
    3690              :             dlt_user_free_buffer(&(log.buffer));
    3691            0 :             return DLT_RETURN_ERROR;
    3692              :         }
    3693              : 
    3694              :         /* Write stream handle */
    3695            0 :         if (dlt_user_log_write_uint32(&log, id) < DLT_RETURN_OK) {
    3696              :             dlt_user_free_buffer(&(log.buffer));
    3697            0 :             return DLT_RETURN_ERROR;
    3698              :         }
    3699              : 
    3700              :         /* Write segment sequence number */
    3701            0 :         if (dlt_user_log_write_uint16(&log, (uint16_t)sequence) < DLT_RETURN_OK) {
    3702              :             dlt_user_free_buffer(&(log.buffer));
    3703            0 :             return DLT_RETURN_ERROR;
    3704              :         }
    3705              : 
    3706              :         /* Write data */
    3707            0 :         if (dlt_user_log_write_raw(&log, payload, payload_len) < DLT_RETURN_OK) {
    3708              :             dlt_user_free_buffer(&(log.buffer));
    3709            0 :             return DLT_RETURN_ERROR;
    3710              :         }
    3711              : 
    3712            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3713              :         /* Send log */
    3714              : 
    3715              :         dlt_user_free_buffer(&(log.buffer));
    3716              : 
    3717            0 :         return ret;
    3718              :     }
    3719              : 
    3720              :     /* Allow other threads to log between chunks */
    3721            0 :     sched_yield();
    3722            0 :     return DLT_RETURN_OK;
    3723              : }
    3724              : 
    3725            0 : DltReturnValue dlt_user_trace_network_segmented_end(uint32_t id, DltContext* handle, DltNetworkTraceType nw_trace_type)
    3726              : {
    3727            0 :     DltContextData log = {0};
    3728              :     int ret = DLT_RETURN_ERROR;
    3729              : 
    3730            0 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3731            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3732            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3733              :     }
    3734              : 
    3735            0 :     if (dlt_user.dlt_ll_ts == NULL)
    3736              :         return DLT_RETURN_ERROR;
    3737              : 
    3738            0 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3739              :         /* initialize values */
    3740            0 :         if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3741              :             return DLT_RETURN_ERROR;
    3742              : 
    3743              :         /* initialize values */
    3744            0 :         if (log.buffer == NULL) {
    3745            0 :             log.buffer = calloc(dlt_user.log_buf_len, sizeof(unsigned char));
    3746              : 
    3747            0 :             if (log.buffer == NULL) {
    3748            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3749            0 :                 return DLT_RETURN_ERROR;
    3750              :             }
    3751              :         }
    3752              : 
    3753            0 :         log.args_num = 0;
    3754            0 :         log.trace_status = nw_trace_type;
    3755            0 :         log.size = 0;
    3756              : 
    3757              :         /* Write identifier */
    3758            0 :         if (dlt_user_log_write_string(&log, DLT_TRACE_NW_END) < DLT_RETURN_OK) {
    3759              :             dlt_user_free_buffer(&(log.buffer));
    3760            0 :             return DLT_RETURN_ERROR;
    3761              :         }
    3762              : 
    3763              :         /* Write stream handle */
    3764            0 :         if (dlt_user_log_write_uint32(&log, id) < DLT_RETURN_OK) {
    3765              :             dlt_user_free_buffer(&(log.buffer));
    3766            0 :             return DLT_RETURN_ERROR;
    3767              :         }
    3768              : 
    3769            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3770              :         /* Send log */
    3771              : 
    3772              :         dlt_user_free_buffer(&(log.buffer));
    3773              : 
    3774            0 :         return ret;
    3775              :     }
    3776              : 
    3777              :     return DLT_RETURN_OK;
    3778              : }
    3779              : 
    3780        21002 : void* dlt_user_trace_network_segmented_thread(void* unused)
    3781              : {
    3782              :     /* Unused on purpose. */
    3783              :     (void)unused;
    3784              : #ifdef DLT_USE_PTHREAD_SETNAME_NP
    3785        21002 :     if (pthread_setname_np(dlt_user.dlt_segmented_nwt_handle, "dlt_segmented"))
    3786            0 :         dlt_log(LOG_WARNING, "Failed to rename segmented thread!\n");
    3787              : #elif linux
    3788              :     if (prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0) < 0)
    3789              :         dlt_log(LOG_WARNING, "Failed to rename segmented thread!\n");
    3790              : #endif
    3791        42004 :     pthread_cleanup_push(dlt_user_cleanup_handler, NULL);
    3792              : 
    3793              :     s_segmented_data* data;
    3794              : 
    3795              :     while (1) {
    3796              :         /* Wait until message queue is initialized */
    3797        21002 :         dlt_lock_mutex(&mq_mutex);
    3798              : 
    3799        21202 :         while (dlt_user.dlt_segmented_queue_read_handle < 0) {
    3800        21202 :             pthread_cond_wait(&mq_init_condition, &mq_mutex);
    3801              :         }
    3802              : 
    3803            0 :         dlt_unlock_mutex(&mq_mutex);
    3804              : 
    3805              :         ssize_t read =
    3806            0 :             mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char*)&data, sizeof(s_segmented_data*), NULL);
    3807              : 
    3808            0 :         if (read < 0) {
    3809            0 :             if (errno != EINTR) {
    3810              :                 struct timespec req;
    3811              :                 long sec = (DLT_USER_MQ_ERROR_RETRY_INTERVAL / 1000000);
    3812            0 :                 dlt_vlog(LOG_WARNING, "NWTSegmented: Error while reading queue: %s\n", strerror(errno));
    3813            0 :                 req.tv_sec = sec;
    3814            0 :                 req.tv_nsec = (DLT_USER_MQ_ERROR_RETRY_INTERVAL - sec * 1000000) * 1000;
    3815            0 :                 nanosleep(&req, NULL);
    3816              :             }
    3817              : 
    3818            0 :             continue;
    3819              :         }
    3820              : 
    3821            0 :         if (read != sizeof(s_segmented_data*)) {
    3822              :             /* This case will not happen. */
    3823              :             /* When this thread is interrupted by signal, mq_receive() will not return */
    3824              :             /* partial read length and will return -1. And also no data is removed from mq. */
    3825            0 :             dlt_vlog(LOG_WARNING, "NWTSegmented: Could not read data fully from queue: %zd\n", read);
    3826            0 :             continue;
    3827              :         }
    3828              : 
    3829            0 :         dlt_user_trace_network_segmented_thread_segmenter(data);
    3830              : 
    3831              :         /* Send the end message */
    3832            0 :         DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
    3833              : 
    3834            0 :         if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR))
    3835            0 :             dlt_log(LOG_WARNING, "NWTSegmented: Could not send end segment.\n");
    3836              : 
    3837              :         /* Free resources */
    3838            0 :         free(data->header);
    3839            0 :         free(data->payload);
    3840            0 :         free(data);
    3841              :     }
    3842              : 
    3843              :     pthread_cleanup_pop(1);
    3844              :     return NULL;
    3845              : }
    3846              : 
    3847            0 : void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data* data)
    3848              : {
    3849              :     /* Segment the data and send the chunks */
    3850              :     void* ptr = NULL;
    3851              :     uint32_t offset = 0;
    3852              :     uint16_t sequence = 0;
    3853              : 
    3854              :     do {
    3855              :         uint16_t len = 0;
    3856              : 
    3857            0 :         if (offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
    3858            0 :             len = (uint16_t)(data->payload_len - offset);
    3859              :         else
    3860              :             len = DLT_MAX_TRACE_SEGMENT_SIZE;
    3861              : 
    3862              :         /* If payload size aligns perfectly with segment size, avoid sending empty segment */
    3863            0 :         if (len == 0)
    3864              :             break;
    3865              : 
    3866            0 :         ptr = (void*)((uintptr_t)data->payload + offset);
    3867              :         DltReturnValue err =
    3868            0 :             dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
    3869              : 
    3870            0 :         if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) {
    3871            0 :             dlt_log(LOG_ERR, "NWTSegmented: Could not send segment. Aborting.\n");
    3872            0 :             break; /* loop */
    3873              :         }
    3874              : 
    3875            0 :         offset += len;
    3876            0 :     } while (offset < (uint32_t)((uintptr_t)data->payload + data->payload_len));
    3877            0 : }
    3878              : 
    3879              : 
    3880           10 : DltReturnValue dlt_user_trace_network_segmented(
    3881              :     DltContext* handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void* header, uint16_t payload_len,
    3882              :     void* payload)
    3883              : {
    3884              :     /* forbid dlt usage in child after fork */
    3885           10 :     if (g_dlt_is_child)
    3886              :         return DLT_RETURN_ERROR;
    3887              : 
    3888              :     /* Send as normal trace if possible */
    3889           10 :     if ((size_t)header_len + (size_t)payload_len + sizeof(uint16_t) < dlt_user.log_buf_len)
    3890           10 :         return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
    3891              : 
    3892              :     /* Allocate Memory */
    3893            0 :     s_segmented_data* thread_data = malloc(sizeof(s_segmented_data));
    3894              : 
    3895            0 :     if (thread_data == NULL)
    3896              :         return DLT_RETURN_ERROR;
    3897              : 
    3898            0 :     thread_data->header = malloc(header_len);
    3899              : 
    3900            0 :     if (thread_data->header == NULL) {
    3901            0 :         free(thread_data);
    3902            0 :         return DLT_RETURN_ERROR;
    3903              :     }
    3904              : 
    3905            0 :     thread_data->payload = malloc(payload_len);
    3906              : 
    3907            0 :     if (thread_data->payload == NULL) {
    3908            0 :         free(thread_data->header);
    3909            0 :         free(thread_data);
    3910            0 :         return DLT_RETURN_ERROR;
    3911              :     }
    3912              : 
    3913              :     /* Copy data */
    3914            0 :     thread_data->handle = handle;
    3915            0 :     thread_data->nw_trace_type = nw_trace_type;
    3916            0 :     thread_data->header_len = header_len;
    3917              :     memcpy(thread_data->header, header, header_len);
    3918            0 :     thread_data->payload_len = payload_len;
    3919              :     memcpy(thread_data->payload, payload, payload_len);
    3920              : 
    3921              :     /* Send start message */
    3922            0 :     DltReturnValue err = dlt_user_trace_network_segmented_start(
    3923              :         &(thread_data->id), thread_data->handle, thread_data->nw_trace_type, (uint16_t)thread_data->header_len,
    3924              :         thread_data->header, (uint16_t)thread_data->payload_len);
    3925              : 
    3926            0 :     if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) {
    3927            0 :         dlt_log(LOG_ERR, "NWTSegmented: Could not send start segment. Aborting.\n");
    3928            0 :         free(thread_data->header);
    3929            0 :         free(thread_data->payload);
    3930            0 :         free(thread_data);
    3931            0 :         return DLT_RETURN_ERROR;
    3932              :     }
    3933              : 
    3934              :     /* Open queue if it is not open */
    3935            0 :     if (dlt_init_message_queue() < 0) {
    3936            0 :         dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
    3937            0 :         free(thread_data->header);
    3938            0 :         free(thread_data->payload);
    3939            0 :         free(thread_data);
    3940              : 
    3941            0 :         return DLT_RETURN_ERROR;
    3942              :     }
    3943              : 
    3944              :     /* Add to queue */
    3945            0 :     if (mq_send(dlt_user.dlt_segmented_queue_write_handle, (char*)&thread_data, sizeof(s_segmented_data*), 1) < 0) {
    3946            0 :         if (errno == EAGAIN)
    3947            0 :             dlt_log(LOG_WARNING, "NWTSegmented: Queue full. Message discarded.\n");
    3948              : 
    3949            0 :         free(thread_data->header);
    3950            0 :         free(thread_data->payload);
    3951            0 :         free(thread_data);
    3952            0 :         dlt_vnlog(LOG_WARNING, 256, "NWTSegmented: Could not write into queue: %s \n", strerror(errno));
    3953            0 :         return DLT_RETURN_ERROR;
    3954              :     }
    3955              : 
    3956              :     /*thread_data will be freed by the receiver function */
    3957              :     /*coverity[leaked_storage] */
    3958              :     return DLT_RETURN_OK;
    3959              : }
    3960              : 
    3961           20 : DltReturnValue dlt_user_trace_network(
    3962              :     DltContext* handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void* header, uint16_t payload_len,
    3963              :     void* payload)
    3964              : {
    3965           20 :     return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
    3966              : }
    3967              : 
    3968           34 : DltReturnValue dlt_user_trace_network_truncated(
    3969              :     DltContext* handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void* header, uint16_t payload_len,
    3970              :     void* payload, int allow_truncate)
    3971              : {
    3972              :     int ret = DLT_RETURN_ERROR;
    3973           34 :     DltContextData log = {0};
    3974              : 
    3975           34 :     if ((payload == NULL) && (payload_len > 0))
    3976              :         return DLT_RETURN_WRONG_PARAMETER;
    3977              : 
    3978           22 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3979            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3980            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3981              :     }
    3982              : 
    3983           22 :     if (dlt_user.dlt_ll_ts == NULL)
    3984              :         return DLT_RETURN_ERROR;
    3985              : 
    3986           22 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3987            0 :         if ((dlt_user_log_init(handle, &log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL))
    3988              :             return DLT_RETURN_ERROR;
    3989              : 
    3990              :         /* initialize values */
    3991            0 :         if (log.buffer == NULL) {
    3992            0 :             log.buffer = calloc(dlt_user.log_buf_len, sizeof(unsigned char));
    3993              : 
    3994            0 :             if (log.buffer == NULL) {
    3995            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3996            0 :                 return DLT_RETURN_ERROR;
    3997              :             }
    3998              :         }
    3999              : 
    4000            0 :         log.args_num = 0;
    4001            0 :         log.trace_status = nw_trace_type;
    4002            0 :         log.size = 0;
    4003              : 
    4004            0 :         if (header == NULL)
    4005              :             header_len = 0;
    4006              : 
    4007              :         /* If truncation is allowed, check if we must do it */
    4008            0 :         if ((allow_truncate > 0)
    4009            0 :             && ((size_t)header_len + (size_t)payload_len + sizeof(uint16_t) > dlt_user.log_buf_len)) {
    4010              :             /* Identify as truncated */
    4011            0 :             if (dlt_user_log_write_string(&log, DLT_TRACE_NW_TRUNCATED) < DLT_RETURN_OK) {
    4012              :                 dlt_user_free_buffer(&(log.buffer));
    4013            0 :                 return DLT_RETURN_ERROR;
    4014              :             }
    4015              : 
    4016              :             /* Write header and its length */
    4017            0 :             if (dlt_user_log_write_raw(&log, header, header_len) < DLT_RETURN_OK) {
    4018              :                 dlt_user_free_buffer(&(log.buffer));
    4019            0 :                 return DLT_RETURN_ERROR;
    4020              :             }
    4021              : 
    4022              :             /* Write original size of payload */
    4023            0 :             if (dlt_user_log_write_uint32(&log, payload_len) < DLT_RETURN_OK) {
    4024              :                 dlt_user_free_buffer(&(log.buffer));
    4025            0 :                 return DLT_RETURN_ERROR;
    4026              :             }
    4027              : 
    4028              :             /**
    4029              :              *  Calculate maximum available space in sending buffer after headers.
    4030              :              */
    4031              : 
    4032            0 :             uint16_t truncated_payload_len =
    4033            0 :                 (uint16_t)((size_t)dlt_user.log_buf_len - (size_t)log.size - sizeof(uint16_t) - sizeof(uint32_t));
    4034              :             /* Write truncated payload */
    4035            0 :             if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < DLT_RETURN_OK) {
    4036              :                 dlt_user_free_buffer(&(log.buffer));
    4037            0 :                 return DLT_RETURN_ERROR;
    4038              :             }
    4039              :         } else { /* Truncation not allowed or data short enough */
    4040              : 
    4041              :             /* Write header and its length */
    4042            0 :             if (dlt_user_log_write_raw(&log, header, header_len) < DLT_RETURN_OK) {
    4043              :                 dlt_user_free_buffer(&(log.buffer));
    4044            0 :                 return DLT_RETURN_ERROR;
    4045              :             }
    4046              : 
    4047            0 :             if (payload == NULL)
    4048              :                 payload_len = 0;
    4049              : 
    4050              :             /* Write payload and its length */
    4051            0 :             if (dlt_user_log_write_raw(&log, payload, payload_len) < DLT_RETURN_OK) {
    4052              :                 dlt_user_free_buffer(&(log.buffer));
    4053            0 :                 return DLT_RETURN_ERROR;
    4054              :             }
    4055              :         }
    4056              : 
    4057            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    4058              : 
    4059              :         dlt_user_free_buffer(&(log.buffer));
    4060              : 
    4061              :         /* Send log */
    4062            0 :         return ret;
    4063              :     }
    4064              : 
    4065              :     return DLT_RETURN_OK;
    4066              : }
    4067              : #else /* DLT_NETWORK_TRACE_ENABLE not set */
    4068              : DltReturnValue dlt_user_trace_network_segmented(
    4069              :     DltContext* handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void* header, uint16_t payload_len,
    4070              :     void* payload)
    4071              : {
    4072              :     /**
    4073              :      *  vsomeip uses the DLT_TRACE_NETWORK_SEGMENTED macro that calls this function.
    4074              :      *  It's not possible to rewrite this macro directly to a no-op,
    4075              :      *  because the macro is used on vsomeip side and there our defines are not set.
    4076              :      *  Add an empty function to the dlt-lib to avoid a broken build.
    4077              :      */
    4078              :     (void)handle;
    4079              :     (void)nw_trace_type;
    4080              :     (void)header_len;
    4081              :     (void)header;
    4082              :     (void)payload_len;
    4083              :     (void)payload;
    4084              :     return DLT_RETURN_LOGGING_DISABLED;
    4085              : }
    4086              : 
    4087              : DltReturnValue dlt_user_trace_network_truncated(
    4088              :     DltContext* handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void* header, uint16_t payload_len,
    4089              :     void* payload, int allow_truncate)
    4090              : {
    4091              :     /**
    4092              :      *  vsomeip uses the DLT_TRACE_NETWORK_TRUNCATED macro that calls this function.
    4093              :      *  It's not possible to rewrite this macro directly to a no-op,
    4094              :      *  because the macro is used on vsomeip side and there our defines are not set.
    4095              :      *  Add an empty function to the dlt-lib to avoid a broken build.
    4096              :      */
    4097              :     (void)handle;
    4098              :     (void)nw_trace_type;
    4099              :     (void)header_len;
    4100              :     (void)header;
    4101              :     (void)payload_len;
    4102              :     (void)payload;
    4103              :     (void)allow_truncate;
    4104              :     return DLT_RETURN_LOGGING_DISABLED;
    4105              : }
    4106              : 
    4107              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    4108              : 
    4109           18 : DltReturnValue dlt_log_string(DltContext* handle, DltLogLevelType loglevel, const char* text)
    4110              : {
    4111           36 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4112              :         return DLT_RETURN_ERROR;
    4113              : 
    4114           18 :     if ((handle == NULL) || (text == NULL))
    4115              :         return DLT_RETURN_WRONG_PARAMETER;
    4116              : 
    4117              :     DltReturnValue ret = DLT_RETURN_OK;
    4118              :     DltContextData log;
    4119              : 
    4120           15 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4121           11 :         ret = dlt_user_log_write_string(&log, text);
    4122              : 
    4123           11 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    4124              :             ret = DLT_RETURN_ERROR;
    4125              :     }
    4126              : 
    4127              :     return ret;
    4128              : }
    4129              : 
    4130            0 : DltReturnValue dlt_log_string_v2(DltContext* handle, DltLogLevelType loglevel, const char* text)
    4131              : {
    4132            0 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4133              :         return DLT_RETURN_ERROR;
    4134              : 
    4135            0 :     if ((handle == NULL) || (text == NULL))
    4136              :         return DLT_RETURN_WRONG_PARAMETER;
    4137              : 
    4138              :     DltReturnValue ret = DLT_RETURN_OK;
    4139              :     DltContextData log;
    4140              : 
    4141            0 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4142            0 :         ret = dlt_user_log_write_string(&log, text);
    4143              : 
    4144            0 :         if (dlt_user_log_write_finish_v2(&log) < DLT_RETURN_OK)
    4145              :             ret = DLT_RETURN_ERROR;
    4146              :     }
    4147              : 
    4148              :     return ret;
    4149              : }
    4150              : 
    4151           25 : DltReturnValue dlt_log_string_int(DltContext* handle, DltLogLevelType loglevel, const char* text, int data)
    4152              : {
    4153           50 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4154              :         return DLT_RETURN_ERROR;
    4155              : 
    4156           25 :     if ((handle == NULL) || (text == NULL))
    4157              :         return DLT_RETURN_WRONG_PARAMETER;
    4158              : 
    4159              :     DltReturnValue ret = DLT_RETURN_OK;
    4160              :     DltContextData log;
    4161              : 
    4162           22 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4163           16 :         ret = dlt_user_log_write_string(&log, text);
    4164           16 :         dlt_user_log_write_int(&log, data);
    4165              : 
    4166           16 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    4167              :             ret = DLT_RETURN_ERROR;
    4168              :     }
    4169              : 
    4170              :     return ret;
    4171              : }
    4172              : 
    4173            0 : DltReturnValue dlt_log_string_int_v2(DltContext* handle, DltLogLevelType loglevel, const char* text, int data)
    4174              : {
    4175            0 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4176              :         return DLT_RETURN_ERROR;
    4177              : 
    4178            0 :     if ((handle == NULL) || (text == NULL))
    4179              :         return DLT_RETURN_WRONG_PARAMETER;
    4180              : 
    4181              :     DltReturnValue ret = DLT_RETURN_OK;
    4182              :     DltContextData log;
    4183              : 
    4184            0 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4185            0 :         ret = dlt_user_log_write_string(&log, text);
    4186            0 :         dlt_user_log_write_int(&log, data);
    4187              : 
    4188            0 :         if (dlt_user_log_write_finish_v2(&log) < DLT_RETURN_OK)
    4189              :             ret = DLT_RETURN_ERROR;
    4190              :     }
    4191              : 
    4192              :     return ret;
    4193              : }
    4194              : 
    4195           25 : DltReturnValue dlt_log_string_uint(DltContext* handle, DltLogLevelType loglevel, const char* text, unsigned int data)
    4196              : {
    4197           50 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4198              :         return DLT_RETURN_ERROR;
    4199              : 
    4200           25 :     if ((handle == NULL) || (text == NULL))
    4201              :         return DLT_RETURN_WRONG_PARAMETER;
    4202              : 
    4203              :     DltReturnValue ret = DLT_RETURN_OK;
    4204              :     DltContextData log;
    4205              : 
    4206           22 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4207           16 :         ret = dlt_user_log_write_string(&log, text);
    4208           16 :         dlt_user_log_write_uint(&log, data);
    4209              : 
    4210           16 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    4211              :             ret = DLT_RETURN_ERROR;
    4212              :     }
    4213              : 
    4214              :     return ret;
    4215              : }
    4216              : 
    4217            0 : DltReturnValue dlt_log_string_uint_v2(DltContext* handle, DltLogLevelType loglevel, const char* text, unsigned int data)
    4218              : {
    4219            0 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4220              :         return DLT_RETURN_ERROR;
    4221              : 
    4222            0 :     if ((handle == NULL) || (text == NULL))
    4223              :         return DLT_RETURN_WRONG_PARAMETER;
    4224              : 
    4225              :     DltReturnValue ret = DLT_RETURN_OK;
    4226              :     DltContextData log;
    4227              : 
    4228            0 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4229            0 :         ret = dlt_user_log_write_string(&log, text);
    4230            0 :         dlt_user_log_write_uint(&log, data);
    4231              : 
    4232            0 :         if (dlt_user_log_write_finish_v2(&log) < DLT_RETURN_OK)
    4233              :             ret = DLT_RETURN_ERROR;
    4234              :     }
    4235              : 
    4236              :     return ret;
    4237              : }
    4238              : 
    4239           22 : DltReturnValue dlt_log_int(DltContext* handle, DltLogLevelType loglevel, int data)
    4240              : {
    4241           44 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4242              :         return DLT_RETURN_ERROR;
    4243              : 
    4244           22 :     if (handle == NULL)
    4245              :         return DLT_RETURN_ERROR;
    4246              : 
    4247              :     DltContextData log;
    4248              : 
    4249           21 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4250           15 :         dlt_user_log_write_int(&log, data);
    4251              : 
    4252           15 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    4253              :             return DLT_RETURN_ERROR;
    4254              :     }
    4255              : 
    4256              :     return DLT_RETURN_OK;
    4257              : }
    4258              : 
    4259            0 : DltReturnValue dlt_log_int_v2(DltContext* handle, DltLogLevelType loglevel, int data)
    4260              : {
    4261            0 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4262              :         return DLT_RETURN_ERROR;
    4263              : 
    4264            0 :     if (handle == NULL)
    4265              :         return DLT_RETURN_ERROR;
    4266              : 
    4267              :     DltContextData log;
    4268              : 
    4269            0 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4270            0 :         dlt_user_log_write_int(&log, data);
    4271              : 
    4272            0 :         if (dlt_user_log_write_finish_v2(&log) < DLT_RETURN_OK)
    4273              :             return DLT_RETURN_ERROR;
    4274              :     }
    4275              : 
    4276              :     return DLT_RETURN_OK;
    4277              : }
    4278              : 
    4279           22 : DltReturnValue dlt_log_uint(DltContext* handle, DltLogLevelType loglevel, unsigned int data)
    4280              : {
    4281           44 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4282              :         return DLT_RETURN_ERROR;
    4283              : 
    4284           22 :     if (handle == NULL)
    4285              :         return DLT_RETURN_WRONG_PARAMETER;
    4286              : 
    4287              :     DltContextData log;
    4288              : 
    4289           21 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4290           15 :         dlt_user_log_write_uint(&log, data);
    4291              : 
    4292           15 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    4293              :             return DLT_RETURN_ERROR;
    4294              :     }
    4295              : 
    4296              :     return DLT_RETURN_OK;
    4297              : }
    4298              : 
    4299            0 : DltReturnValue dlt_log_uint_v2(DltContext* handle, DltLogLevelType loglevel, unsigned int data)
    4300              : {
    4301            0 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4302              :         return DLT_RETURN_ERROR;
    4303              : 
    4304            0 :     if (handle == NULL)
    4305              :         return DLT_RETURN_WRONG_PARAMETER;
    4306              : 
    4307              :     DltContextData log;
    4308              : 
    4309            0 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    4310            0 :         dlt_user_log_write_uint(&log, data);
    4311              : 
    4312            0 :         if (dlt_user_log_write_finish_v2(&log) < DLT_RETURN_OK)
    4313              :             return DLT_RETURN_ERROR;
    4314              :     }
    4315              : 
    4316              :     return DLT_RETURN_OK;
    4317              : }
    4318              : 
    4319           11 : DltReturnValue dlt_log_raw(DltContext* handle, DltLogLevelType loglevel, void* data, uint16_t length)
    4320              : {
    4321           22 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4322              :         return DLT_RETURN_ERROR;
    4323              : 
    4324           11 :     if (handle == NULL)
    4325              :         return DLT_RETURN_WRONG_PARAMETER;
    4326              : 
    4327              :     DltContextData log;
    4328              :     DltReturnValue ret = DLT_RETURN_OK;
    4329              : 
    4330            9 :     if (dlt_user_log_write_start(handle, &log, loglevel) > 0) {
    4331            7 :         if ((ret = dlt_user_log_write_raw(&log, data, length)) < DLT_RETURN_OK) {
    4332              :             dlt_user_free_buffer(&(log.buffer));
    4333            2 :             return ret;
    4334              :         }
    4335              : 
    4336            5 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    4337              :             return DLT_RETURN_ERROR;
    4338              :     }
    4339              : 
    4340              :     return DLT_RETURN_OK;
    4341              : }
    4342              : 
    4343            0 : DltReturnValue dlt_log_raw_v2(DltContext* handle, DltLogLevelType loglevel, void* data, uint16_t length)
    4344              : {
    4345            0 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    4346              :         return DLT_RETURN_ERROR;
    4347              : 
    4348            0 :     if (handle == NULL)
    4349              :         return DLT_RETURN_WRONG_PARAMETER;
    4350              : 
    4351              :     DltContextData log;
    4352              :     DltReturnValue ret = DLT_RETURN_OK;
    4353              : 
    4354            0 :     if (dlt_user_log_write_start(handle, &log, loglevel) > 0) {
    4355            0 :         if ((ret = dlt_user_log_write_raw(&log, data, length)) < DLT_RETURN_OK) {
    4356              :             dlt_user_free_buffer(&(log.buffer));
    4357            0 :             return ret;
    4358              :         }
    4359              : 
    4360            0 :         if (dlt_user_log_write_finish_v2(&log) < DLT_RETURN_OK)
    4361              :             return DLT_RETURN_ERROR;
    4362              :     }
    4363              : 
    4364              :     return DLT_RETURN_OK;
    4365              : }
    4366              : 
    4367            1 : DltReturnValue dlt_log_marker()
    4368              : {
    4369            1 :     if (!DLT_USER_INITIALIZED) {
    4370            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4371            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4372            0 :             return DLT_RETURN_ERROR;
    4373              :         }
    4374              :     }
    4375              : 
    4376            1 :     return dlt_user_log_send_marker();
    4377              : }
    4378              : 
    4379           10 : DltReturnValue dlt_verbose_mode(void)
    4380              : {
    4381           10 :     if (!DLT_USER_INITIALIZED) {
    4382            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4383            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4384            0 :             return DLT_RETURN_ERROR;
    4385              :         }
    4386              :     }
    4387              : 
    4388              :     /* Switch to verbose mode */
    4389           10 :     dlt_user.verbose_mode = 1;
    4390              : 
    4391           10 :     return DLT_RETURN_OK;
    4392              : }
    4393              : 
    4394           10 : DltReturnValue dlt_nonverbose_mode(void)
    4395              : {
    4396           10 :     if (!DLT_USER_INITIALIZED) {
    4397            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4398            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4399            0 :             return DLT_RETURN_ERROR;
    4400              :         }
    4401              :     }
    4402              : 
    4403              :     /* Switch to non-verbose mode */
    4404           10 :     dlt_user.verbose_mode = 0;
    4405              : 
    4406           10 :     return DLT_RETURN_OK;
    4407              : }
    4408              : 
    4409            2 : DltReturnValue dlt_use_extended_header_for_non_verbose(int8_t use_extended_header_for_non_verbose)
    4410              : {
    4411            2 :     if (!DLT_USER_INITIALIZED) {
    4412            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4413            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4414            0 :             return DLT_RETURN_ERROR;
    4415              :         }
    4416              :     }
    4417              : 
    4418              :     /* Set use_extended_header_for_non_verbose */
    4419            2 :     dlt_user.use_extended_header_for_non_verbose = use_extended_header_for_non_verbose;
    4420              : 
    4421            2 :     return DLT_RETURN_OK;
    4422              : }
    4423              : 
    4424            0 : DltReturnValue dlt_with_session_id(int8_t with_session_id)
    4425              : {
    4426            0 :     if (!DLT_USER_INITIALIZED) {
    4427            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4428            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4429            0 :             return DLT_RETURN_ERROR;
    4430              :         }
    4431              :     }
    4432              : 
    4433              :     /* Set use_extended_header_for_non_verbose */
    4434            0 :     dlt_user.with_session_id = with_session_id;
    4435              : 
    4436            0 :     return DLT_RETURN_OK;
    4437              : }
    4438              : 
    4439            0 : DltReturnValue dlt_with_timestamp(int8_t with_timestamp)
    4440              : {
    4441            0 :     if (!DLT_USER_INITIALIZED) {
    4442            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4443            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4444            0 :             return DLT_RETURN_ERROR;
    4445              :         }
    4446              :     }
    4447              : 
    4448              :     /* Set with_timestamp */
    4449            0 :     dlt_user.with_timestamp = with_timestamp;
    4450              : 
    4451            0 :     return DLT_RETURN_OK;
    4452              : }
    4453              : 
    4454            0 : DltReturnValue dlt_with_ecu_id(int8_t with_ecu_id)
    4455              : {
    4456            0 :     if (!DLT_USER_INITIALIZED) {
    4457            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4458            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4459            0 :             return DLT_RETURN_ERROR;
    4460              :         }
    4461              :     }
    4462              : 
    4463              :     /* Set with_timestamp */
    4464            0 :     dlt_user.with_ecu_id = with_ecu_id;
    4465              : 
    4466            0 :     return DLT_RETURN_OK;
    4467              : }
    4468              : 
    4469            0 : DltReturnValue dlt_with_filename_and_line_number(const char* fina, const int linr)
    4470              : {
    4471            0 :     if (fina == NULL) {
    4472            0 :         dlt_vlog(LOG_ERR, "%s Wrong parameter", __func__);
    4473            0 :         return DLT_RETURN_ERROR;
    4474              :     }
    4475            0 :     if (!DLT_USER_INITIALIZED) {
    4476            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4477            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4478            0 :             return DLT_RETURN_ERROR;
    4479              :         }
    4480              :     }
    4481              : 
    4482              :     /* Set filename and line number */
    4483            0 :     dlt_user.with_filename_and_line_number = 1;
    4484            0 :     dlt_user.filenamelen = (uint8_t)strlen(fina);
    4485            0 :     if (dlt_user.filename != NULL) {
    4486            0 :         free(dlt_user.filename);
    4487              :         dlt_user.filename = NULL;
    4488              :     }
    4489              : 
    4490            0 :     dlt_user.filename = (char*)malloc((size_t)dlt_user.filenamelen + 1);
    4491            0 :     if (dlt_user.filename == NULL) {
    4492            0 :         dlt_vlog(LOG_ERR, "%s Could not allocate memory for filename", __func__);
    4493            0 :         return DLT_RETURN_ERROR;
    4494              :     }
    4495              :     strcpy(dlt_user.filename, fina);
    4496              : 
    4497            0 :     dlt_user.linenumber = (uint32_t)linr;
    4498            0 :     return DLT_RETURN_OK;
    4499              : }
    4500              : 
    4501            0 : DltReturnValue dlt_with_prlv(uint8_t prlv)
    4502              : {
    4503            0 :     if (!DLT_USER_INITIALIZED) {
    4504            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4505            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4506            0 :             return DLT_RETURN_ERROR;
    4507              :         }
    4508              :     }
    4509              : 
    4510              :     /* Set privacy level */
    4511            0 :     dlt_user.with_privacy_level = 1;
    4512            0 :     dlt_user.prlv = prlv;
    4513              : 
    4514            0 :     return DLT_RETURN_OK;
    4515              : }
    4516              : 
    4517            0 : DltReturnValue dlt_with_tags(const char* firstTag, ...)
    4518              : {
    4519            0 :     if (firstTag == NULL) {
    4520            0 :         dlt_vlog(LOG_ERR, "%s Wrong parameter", __func__);
    4521            0 :         return DLT_RETURN_ERROR;
    4522              :     }
    4523            0 :     if (!DLT_USER_INITIALIZED) {
    4524            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4525            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4526            0 :             return DLT_RETURN_ERROR;
    4527              :         }
    4528              :     }
    4529              : 
    4530              :     va_list args;
    4531              :     const char* currentTag = firstTag;
    4532              :     uint8_t count = 0;
    4533              : 
    4534              :     // Initial pass: Count the number of tags to allocate memory accurately
    4535            0 :     va_start(args, firstTag);
    4536            0 :     while (currentTag != NULL) {
    4537            0 :         count++;
    4538            0 :         currentTag = va_arg(args, const char*);
    4539              :     }
    4540            0 :     va_end(args);
    4541              : 
    4542            0 :     dlt_user.with_tags = 1;
    4543            0 :     dlt_user.numberoftags = count;
    4544              : 
    4545              :     /* Allocate DltTag array and copy each tag name into the fixed-size
    4546              :      * `tagname` buffer inside DltTag to avoid extra mallocs. Truncate if
    4547              :      * necessary to fit `DLT_V2_ID_SIZE - 1` characters plus NUL.
    4548              :      */
    4549              :     int i = 0;
    4550            0 :     dlt_user.tag = (DltTag*)malloc((size_t)count * sizeof(DltTag));
    4551            0 :     if (dlt_user.tag == NULL) {
    4552              :         return DLT_RETURN_ERROR;
    4553              :     }
    4554              : 
    4555              :     currentTag = firstTag;
    4556            0 :     va_start(args, firstTag);
    4557              :     int total_size = 0;
    4558            0 :     while (currentTag != NULL) {
    4559            0 :         size_t len = strlen(currentTag);
    4560            0 :         if (len >= DLT_V2_ID_SIZE) {
    4561              :             /* copy truncated */
    4562            0 :             memcpy(dlt_user.tag[i].tagname, currentTag, DLT_V2_ID_SIZE - 1);
    4563            0 :             dlt_user.tag[i].tagname[DLT_V2_ID_SIZE - 1] = '\0';
    4564            0 :             dlt_user.tag[i].taglen = (uint8_t)(DLT_V2_ID_SIZE - 1);
    4565            0 :             total_size += DLT_V2_ID_SIZE;
    4566              :         } else {
    4567            0 :             memcpy(dlt_user.tag[i].tagname, currentTag, len);
    4568            0 :             dlt_user.tag[i].tagname[len] = '\0';
    4569            0 :             dlt_user.tag[i].taglen = (uint8_t)len;
    4570            0 :             total_size += (int)len + 1;
    4571              :         }
    4572            0 :         i++;
    4573            0 :         currentTag = va_arg(args, const char*);
    4574              :     }
    4575            0 :     va_end(args);
    4576              : 
    4577            0 :     dlt_user.tagbuffersize = total_size;
    4578              : 
    4579            0 :     return DLT_RETURN_OK;
    4580              : }
    4581              : 
    4582            0 : DltReturnValue dlt_enable_local_print(void)
    4583              : {
    4584            0 :     if (!DLT_USER_INITIALIZED) {
    4585            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4586            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4587            0 :             return DLT_RETURN_ERROR;
    4588              :         }
    4589              :     }
    4590              : 
    4591            0 :     dlt_user.enable_local_print = 1;
    4592              : 
    4593            0 :     return DLT_RETURN_OK;
    4594              : }
    4595              : 
    4596            0 : DltReturnValue dlt_disable_local_print(void)
    4597              : {
    4598            0 :     if (!DLT_USER_INITIALIZED) {
    4599            0 :         if (dlt_init() < DLT_RETURN_OK) {
    4600            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4601            0 :             return DLT_RETURN_ERROR;
    4602              :         }
    4603              :     }
    4604              : 
    4605            0 :     dlt_user.enable_local_print = 0;
    4606              : 
    4607            0 :     return DLT_RETURN_OK;
    4608              : }
    4609              : 
    4610              : /* Cleanup on thread cancellation, thread may hold lock release it here */
    4611        42003 : static void dlt_user_cleanup_handler(void* arg)
    4612              : {
    4613              :     DLT_UNUSED(arg); /* Satisfy compiler */
    4614              : 
    4615              : #ifdef DLT_NETWORK_TRACE_ENABLE
    4616              :     /* Unlock the message queue */
    4617        42003 :     dlt_unlock_mutex(&mq_mutex);
    4618              : #endif
    4619              :     /* unlock DLT (dlt_mutex) */
    4620        42004 :     dlt_mutex_unlock();
    4621        42004 : }
    4622              : 
    4623        21002 : void* dlt_user_housekeeperthread_function(void* ptr)
    4624              : {
    4625              :     struct timespec ts;
    4626              :     bool in_loop = true;
    4627              :     int signal_status = 0;
    4628              :     atomic_bool* dlt_housekeeper_running = (atomic_bool*)ptr;
    4629              : 
    4630              : #ifdef __ANDROID_API__
    4631              :     sigset_t set;
    4632              :     sigset_t pset;
    4633              :     /*
    4634              :      * bionic is not supporting pthread_cancel so
    4635              :      * use SIGUSR1 to kill thread properly.
    4636              :      */
    4637              :     sigemptyset(&set);
    4638              :     sigaddset(&set, SIGUSR1);
    4639              :     if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
    4640              :         dlt_vlog(LOG_ERR, "Failed to block signal with error [%s]\n", strerror(errno));
    4641              :         in_loop = false;
    4642              :     }
    4643              : #endif
    4644              : 
    4645              : #ifdef DLT_USE_PTHREAD_SETNAME_NP
    4646              : #if defined(__APPLE__)
    4647              :     if (pthread_setname_np("dlt_housekeeper"))
    4648              : #else
    4649        21002 :     if (pthread_setname_np(dlt_housekeeperthread_handle, "dlt_housekeeper"))
    4650              : #endif
    4651            0 :         dlt_log(LOG_WARNING, "Failed to rename housekeeper thread!\n");
    4652              : #elif defined(linux)
    4653              :     if (prctl(PR_SET_NAME, "dlt_housekeeper", 0, 0, 0) < 0)
    4654              :         dlt_log(LOG_WARNING, "Failed to rename housekeeper thread!\n");
    4655              : #endif
    4656              : 
    4657        42004 :     pthread_cleanup_push(dlt_user_cleanup_handler, NULL);
    4658              : 
    4659              : 
    4660        21002 :     pthread_mutex_lock(&dlt_housekeeper_running_mutex);
    4661              : 
    4662              :     // signal dlt thread to be running
    4663        21002 :     *dlt_housekeeper_running = true;
    4664        21002 :     signal_status = pthread_cond_signal(&dlt_housekeeper_running_cond);
    4665        21002 :     if (signal_status != 0) {
    4666            0 :         dlt_log(LOG_CRIT, "Housekeeper thread failed to signal running state\n");
    4667              :     }
    4668              : 
    4669        21002 :     pthread_mutex_unlock(&dlt_housekeeper_running_mutex);
    4670              : 
    4671              :     while (in_loop) {
    4672              :         /* Check for new messages from DLT daemon */
    4673        21009 :         if (!dlt_user.disable_injection_msg)
    4674        21009 :             if (dlt_user_log_check_user_message() < DLT_RETURN_OK)
    4675              :                 /* Critical error */
    4676            0 :                 dlt_log(LOG_CRIT, "Housekeeper thread encountered error condition\n");
    4677              : 
    4678              :         /* Reattach to daemon if neccesary */
    4679           19 :         dlt_user_log_reattach_to_daemon();
    4680              : 
    4681              :         /* flush buffer to DLT daemon if possible */
    4682           19 :         if (dlt_user.dlt_log_handle != DLT_FD_INIT)
    4683           19 :             dlt_user_log_resend_buffer();
    4684              : 
    4685              : #ifdef __ANDROID_API__
    4686              :         if (sigpending(&pset)) {
    4687              :             dlt_vlog(LOG_ERR, "sigpending failed with error [%s]!\n", strerror(errno));
    4688              :             break;
    4689              :         }
    4690              : 
    4691              :         if (sigismember(&pset, SIGUSR1)) {
    4692              :             dlt_log(LOG_NOTICE, "Received SIGUSR1! Stop thread\n");
    4693              :             break;
    4694              :         }
    4695              : #endif
    4696              : 
    4697              :         /* delay */
    4698           19 :         ts.tv_sec = 0;
    4699           19 :         ts.tv_nsec = DLT_USER_RECEIVE_NDELAY;
    4700           19 :         nanosleep(&ts, NULL);
    4701              :     }
    4702              : 
    4703              :     pthread_cleanup_pop(1);
    4704              :     return NULL;
    4705              : }
    4706              : 
    4707              : /* Private functions of user library */
    4708              : 
    4709         6503 : DltReturnValue dlt_user_log_init(DltContext* handle, DltContextData* log)
    4710              : {
    4711              :     int ret = DLT_RETURN_OK;
    4712              : 
    4713         6503 :     if ((handle == NULL) || (log == NULL))
    4714              :         return DLT_RETURN_WRONG_PARAMETER;
    4715              : 
    4716         6503 :     if (!DLT_USER_INITIALIZED) {
    4717            0 :         ret = dlt_init();
    4718              : 
    4719            0 :         if (ret < DLT_RETURN_OK) {
    4720            0 :             if (ret != DLT_RETURN_LOGGING_DISABLED)
    4721            0 :                 dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __func__);
    4722              : 
    4723            0 :             return ret;
    4724              :         }
    4725              :     }
    4726              : 
    4727         6503 :     log->handle = handle;
    4728         6503 :     log->buffer = NULL;
    4729         6503 :     return ret;
    4730              : }
    4731              : 
    4732         6008 : DltReturnValue dlt_user_log_send_log(DltContextData* log, const int mtype, int* const sent_size)
    4733              : {
    4734              :     DltMessage msg;
    4735              :     DltUserHeader userheader;
    4736              :     uint32_t len;
    4737              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4738              :     uint32_t time_stamp;
    4739              : #else
    4740              :     // shut up warning
    4741              :     (void)sent_size;
    4742              : #endif
    4743              : 
    4744              :     DltReturnValue ret = DLT_RETURN_OK;
    4745              : 
    4746         6008 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    4747            0 :         dlt_vlog(
    4748              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    4749            0 :             dlt_user_init_state, dlt_user_freeing);
    4750            0 :         return DLT_RETURN_ERROR;
    4751              :     }
    4752              : 
    4753         6008 :     dlt_mutex_lock();
    4754         6008 :     if ((log == NULL) || (log->handle == NULL) || (log->handle->contextID[0] == '\0') || (mtype < DLT_TYPE_LOG)
    4755         5999 :         || (mtype > DLT_TYPE_CONTROL)) {
    4756            9 :         dlt_mutex_unlock();
    4757            9 :         return DLT_RETURN_WRONG_PARAMETER;
    4758              :     }
    4759              : 
    4760              :     /* also for Trace messages */
    4761         5999 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG) < DLT_RETURN_OK) {
    4762            0 :         dlt_mutex_unlock();
    4763            0 :         return DLT_RETURN_ERROR;
    4764              :     }
    4765              : 
    4766         5999 :     if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) {
    4767            0 :         dlt_mutex_unlock();
    4768            0 :         return DLT_RETURN_ERROR;
    4769              :     }
    4770              : 
    4771         5999 :     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
    4772              : 
    4773         5999 :     if (dlt_set_storageheader(msg.storageheader, dlt_user.ecuID) == DLT_RETURN_ERROR) {
    4774            0 :         dlt_mutex_unlock();
    4775            0 :         return DLT_RETURN_ERROR;
    4776              :     }
    4777              : 
    4778         5999 :     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
    4779         5999 :     msg.standardheader->htyp = DLT_HTYP_PROTOCOL_VERSION1;
    4780              : 
    4781              :     /* send ecu id */
    4782         5999 :     if (dlt_user.with_ecu_id)
    4783         5999 :         msg.standardheader->htyp |= DLT_HTYP_WEID;
    4784              : 
    4785              :     /* send timestamp */
    4786         5999 :     if (dlt_user.with_timestamp)
    4787         5999 :         msg.standardheader->htyp |= DLT_HTYP_WTMS;
    4788              : 
    4789              :     /* send session id */
    4790         5999 :     if (dlt_user.with_session_id) {
    4791         5999 :         msg.standardheader->htyp |= DLT_HTYP_WSID;
    4792         5999 :         if (__builtin_expect(!!(dlt_user.local_pid == -1), false)) {
    4793           19 :             dlt_user.local_pid = getpid();
    4794              :         }
    4795         5999 :         msg.headerextra.seid = (uint32_t)dlt_user.local_pid;
    4796              :     }
    4797              : 
    4798         5999 :     if (is_verbose_mode(dlt_user.verbose_mode, log))
    4799              :         /* In verbose mode, send extended header */
    4800         5996 :         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH);
    4801              :     else
    4802              :         /* In non-verbose, send extended header if desired */
    4803            3 :         if (dlt_user.use_extended_header_for_non_verbose)
    4804            2 :             msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH);
    4805              : 
    4806              : #if (BYTE_ORDER == BIG_ENDIAN)
    4807              :     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
    4808              : #endif
    4809              : 
    4810         5999 :     msg.standardheader->mcnt = log->handle->mcnt++;
    4811              : 
    4812              :     /* Set header extra parameters */
    4813         5999 :     dlt_set_id(msg.headerextra.ecu, dlt_user.ecuID);
    4814              : 
    4815              :     /*msg.headerextra.seid = 0; */
    4816         5999 :     if (log->use_timestamp == DLT_AUTO_TIMESTAMP) {
    4817         5998 :         msg.headerextra.tmsp = dlt_uptime();
    4818              :     } else {
    4819            1 :         msg.headerextra.tmsp = log->user_timestamp;
    4820              :     }
    4821              : 
    4822              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4823              :     time_stamp = msg.headerextra.tmsp;
    4824              : #endif
    4825              : 
    4826         5999 :     if (dlt_message_set_extraparameters(&msg, 0) == DLT_RETURN_ERROR) {
    4827            0 :         dlt_mutex_unlock();
    4828            0 :         return DLT_RETURN_ERROR;
    4829              :     }
    4830              : 
    4831              :     /* Fill out extended header, if extended header should be provided */
    4832         5999 :     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp)) {
    4833              :         /* with extended header */
    4834         5998 :         msg.extendedheader =
    4835         5998 :             (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
    4836         5998 :                                  + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
    4837              : 
    4838         5998 :         switch (mtype) {
    4839         5998 :         case DLT_TYPE_LOG: {
    4840         5998 :             msg.extendedheader->msin = (uint8_t)(DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT
    4841         5998 :                                                  | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    4842         5998 :             break;
    4843              :         }
    4844            0 :         case DLT_TYPE_NW_TRACE: {
    4845            0 :             msg.extendedheader->msin = (uint8_t)(DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT
    4846            0 :                                                  | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    4847            0 :             break;
    4848              :         }
    4849            0 :         default: {
    4850              :             /* This case should not occur */
    4851            0 :             dlt_mutex_unlock();
    4852            0 :             return DLT_RETURN_ERROR;
    4853              :             break;
    4854              :         }
    4855              :         }
    4856              : 
    4857              :         /* If in verbose mode, set flag in header for verbose mode */
    4858         5998 :         if (is_verbose_mode(dlt_user.verbose_mode, log))
    4859         5996 :             msg.extendedheader->msin |= DLT_MSIN_VERB;
    4860              : 
    4861         5998 :         msg.extendedheader->noar = (uint8_t)log->args_num;            /* number of arguments */
    4862         5998 :         dlt_set_id(msg.extendedheader->apid, dlt_user.appID);         /* application id */
    4863         5998 :         dlt_set_id(msg.extendedheader->ctid, log->handle->contextID); /* context id */
    4864              : 
    4865         5998 :         msg.headersize = (int32_t)(sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader)
    4866         5998 :                                    + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
    4867              :     } else {
    4868              :         /* without extended header */
    4869            1 :         msg.headersize = (int32_t)(sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
    4870            1 :                                    + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
    4871              :     }
    4872              : 
    4873         5999 :     int32_t tmplen = (int32_t)msg.headersize - (int32_t)sizeof(DltStorageHeader) + (int32_t)log->size;
    4874         5999 :     if (log->size < 0 || tmplen < 0) {
    4875            0 :         dlt_log(LOG_WARNING, "Negative message length!\n");
    4876            0 :         dlt_mutex_unlock();
    4877            0 :         return DLT_RETURN_ERROR;
    4878              :     }
    4879         5999 :     if ((uint32_t)tmplen > UINT16_MAX) {
    4880            0 :         dlt_log(LOG_WARNING, "Huge message discarded!\n");
    4881            0 :         dlt_mutex_unlock();
    4882            0 :         return DLT_RETURN_ERROR;
    4883              :     }
    4884              :     len = (uint32_t)tmplen;
    4885         5999 :     msg.standardheader->len = DLT_HTOBE_16((uint16_t)len);
    4886              : 
    4887              :     /* print to std out, if enabled */
    4888         5999 :     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) && (dlt_user.local_print_mode != DLT_PM_AUTOMATIC)) {
    4889         5999 :         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
    4890            0 :             if (dlt_user_print_msg(&msg, log) == DLT_RETURN_ERROR) {
    4891            0 :                 dlt_mutex_unlock();
    4892            0 :                 return DLT_RETURN_ERROR;
    4893              :             }
    4894              :     }
    4895              : 
    4896         5999 :     if (dlt_user.dlt_is_file) {
    4897            0 :         if (dlt_user_file_reach_max) {
    4898            0 :             dlt_mutex_unlock();
    4899            0 :             return DLT_RETURN_FILESZERR;
    4900              :         } else {
    4901              :             /* Get file size */
    4902              :             struct stat st;
    4903            0 :             if (fstat(dlt_user.dlt_log_handle, &st) != 0) {
    4904            0 :                 dlt_vlog(LOG_WARNING, "%s: Cannot get file information (errno=%d)\n", __func__, errno);
    4905            0 :                 dlt_mutex_unlock();
    4906            0 :                 return DLT_RETURN_ERROR;
    4907              :             }
    4908              : 
    4909            0 :             dlt_vlog(LOG_DEBUG, "%s: Current file size=[%lld]\n", __func__, (long long)st.st_size);
    4910              :             /* Check filesize */
    4911              :             /* Return error if the file size has reached to maximum */
    4912            0 :             unsigned int msg_size = (unsigned int)st.st_size + (unsigned int)msg.headersize + (unsigned int)log->size;
    4913            0 :             if (msg_size > dlt_user.filesize_max) {
    4914            0 :                 dlt_user_file_reach_max = true;
    4915            0 :                 dlt_vlog(
    4916              :                     LOG_ERR, "%s: File size (%lld bytes) reached to defined maximum size (%d bytes)\n", __func__,
    4917              :                     (long long)st.st_size, dlt_user.filesize_max);
    4918            0 :                 dlt_mutex_unlock();
    4919            0 :                 return DLT_RETURN_FILESZERR;
    4920              :             } else {
    4921              :                 /* log to file */
    4922            0 :                 ret = dlt_user_log_out2(
    4923            0 :                     dlt_user.dlt_log_handle, msg.headerbuffer, (size_t)msg.headersize, log->buffer, (size_t)log->size);
    4924            0 :                 dlt_mutex_unlock();
    4925            0 :                 return ret;
    4926              :             }
    4927              :         }
    4928              :     } else {
    4929         5999 :         if (dlt_user.overflow_counter) {
    4930            0 :             if (dlt_user_log_send_overflow() == DLT_RETURN_OK) {
    4931            0 :                 dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "%u messages discarded!\n", dlt_user.overflow_counter);
    4932            0 :                 dlt_user.overflow_counter = 0;
    4933              :             }
    4934              :         }
    4935              : 
    4936              :         /* try to resent old data first */
    4937              :         ret = DLT_RETURN_OK;
    4938              : 
    4939         5999 :         if ((dlt_user.dlt_log_handle != -1) && (dlt_user.appID[0] != '\0')) {
    4940         5999 :             dlt_mutex_lock();
    4941         5999 :             ret = dlt_user_log_resend_buffer();
    4942         5999 :             dlt_mutex_unlock();
    4943              :         }
    4944              : 
    4945         5999 :         if ((ret == DLT_RETURN_OK) && (dlt_user.appID[0] != '\0')) {
    4946              :             /* resend ok or nothing to resent */
    4947              : #ifdef DLT_SHM_ENABLE
    4948              : 
    4949              :             if (dlt_user.dlt_log_handle != -1)
    4950              :                 dlt_shm_push(
    4951              :                     &dlt_user.dlt_shm, msg.headerbuffer + sizeof(DltStorageHeader),
    4952              :                     msg.headersize - sizeof(DltStorageHeader), log->buffer, log->size, 0, 0);
    4953              : 
    4954              :             ret = dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0, 0, 0);
    4955              : #else
    4956              : #ifdef DLT_TEST_ENABLE
    4957              : 
    4958              :             if (dlt_user.corrupt_user_header) {
    4959              :                 userheader.pattern[0] = (char)0xff;
    4960              :                 userheader.pattern[1] = (char)0xff;
    4961              :                 userheader.pattern[2] = (char)0xff;
    4962              :                 userheader.pattern[3] = (char)0xff;
    4963              :             }
    4964              : 
    4965              :             if (dlt_user.corrupt_message_size)
    4966              :                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
    4967              : 
    4968              : #endif
    4969              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4970              :             /* Check trace load before output */
    4971              :             if (!sent_size) {
    4972              :                 int pos = log->handle->log_level_pos;
    4973              :                 char ctxid[DLT_ID_SIZE];
    4974              :                 memcpy(ctxid, log->handle->contextID, DLT_ID_SIZE);
    4975              : 
    4976              :                 if ((uint32_t)pos > dlt_user.dlt_ll_ts_num_entries) {
    4977              :                     char msg_buffer[255];
    4978              :                     sprintf(
    4979              :                         msg_buffer, "log handle has invalid log level pos %d, current entries: %u, dropping message\n",
    4980              :                         log->handle->log_level_pos, dlt_user.dlt_ll_ts_num_entries);
    4981              :                     dlt_mutex_unlock();
    4982              :                     dlt_user_output_internal_msg(LOG_ERR, msg_buffer, NULL);
    4983              :                     return DLT_RETURN_ERROR;
    4984              :                 }
    4985              :                 dlt_mutex_unlock();
    4986              : 
    4987              :                 pthread_rwlock_rdlock(&trace_load_rw_lock);
    4988              :                 DltTraceLoadSettings* computed_settings = dlt_find_runtime_trace_load_settings(
    4989              :                     trace_load_settings, trace_load_settings_count, dlt_user.appID, ctxid);
    4990              :                 pthread_rwlock_unlock(&trace_load_rw_lock);
    4991              : 
    4992              :                 dlt_mutex_lock();
    4993              :                 if ((uint32_t)pos < dlt_user.dlt_ll_ts_num_entries) {
    4994              :                     dlt_ll_ts_type* ll_ts = &dlt_user.dlt_ll_ts[pos];
    4995              :                     if (ll_ts->trace_load_settings == NULL) {
    4996              :                         ll_ts->trace_load_settings = computed_settings;
    4997              :                     }
    4998              :                 }
    4999              :                 dlt_mutex_unlock();
    5000              :                 size_t trace_load_size = (size_t)sizeof(DltUserHeader) + (size_t)msg.headersize
    5001              :                                          - (size_t)sizeof(DltStorageHeader) + (size_t)log->size;
    5002              : 
    5003              :                 int32_t trace_load_size_i32 = safe_size_to_int32(trace_load_size);
    5004              :                 const bool trace_load_in_limits = dlt_check_trace_load(
    5005              :                     computed_settings, log->log_level, time_stamp, trace_load_size_i32, dlt_user_output_internal_msg,
    5006              :                     NULL);
    5007              : 
    5008              :                 if (!trace_load_in_limits) {
    5009              :                     return DLT_RETURN_LOAD_EXCEEDED;
    5010              :                 }
    5011              :                 dlt_mutex_lock();
    5012              :             } else {
    5013              :                 {
    5014              :                     size_t total_size = (size_t)sizeof(DltUserHeader) + (size_t)msg.headersize
    5015              :                                         - (size_t)sizeof(DltStorageHeader) + (size_t)log->size;
    5016              :                     *sent_size = safe_size_to_int32(total_size);
    5017              :                 }
    5018              :             }
    5019              : #endif
    5020              : 
    5021         5999 :             ret = dlt_user_log_out3(
    5022              :                 dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
    5023         5999 :                 msg.headerbuffer + sizeof(DltStorageHeader), (size_t)msg.headersize - (size_t)sizeof(DltStorageHeader),
    5024         5999 :                 log->buffer, (size_t)log->size);
    5025              : #endif
    5026              :         }
    5027              : 
    5028              :         DltReturnValue process_error_ret = DLT_RETURN_OK;
    5029              :         /* store message in ringbuffer, if an error has occurred */
    5030              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    5031              :         if (((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0')) && !sent_size)
    5032              : #else
    5033         5999 :         if ((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0'))
    5034              : #endif
    5035         1308 :             process_error_ret = dlt_user_log_out_error_handling(
    5036              :                 &(userheader), sizeof(DltUserHeader), msg.headerbuffer + sizeof(DltStorageHeader),
    5037         1308 :                 (size_t)msg.headersize - (size_t)sizeof(DltStorageHeader), log->buffer, (size_t)log->size);
    5038              : 
    5039         1308 :         if (process_error_ret == DLT_RETURN_OK) {
    5040         5999 :             dlt_mutex_unlock();
    5041         5999 :             return DLT_RETURN_OK;
    5042              :         }
    5043            0 :         if (process_error_ret == DLT_RETURN_BUFFER_FULL) {
    5044              :             /* Buffer full */
    5045            0 :             dlt_user.overflow_counter += 1;
    5046            0 :             dlt_mutex_unlock();
    5047            0 :             return DLT_RETURN_BUFFER_FULL;
    5048              :         }
    5049              : 
    5050              :         /* handle return value of function dlt_user_log_out3() when process_error_ret < 0*/
    5051            0 :         switch (ret) {
    5052            0 :         case DLT_RETURN_PIPE_FULL: {
    5053              :             /* data could not be written */
    5054            0 :             dlt_mutex_unlock();
    5055            0 :             return DLT_RETURN_PIPE_FULL;
    5056              :         }
    5057            0 :         case DLT_RETURN_PIPE_ERROR: {
    5058              :             /* handle not open or pipe error */
    5059            0 :             close(dlt_user.dlt_log_handle);
    5060            0 :             dlt_user.dlt_log_handle = -1;
    5061              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    5062              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
    5063              : #endif
    5064              : 
    5065              : #ifdef DLT_SHM_ENABLE
    5066              :             /* free shared memory */
    5067              :             dlt_shm_free_client(&dlt_user.dlt_shm);
    5068              : #endif
    5069              : 
    5070            0 :             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
    5071            0 :                 dlt_user_print_msg(&msg, log);
    5072              : 
    5073            0 :             dlt_mutex_unlock();
    5074            0 :             return DLT_RETURN_PIPE_ERROR;
    5075              :         }
    5076            0 :         case DLT_RETURN_ERROR: {
    5077              :             /* other error condition */
    5078            0 :             dlt_mutex_unlock();
    5079            0 :             return DLT_RETURN_ERROR;
    5080              :         }
    5081            0 :         case DLT_RETURN_OK: {
    5082            0 :             dlt_mutex_unlock();
    5083            0 :             return DLT_RETURN_OK;
    5084              :         }
    5085            0 :         default: {
    5086              :             /* This case should never occur. */
    5087            0 :             dlt_mutex_unlock();
    5088            0 :             return DLT_RETURN_ERROR;
    5089              :         }
    5090              :         }
    5091              :     }
    5092              : 
    5093              :     dlt_mutex_unlock();
    5094              :     return DLT_RETURN_OK;
    5095              : }
    5096              : 
    5097           30 : DltReturnValue dlt_user_log_send_log_v2(
    5098              :     DltContextData* log, const int mtype, DltHtyp2ContentType msgcontent, int* const sent_size)
    5099              : {
    5100           30 :     DltMessageV2 msg = {0};
    5101              :     DltUserHeader userheader;
    5102              :     uint32_t len;
    5103              : 
    5104              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    5105              :     uint32_t time_stamp;
    5106              : #else
    5107              :     // shut up warning
    5108              :     (void)sent_size;
    5109              : #endif
    5110              : 
    5111              :     DltReturnValue ret = DLT_RETURN_OK;
    5112           30 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    5113            0 :         dlt_vlog(
    5114              :             LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __func__,
    5115            0 :             dlt_user_init_state, dlt_user_freeing);
    5116            0 :         return DLT_RETURN_ERROR;
    5117              :     }
    5118              : 
    5119           30 :     if ((log == NULL) || (log->handle == NULL) || (log->handle->contextID2 == NULL) || (mtype < DLT_TYPE_LOG)
    5120           21 :         || (mtype > DLT_TYPE_CONTROL) || (msgcontent < DLT_VERBOSE_DATA_MSG) || (msgcontent > DLT_CONTROL_MSG))
    5121              :         return DLT_RETURN_WRONG_PARAMETER;
    5122              : 
    5123              :     /* also for Trace messages */
    5124           21 :     if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_LOG) < DLT_RETURN_OK)
    5125              :         return DLT_RETURN_ERROR;
    5126              : 
    5127           21 :     if (dlt_message_init_v2(&msg, 0) == DLT_RETURN_ERROR)
    5128              :         return DLT_RETURN_ERROR;
    5129           21 :     msg.storageheadersizev2 = STORAGE_HEADER_V2_FIXED_SIZE + (uint32_t)dlt_user.ecuID2len;
    5130           21 :     msg.baseheadersizev2 = BASE_HEADER_V2_FIXED_SIZE;
    5131           21 :     msg.baseheaderextrasizev2 = (uint32_t)dlt_message_get_extraparameters_size_v2(msgcontent);
    5132           21 :     msg.extendedheadersizev2 = (uint32_t)dlt_get_extendedheadersize_v2(dlt_user, log->handle->contextID2len);
    5133              : 
    5134           21 :     msg.headersizev2 = (int32_t)(msg.storageheadersizev2 + msg.baseheadersizev2 + msg.baseheaderextrasizev2
    5135           21 :                                  + msg.extendedheadersizev2);
    5136              : 
    5137           21 :     if (msg.headerbufferv2 != NULL) {
    5138            0 :         free(msg.headerbufferv2);
    5139              :         msg.headerbufferv2 = NULL;
    5140              :     }
    5141              : 
    5142           21 :     msg.headerbufferv2 = (uint8_t*)malloc((size_t)msg.headersizev2);
    5143              : 
    5144           21 :     if (dlt_set_storageheader_v2(&(msg.storageheaderv2), dlt_user.ecuID2len, dlt_user.ecuID2) == DLT_RETURN_ERROR)
    5145              :         return DLT_RETURN_ERROR;
    5146              : 
    5147           21 :     if (dlt_message_set_storageparameters_v2(&msg, 0) != DLT_RETURN_OK)
    5148              :         return DLT_RETURN_ERROR;
    5149              : 
    5150           21 :     msg.baseheaderv2 = (DltBaseHeaderV2*)(msg.headerbufferv2 + msg.storageheadersizev2);
    5151              :     msg.baseheaderv2->htyp2 = DLT_HTYP2_PROTOCOL_VERSION2;
    5152              : 
    5153           21 :     msg.baseheaderv2->htyp2 |= msgcontent;
    5154              : 
    5155              :     /* send ecu id */
    5156           21 :     if (dlt_user.with_ecu_id)
    5157           21 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WEID;
    5158              : 
    5159              :     /* send app and context id */
    5160           21 :     if (dlt_user.with_app_and_context_id)
    5161           21 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WACID;
    5162              : 
    5163              :     /* send session id */
    5164           21 :     if (dlt_user.with_session_id) {
    5165           21 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WSID;
    5166              :     }
    5167              : 
    5168              :     /* send source filename and line number */
    5169           21 :     if (dlt_user.with_filename_and_line_number)
    5170            0 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WSFLN;
    5171              : 
    5172              :     /* send Tags */
    5173           21 :     if (dlt_user.with_tags)
    5174            0 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WTGS;
    5175              : 
    5176              :     /* send privacy level */
    5177           21 :     if (dlt_user.with_privacy_level)
    5178            0 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WPVL;
    5179              : 
    5180              :     /* send segmented message */
    5181           21 :     if (dlt_user.with_segmentation)
    5182            0 :         msg.baseheaderv2->htyp2 |= DLT_HTYP2_WSGM;
    5183              : 
    5184           21 :     msg.baseheaderv2->mcnt = log->handle->mcnt++;
    5185              : 
    5186              :     /* Fill base header conditional parameters */
    5187              : 
    5188           21 :     if (msgcontent == DLT_VERBOSE_DATA_MSG) {
    5189              :         /* To Update Handle all mtypes*/
    5190           21 :         switch (mtype) {
    5191           21 :         case DLT_TYPE_LOG: {
    5192           21 :             msg.headerextrav2.msin = (uint8_t)(DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT
    5193           21 :                                                | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    5194           21 :             break;
    5195              :         }
    5196            0 :         case DLT_TYPE_NW_TRACE: {
    5197            0 :             msg.headerextrav2.msin = (uint8_t)(DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT
    5198            0 :                                                | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    5199            0 :             break;
    5200              :         }
    5201              :         default: {
    5202              :             /* This case should not occur */
    5203              :             return DLT_RETURN_ERROR;
    5204              :             break;
    5205              :         }
    5206              :         }
    5207              :         /* If in verbose mode, set flag in header for verbose mode */
    5208           21 :         if (is_verbose_mode(dlt_user.verbose_mode, log))
    5209           21 :             msg.headerextrav2.msin |= DLT_MSIN_VERB;
    5210           21 :         msg.headerextrav2.noar = (uint8_t)log->args_num; /* number of arguments */
    5211              :     }
    5212              : 
    5213           21 :     if ((msgcontent == DLT_VERBOSE_DATA_MSG) || (msgcontent == DLT_NON_VERBOSE_DATA_MSG)) {
    5214              :         memset(msg.headerextrav2.seconds, 0, 5);
    5215           21 :         msg.headerextrav2.nanoseconds = 0;
    5216              : #if defined(__WIN32__) || defined(_MSC_VER)
    5217              :         time_t t = time(NULL);
    5218              :         if (t == -1) {
    5219              :             uint32_t tcnt = (uint32_t)(GetTickCount()); /* GetTickCount() in 10 ms resolution */
    5220              :             tcnt_seconds = tcnt / 100;
    5221              :             tcnt_ns = (tcnt - (tcnt * 100)) * 10000;
    5222              :             msg.headerextrav2.seconds[0] = (tcnt_seconds >> 32) & 0xFF;
    5223              :             msg.headerextrav2.seconds[1] = (tcnt_seconds >> 24) & 0xFF;
    5224              :             msg.headerextrav2.seconds[2] = (tcnt_seconds >> 16) & 0xFF;
    5225              :             msg.headerextrav2.seconds[3] = (tcnt_seconds >> 8) & 0xFF;
    5226              :             msg.headerextrav2.seconds[4] = tcnt_seconds & 0xFF;
    5227              :             if (ts.tv_nsec < 0x3B9ACA00) {
    5228              :                 msg.headerextrav2.nanoseconds = tcnt_ns;
    5229              :             }
    5230              :         } else {
    5231              :             msg.headerextrav2.seconds[0] = (t >> 32) & 0xFF;
    5232              :             msg.headerextrav2.seconds[1] = (t >> 24) & 0xFF;
    5233              :             msg.headerextrav2.seconds[2] = (t >> 16) & 0xFF;
    5234              :             msg.headerextrav2.seconds[3] = (t >> 8) & 0xFF;
    5235              :             msg.headerextrav2.seconds[4] = t & 0xFF;
    5236              :             msg.headerextrav2.nanoseconds |= 0x80000000;
    5237              :         }
    5238              : #else
    5239              :         struct timespec ts;
    5240           21 :         if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
    5241           21 :             msg.headerextrav2.seconds[0] = (uint8_t)(((uint64_t)ts.tv_sec >> 32) & 0xFF);
    5242           21 :             msg.headerextrav2.seconds[1] = (uint8_t)((ts.tv_sec >> 24) & 0xFF);
    5243           21 :             msg.headerextrav2.seconds[2] = (uint8_t)((ts.tv_sec >> 16) & 0xFF);
    5244           21 :             msg.headerextrav2.seconds[3] = (uint8_t)((ts.tv_sec >> 8) & 0xFF);
    5245           21 :             msg.headerextrav2.seconds[4] = (uint8_t)(ts.tv_sec & 0xFF);
    5246           21 :             if (ts.tv_nsec < 0x3B9ACA00) {
    5247           21 :                 msg.headerextrav2.nanoseconds = (uint32_t)ts.tv_nsec; /* value is long */
    5248              :             }
    5249            0 :         } else if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
    5250            0 :             msg.headerextrav2.seconds[0] = (uint8_t)(((uint64_t)ts.tv_sec >> 32) & 0xFF);
    5251            0 :             msg.headerextrav2.seconds[1] = (uint8_t)((ts.tv_sec >> 24) & 0xFF);
    5252            0 :             msg.headerextrav2.seconds[2] = (uint8_t)((ts.tv_sec >> 16) & 0xFF);
    5253            0 :             msg.headerextrav2.seconds[3] = (uint8_t)((ts.tv_sec >> 8) & 0xFF);
    5254            0 :             msg.headerextrav2.seconds[4] = (uint8_t)(ts.tv_sec & 0xFF);
    5255            0 :             if (ts.tv_nsec < 0x3B9ACA00) {
    5256            0 :                 msg.headerextrav2.nanoseconds = (uint32_t)ts.tv_nsec; /* value is long */
    5257              :             }
    5258            0 :             msg.headerextrav2.nanoseconds |= 0x80000000;
    5259              :         }
    5260              : #endif
    5261              :     }
    5262              : 
    5263           21 :     if (msgcontent == DLT_NON_VERBOSE_DATA_MSG) {
    5264            0 :         msg.headerextrav2.msid = log->msid;
    5265              :     }
    5266              : 
    5267              :     /* TODO:
    5268              :     #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    5269              :         time_stamp = msg.headerextra.tmsp;
    5270              :     #endif
    5271              :     */
    5272              : 
    5273           21 :     if (dlt_message_set_extraparameters_v2(&msg, 0) != DLT_RETURN_OK)
    5274              :         return DLT_RETURN_ERROR;
    5275              : 
    5276              :     /* Fill out extended header, if extended header should be provided */
    5277           21 :     if (DLT_IS_HTYP2_WEID(msg.baseheaderv2->htyp2)) {
    5278           21 :         msg.extendedheaderv2.ecidlen = dlt_user.ecuID2len;
    5279           21 :         if (msg.extendedheaderv2.ecidlen > 0) {
    5280           21 :             msg.extendedheaderv2.ecid = dlt_user.ecuID2;
    5281              :         } else {
    5282            0 :             msg.extendedheaderv2.ecid = NULL;
    5283              :         }
    5284              :     }
    5285              : 
    5286           21 :     if (DLT_IS_HTYP2_WACID(msg.baseheaderv2->htyp2)) {
    5287           21 :         msg.extendedheaderv2.apidlen = dlt_user.appID2len;
    5288           21 :         if (msg.extendedheaderv2.apidlen > 0) {
    5289           21 :             msg.extendedheaderv2.apid = dlt_user.appID2;
    5290              :         } else {
    5291            0 :             msg.extendedheaderv2.apid = NULL;
    5292              :         }
    5293              : 
    5294           21 :         msg.extendedheaderv2.ctidlen = log->handle->contextID2len;
    5295           21 :         if (msg.extendedheaderv2.ctidlen > 0) {
    5296           21 :             msg.extendedheaderv2.ctid = log->handle->contextID2;
    5297              :         } else {
    5298            0 :             msg.extendedheaderv2.ctid = NULL;
    5299              :         }
    5300              :     }
    5301              : 
    5302           21 :     if (DLT_IS_HTYP2_WSID(msg.baseheaderv2->htyp2)) {
    5303           21 :         if (__builtin_expect(!!(dlt_user.local_pid == -1), false)) {
    5304            1 :             dlt_user.local_pid = getpid();
    5305              :         }
    5306           21 :         msg.extendedheaderv2.seid = (uint32_t)dlt_user.local_pid;
    5307              :     }
    5308              : 
    5309           21 :     if (DLT_IS_HTYP2_WSFLN(msg.baseheaderv2->htyp2)) {
    5310            0 :         msg.extendedheaderv2.finalen = dlt_user.filenamelen;
    5311            0 :         if (msg.extendedheaderv2.finalen > 0) {
    5312            0 :             msg.extendedheaderv2.fina = dlt_user.filename;
    5313              :         } else {
    5314            0 :             msg.extendedheaderv2.fina = NULL;
    5315              :         }
    5316            0 :         msg.extendedheaderv2.linr = dlt_user.linenumber;
    5317              :     }
    5318              : 
    5319           21 :     if (DLT_IS_HTYP2_WTGS(msg.baseheaderv2->htyp2)) {
    5320            0 :         msg.extendedheaderv2.notg = dlt_user.numberoftags;
    5321            0 :         if (msg.extendedheaderv2.notg == 0) {
    5322            0 :             msg.extendedheaderv2.tag = NULL;
    5323              :         } else {
    5324            0 :             msg.extendedheaderv2.tag = (DltTag*)malloc((msg.extendedheaderv2.notg) * sizeof(DltTag));
    5325            0 :             if (msg.extendedheaderv2.tag == NULL) {
    5326              :                 return DLT_RETURN_ERROR;
    5327              :             }
    5328            0 :             memcpy(msg.extendedheaderv2.tag, dlt_user.tag, ((dlt_user.numberoftags) * sizeof(DltTag)));
    5329              :         }
    5330              :     }
    5331              : 
    5332              :     /* free temporary container of tag pointers after extended parameters are
    5333              :      * copied into the message header buffer by dlt_message_set_extendedparameters_v2()
    5334              :      * to avoid leaking the allocated array of DltTag structures. The actual
    5335              :      * tag name strings are owned by dlt_user.tag and are freed in dlt_free().
    5336              :      */
    5337           21 :     if (dlt_message_set_extendedparameters_v2(&msg) != DLT_RETURN_OK)
    5338              :         return DLT_RETURN_ERROR;
    5339              : 
    5340           21 :     if (msg.extendedheaderv2.tag != NULL) {
    5341            0 :         free(msg.extendedheaderv2.tag);
    5342            0 :         msg.extendedheaderv2.tag = NULL;
    5343              :     }
    5344              : 
    5345           21 :     if (DLT_IS_HTYP2_WPVL(msg.baseheaderv2->htyp2)) {
    5346            0 :         msg.extendedheaderv2.prlv = dlt_user.prlv;
    5347              :     }
    5348              : 
    5349              :     /* To update: Segmentation part
    5350              :     if (DLT_IS_HTYP2_WSGM(msg.baseheaderv2->htyp2)) {
    5351              :     }
    5352              :     */
    5353              : 
    5354           21 :     int32_t tmplen = (int32_t)msg.headersizev2 - (int32_t)msg.storageheadersizev2 + (int32_t)log->size;
    5355           21 :     if (log->size < 0 || tmplen < 0) {
    5356            0 :         dlt_log(LOG_WARNING, "Negative message length!\n");
    5357            0 :         return DLT_RETURN_ERROR;
    5358              :     }
    5359           21 :     if ((uint32_t)tmplen > UINT16_MAX) {
    5360            0 :         dlt_log(LOG_WARNING, "Huge message discarded!\n");
    5361            0 :         return DLT_RETURN_ERROR;
    5362              :     }
    5363              :     len = (uint32_t)tmplen;
    5364              : 
    5365           21 :     msg.baseheaderv2->len = DLT_HTOBE_16((uint16_t)len);
    5366              : 
    5367              :     /* print to std out, if enabled */
    5368           21 :     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) && (dlt_user.local_print_mode != DLT_PM_AUTOMATIC)) {
    5369           21 :         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
    5370            0 :             if (dlt_user_print_msg_v2(&msg, log) == DLT_RETURN_ERROR)
    5371              :                 return DLT_RETURN_ERROR;
    5372              :     }
    5373              : 
    5374           21 :     if (dlt_user.dlt_is_file) {
    5375            0 :         if (dlt_user_file_reach_max) {
    5376              :             return DLT_RETURN_FILESZERR;
    5377              :         } else {
    5378              :             /* Get file size */
    5379              :             struct stat st;
    5380            0 :             if (fstat(dlt_user.dlt_log_handle, &st) != 0) {
    5381            0 :                 dlt_vlog(LOG_WARNING, "%s: Cannot get file information (errno=%d)\n", __func__, errno);
    5382            0 :                 return DLT_RETURN_ERROR;
    5383              :             }
    5384              : 
    5385            0 :             dlt_vlog(LOG_DEBUG, "%s: Current file size=[%lld]\n", __func__, (long long)st.st_size);
    5386              :             /* Check filesize */
    5387              :             /* Return error if the file size has reached to maximum */
    5388              :             unsigned int msg_size = 0;
    5389            0 :             if (st.st_size < 0 || st.st_size > UINT_MAX) {
    5390            0 :                 dlt_vlog(
    5391              :                     LOG_ERR, "%s: File size (%lld bytes) is invalid or too large for unsigned int\n", __func__,
    5392              :                     (long long)st.st_size);
    5393            0 :                 return DLT_RETURN_FILESZERR;
    5394              :             }
    5395            0 :             msg_size = (unsigned int)st.st_size + (unsigned int)msg.headersizev2 + (unsigned int)log->size;
    5396            0 :             if (msg_size > dlt_user.filesize_max) {
    5397            0 :                 dlt_user_file_reach_max = true;
    5398            0 :                 dlt_vlog(
    5399              :                     LOG_ERR, "%s: File size (%lld bytes) reached to defined maximum size (%d bytes)\n", __func__,
    5400              :                     (long long)st.st_size, dlt_user.filesize_max);
    5401            0 :                 return DLT_RETURN_FILESZERR;
    5402              :             } else {
    5403              :                 /* log to file */
    5404              :                 int32_t headersizev2 = msg.headersizev2;
    5405              :                 int32_t logsize = log->size;
    5406            0 :                 if (headersizev2 < 0 || logsize < 0) {
    5407            0 :                     dlt_log(LOG_WARNING, "Negative header or log size!\n");
    5408            0 :                     return DLT_RETURN_ERROR;
    5409              :                 }
    5410            0 :                 ret = dlt_user_log_out2(
    5411            0 :                     dlt_user.dlt_log_handle, msg.headerbufferv2, (size_t)headersizev2, log->buffer, (size_t)logsize);
    5412            0 :                 return ret;
    5413              :             }
    5414              :         }
    5415              :     } else {
    5416           21 :         if (dlt_user.overflow_counter) {
    5417            0 :             if (dlt_user_log_send_overflow() == DLT_RETURN_OK) {
    5418            0 :                 dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "%u messages discarded!\n", dlt_user.overflow_counter);
    5419            0 :                 dlt_user.overflow_counter = 0;
    5420              :             }
    5421              :         }
    5422              : 
    5423              :         /* try to resent old data first */
    5424              :         ret = DLT_RETURN_OK;
    5425              : 
    5426           21 :         if ((dlt_user.dlt_log_handle != -1) && (dlt_user.appID2len != 0)) {
    5427            0 :             ret = dlt_user_log_resend_buffer();
    5428              :         }
    5429              : 
    5430           21 :         if ((ret == DLT_RETURN_OK) && (dlt_user.appID2len != 0)) {
    5431              :             /* resend ok or nothing to resent */
    5432              : #ifdef DLT_SHM_ENABLE
    5433              : 
    5434              :             if (dlt_user.dlt_log_handle != -1)
    5435              :                 dlt_shm_push(
    5436              :                     &dlt_user.dlt_shm, msg.headerbufferv2 + msg.storageheadersizev2,
    5437              :                     msg.headersizev2 - msg.storageheadersizev2, log->buffer, log->size, 0, 0);
    5438              : 
    5439              :             ret = dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0, 0, 0);
    5440              : #else
    5441              : #ifdef DLT_TEST_ENABLE
    5442              : 
    5443              :             if (dlt_user.corrupt_user_header) {
    5444              :                 userheader.pattern[0] = (char)0xff;
    5445              :                 userheader.pattern[1] = (char)0xff;
    5446              :                 userheader.pattern[2] = (char)0xff;
    5447              :                 userheader.pattern[3] = (char)0xff;
    5448              :             }
    5449              : 
    5450              :             if (dlt_user.corrupt_message_size)
    5451              :                 msg.baseheaderv2->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
    5452              : 
    5453              : #endif
    5454              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    5455              :             /* check trace load before output */
    5456              :             if (!sent_size) {
    5457              :                 pthread_rwlock_wrlock(&trace_load_rw_lock);
    5458              :                 DltTraceLoadSettings* settings = dlt_find_runtime_trace_load_settings(
    5459              :                     trace_load_settings, trace_load_settings_count, dlt_user.appID2, log->handle->contextID2);
    5460              :                 const bool trace_load_in_limits = dlt_check_trace_load(
    5461              :                     settings, log->log_level, time_stamp,
    5462              :                     sizeof(DltUserHeader) + msg.headersizev2 - msg.storageheadersizev2 + log->size,
    5463              :                     dlt_user_output_internal_msg, NULL);
    5464              :                 pthread_rwlock_unlock(&trace_load_rw_lock);
    5465              :                 if (!trace_load_in_limits) {
    5466              :                     return DLT_RETURN_LOAD_EXCEEDED;
    5467              :                 }
    5468              :             } else {
    5469              :                 *sent_size = (sizeof(DltUserHeader) + msg.headersizev2 - msg.storageheadersizev2 + log->size);
    5470              :             }
    5471              : #endif
    5472              : 
    5473           21 :             int32_t header_size = (int32_t)msg.headersizev2 - (int32_t)msg.storageheadersizev2;
    5474           21 :             int32_t logsize = log->size;
    5475           21 :             if (header_size < 0 || logsize < 0) {
    5476            0 :                 dlt_log(LOG_WARNING, "Negative header or log size!\n");
    5477            0 :                 return DLT_RETURN_ERROR;
    5478              :             }
    5479           21 :             ret = dlt_user_log_out3(
    5480              :                 dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
    5481           21 :                 msg.headerbufferv2 + msg.storageheadersizev2, (uint32_t)header_size, log->buffer, (size_t)logsize);
    5482              : 
    5483              : #endif
    5484              :         }
    5485              : 
    5486              :         DltReturnValue process_error_ret = DLT_RETURN_OK;
    5487              :         /* store message in ringbuffer, if an error has occurred */
    5488              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    5489              :         if (((ret != DLT_RETURN_OK) || (dlt_user.appID2len == 0)) && !sent_size)
    5490              : #else
    5491           21 :         if ((ret != DLT_RETURN_OK) || (dlt_user.appID2len == 0))
    5492              : #endif
    5493              :         {
    5494           21 :             int32_t header_size2 = (int32_t)msg.headersizev2 - (int32_t)msg.storageheadersizev2;
    5495           21 :             int32_t logsize2 = log->size;
    5496           21 :             if (header_size2 < 0 || logsize2 < 0) {
    5497            0 :                 dlt_log(LOG_WARNING, "Negative header or log size!\n");
    5498            0 :                 return DLT_RETURN_ERROR;
    5499              :             }
    5500           21 :             process_error_ret = dlt_user_log_out_error_handling(
    5501           21 :                 &(userheader), sizeof(DltUserHeader), msg.headerbufferv2 + msg.storageheadersizev2,
    5502           21 :                 (uint32_t)header_size2, log->buffer, (size_t)logsize2);
    5503              :         }
    5504              : 
    5505           21 :         if (process_error_ret == DLT_RETURN_OK) {
    5506              :             {
    5507           21 :                 unsigned char* headerbufferv2_ptr = msg.headerbufferv2;
    5508              :                 dlt_user_free_buffer(&headerbufferv2_ptr);
    5509              :             }
    5510           21 :             return DLT_RETURN_OK;
    5511              :         }
    5512              : 
    5513            0 :         if (process_error_ret == DLT_RETURN_BUFFER_FULL) {
    5514              :             /* Buffer full */
    5515            0 :             dlt_user.overflow_counter += 1;
    5516            0 :             return DLT_RETURN_BUFFER_FULL;
    5517              :         }
    5518              : 
    5519              :         /* handle return value of function dlt_user_log_out3() when process_error_ret < 0*/
    5520            0 :         switch (ret) {
    5521              :         case DLT_RETURN_PIPE_FULL: {
    5522              :             /* data could not be written */
    5523              :             return DLT_RETURN_PIPE_FULL;
    5524              :         }
    5525            0 :         case DLT_RETURN_PIPE_ERROR: {
    5526              :             /* handle not open or pipe error */
    5527            0 :             dlt_mutex_lock();
    5528            0 :             close(dlt_user.dlt_log_handle);
    5529            0 :             dlt_user.dlt_log_handle = -1;
    5530            0 :             dlt_mutex_unlock();
    5531              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    5532              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
    5533              : #endif
    5534              : 
    5535              : #ifdef DLT_SHM_ENABLE
    5536              :             /* free shared memory */
    5537              :             dlt_shm_free_client(&dlt_user.dlt_shm);
    5538              : #endif
    5539              : 
    5540            0 :             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
    5541            0 :                 dlt_user_print_msg_v2(&msg, log);
    5542              : 
    5543            0 :             return DLT_RETURN_PIPE_ERROR;
    5544              :         }
    5545              :         case DLT_RETURN_ERROR: {
    5546              :             /* other error condition */
    5547              :             return DLT_RETURN_ERROR;
    5548              :         }
    5549            0 :         case DLT_RETURN_OK: {
    5550              :             {
    5551            0 :                 unsigned char* headerbufferv2_ptr = msg.headerbufferv2;
    5552              :                 dlt_user_free_buffer(&headerbufferv2_ptr);
    5553              :             }
    5554            0 :             return DLT_RETURN_OK;
    5555              :         }
    5556              :         default: {
    5557              :             /* This case should never occur. */
    5558              :             return DLT_RETURN_ERROR;
    5559              :         }
    5560              :         }
    5561              :     }
    5562              : 
    5563              :     unsigned char* headerbufferv2_ptr = msg.headerbufferv2;
    5564              :     dlt_user_free_buffer(&headerbufferv2_ptr);
    5565              :     return DLT_RETURN_OK;
    5566              : }
    5567              : 
    5568          171 : DltReturnValue dlt_user_log_send_register_application(void)
    5569              : {
    5570              :     DltUserHeader userheader;
    5571              :     DltUserControlMsgRegisterApplication usercontext;
    5572              : 
    5573              :     DltReturnValue ret;
    5574              : 
    5575          171 :     if (dlt_user.appID[0] == '\0')
    5576              :         return DLT_RETURN_ERROR;
    5577              : 
    5578              :     /* set userheader */
    5579          171 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION) < DLT_RETURN_OK)
    5580              :         return DLT_RETURN_ERROR;
    5581              : 
    5582              :     /* set usercontext */
    5583          171 :     dlt_set_id(usercontext.apid, dlt_user.appID); /* application id */
    5584          171 :     usercontext.pid = getpid();
    5585              : 
    5586          171 :     if (dlt_user.application_description != NULL)
    5587          171 :         usercontext.description_length = (uint32_t)strlen(dlt_user.application_description);
    5588              :     else
    5589            0 :         usercontext.description_length = 0;
    5590              : 
    5591          171 :     if (dlt_user.dlt_is_file)
    5592              :         return DLT_RETURN_OK;
    5593              : 
    5594          171 :     ret = dlt_user_log_out3(
    5595              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext),
    5596          171 :         sizeof(DltUserControlMsgRegisterApplication), dlt_user.application_description, usercontext.description_length);
    5597              : 
    5598              :     /* store message in ringbuffer, if an error has occured */
    5599          171 :     if (ret < DLT_RETURN_OK)
    5600            0 :         return dlt_user_log_out_error_handling(
    5601              :             &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),
    5602            0 :             dlt_user.application_description, usercontext.description_length);
    5603              : 
    5604              :     return DLT_RETURN_OK;
    5605              : }
    5606              : 
    5607           24 : DltReturnValue dlt_user_log_send_register_application_v2(void)
    5608              : {
    5609              :     DltUserHeader userheader;
    5610              :     DltUserControlMsgRegisterApplicationV2 usercontext;
    5611              :     char apid_local[DLT_V2_ID_SIZE];
    5612           24 :     usercontext.apid = apid_local;
    5613              :     uint8_t* buffer;
    5614              :     DltReturnValue ret;
    5615              :     int usercontextSize;
    5616              : 
    5617           24 :     if (dlt_user.appID2len == 0)
    5618              :         return DLT_RETURN_ERROR;
    5619              : 
    5620              :     /* set userheader */
    5621           24 :     if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION) < DLT_RETURN_OK)
    5622              :         return DLT_RETURN_ERROR;
    5623              : 
    5624              :     /* set usercontext */
    5625           24 :     dlt_set_id_v2(usercontext.apid, dlt_user.appID2, dlt_user.appID2len); /* application id */
    5626           24 :     usercontext.apidlen = dlt_user.appID2len;
    5627           24 :     usercontext.pid = getpid();
    5628              : 
    5629           24 :     if (dlt_user.application_description != NULL)
    5630           24 :         usercontext.description_length = (uint32_t)strlen(dlt_user.application_description);
    5631              :     else
    5632            0 :         usercontext.description_length = 0;
    5633              : 
    5634           24 :     if (dlt_user.dlt_is_file)
    5635              :         return DLT_RETURN_OK;
    5636              : 
    5637           24 :     usercontextSize = (int)sizeof(uint8_t) + usercontext.apidlen + (int)sizeof(pid_t) + (int)sizeof(uint32_t);
    5638           24 :     buffer = (uint8_t*)malloc((size_t)usercontextSize);
    5639           24 :     if (!buffer)
    5640              :         return DLT_RETURN_ERROR;
    5641              : 
    5642              :     memset(buffer, usercontext.apidlen, 1);
    5643           24 :     if (usercontext.apid == NULL && usercontext.apidlen > 0) {
    5644            0 :         free(buffer);
    5645            0 :         return DLT_RETURN_ERROR;
    5646              :     }
    5647           24 :     memcpy(buffer + 1, usercontext.apid, usercontext.apidlen);
    5648           24 :     memcpy((buffer + 1 + usercontext.apidlen), &(usercontext.pid), sizeof(pid_t));
    5649           24 :     memcpy((buffer + 1 + usercontext.apidlen + sizeof(pid_t)), &(usercontext.description_length), sizeof(uint32_t));
    5650              : 
    5651           24 :     ret = dlt_user_log_out3(
    5652              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize,
    5653           24 :         dlt_user.application_description, usercontext.description_length);
    5654              : 
    5655              :     /* store message in ringbuffer, if an error has occured */
    5656           24 :     if (ret < DLT_RETURN_OK)
    5657           24 :         ret = dlt_user_log_out_error_handling(
    5658           24 :             &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize, dlt_user.application_description,
    5659           24 :             usercontext.description_length);
    5660              : 
    5661           24 :     free(buffer);
    5662              : 
    5663           24 :     return ret;
    5664              : }
    5665              : 
    5666          182 : DltReturnValue dlt_user_log_send_unregister_application(void)
    5667              : {
    5668              :     DltUserHeader userheader;
    5669              :     DltUserControlMsgUnregisterApplication usercontext;
    5670              :     DltReturnValue ret = DLT_RETURN_OK;
    5671              : 
    5672          182 :     if (dlt_user.appID[0] == '\0')
    5673              :         return DLT_RETURN_ERROR;
    5674              : 
    5675              :     /* set userheader */
    5676          172 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION) < DLT_RETURN_OK)
    5677              :         return DLT_RETURN_ERROR;
    5678              : 
    5679              :     /* set usercontext */
    5680          172 :     dlt_set_id(usercontext.apid, dlt_user.appID); /* application id */
    5681          172 :     usercontext.pid = getpid();
    5682              : 
    5683          172 :     if (dlt_user.dlt_is_file)
    5684              :         return DLT_RETURN_OK;
    5685              : 
    5686          172 :     ret = dlt_user_log_out2(
    5687              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext),
    5688              :         sizeof(DltUserControlMsgUnregisterApplication));
    5689              : 
    5690              :     /* store message in ringbuffer, if an error has occured */
    5691          172 :     if (ret < DLT_RETURN_OK)
    5692            2 :         return dlt_user_log_out_error_handling(
    5693              :             &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication), NULL,
    5694              :             0);
    5695              : 
    5696              :     return DLT_RETURN_OK;
    5697              : }
    5698              : 
    5699           24 : DltReturnValue dlt_user_log_send_unregister_application_v2(void)
    5700              : {
    5701              :     DltUserHeader userheader;
    5702              :     DltUserControlMsgUnregisterApplicationV2 usercontext;
    5703              :     char apid_local[DLT_V2_ID_SIZE];
    5704           24 :     usercontext.apid = apid_local;
    5705              :     uint8_t* buffer;
    5706              :     DltReturnValue ret;
    5707              :     int usercontextSize;
    5708              : 
    5709           24 :     if (dlt_user.appID2len == 0)
    5710              :         return DLT_RETURN_ERROR;
    5711              : 
    5712              :     /* set userheader */
    5713           24 :     if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION) < DLT_RETURN_OK)
    5714              :         return DLT_RETURN_ERROR;
    5715              : 
    5716              :     /* set usercontext */
    5717           24 :     dlt_set_id_v2(usercontext.apid, dlt_user.appID2, dlt_user.appID2len); /* application id */
    5718           24 :     usercontext.apidlen = dlt_user.appID2len;
    5719           24 :     usercontext.pid = getpid();
    5720              : 
    5721           24 :     if (dlt_user.dlt_is_file)
    5722              :         return DLT_RETURN_OK;
    5723              : 
    5724           24 :     usercontextSize = (int)sizeof(uint8_t) + usercontext.apidlen + (int)sizeof(pid_t);
    5725           24 :     buffer = (uint8_t*)malloc((size_t)usercontextSize);
    5726           24 :     if (!buffer)
    5727              :         return DLT_RETURN_ERROR;
    5728              : 
    5729              :     memset(buffer, usercontext.apidlen, 1);
    5730           24 :     memcpy(buffer + 1, usercontext.apid, usercontext.apidlen);
    5731           24 :     memcpy((buffer + 1 + usercontext.apidlen), &(usercontext.pid), sizeof(pid_t));
    5732              : 
    5733           24 :     ret = dlt_user_log_out2(
    5734              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize);
    5735              : 
    5736              :     /* store message in ringbuffer, if an error has occured */
    5737           24 :     if (ret < DLT_RETURN_OK)
    5738           24 :         ret = dlt_user_log_out_error_handling(
    5739              :             &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize, NULL, 0);
    5740           24 :     free(buffer);
    5741           24 :     return ret;
    5742              : }
    5743              : 
    5744          205 : DltReturnValue dlt_user_log_send_register_context(DltContextData* log)
    5745              : {
    5746              :     DltUserHeader userheader;
    5747              :     DltUserControlMsgRegisterContext usercontext;
    5748              :     DltReturnValue ret = DLT_RETURN_ERROR;
    5749              : 
    5750          205 :     if (log == NULL)
    5751              :         return DLT_RETURN_WRONG_PARAMETER;
    5752              : 
    5753          205 :     if (log->handle == NULL)
    5754              :         return DLT_RETURN_ERROR;
    5755              : 
    5756          205 :     if (log->handle->contextID[0] == '\0')
    5757              :         return DLT_RETURN_ERROR;
    5758              : 
    5759              :     /* set userheader */
    5760          205 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT) < DLT_RETURN_OK)
    5761              :         return DLT_RETURN_ERROR;
    5762              : 
    5763              :     /* set usercontext */
    5764          205 :     dlt_set_id(usercontext.apid, dlt_user.appID);         /* application id */
    5765          205 :     dlt_set_id(usercontext.ctid, log->handle->contextID); /* context id */
    5766          205 :     usercontext.log_level_pos = log->handle->log_level_pos;
    5767          205 :     usercontext.pid = getpid();
    5768              : 
    5769          205 :     usercontext.log_level = (int8_t)log->log_level;
    5770          205 :     usercontext.trace_status = (int8_t)log->trace_status;
    5771              : 
    5772          205 :     if (log->context_description != NULL)
    5773          205 :         usercontext.description_length = (uint32_t)strlen(log->context_description);
    5774              :     else
    5775            0 :         usercontext.description_length = 0;
    5776              : 
    5777          205 :     if (dlt_user.dlt_is_file)
    5778              :         return DLT_RETURN_OK;
    5779              : 
    5780          205 :     if (dlt_user.appID[0] != '\0')
    5781          205 :         ret = dlt_user_log_out3(
    5782              :             dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext),
    5783          205 :             sizeof(DltUserControlMsgRegisterContext), log->context_description, usercontext.description_length);
    5784              : 
    5785              :     /* store message in ringbuffer, if an error has occured */
    5786          205 :     if ((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0'))
    5787            0 :         return dlt_user_log_out_error_handling(
    5788              :             &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),
    5789            0 :             log->context_description, usercontext.description_length);
    5790              : 
    5791              :     return DLT_RETURN_OK;
    5792              : }
    5793              : 
    5794           36 : DltReturnValue dlt_user_log_send_register_context_v2(DltContextData* log)
    5795              : {
    5796              :     DltUserHeader userheader;
    5797              :     DltUserControlMsgRegisterContextV2 usercontext;
    5798              :     DltReturnValue ret = DLT_RETURN_ERROR;
    5799              :     uint8_t* buffer;
    5800              :     int usercontextSize;
    5801              :     int offset = 0;
    5802              :     char apid_local[DLT_V2_ID_SIZE];
    5803              :     char ctid_local[DLT_V2_ID_SIZE];
    5804           36 :     usercontext.apid = apid_local;
    5805           36 :     usercontext.ctid = ctid_local;
    5806              : 
    5807           36 :     if (log == NULL)
    5808              :         return DLT_RETURN_WRONG_PARAMETER;
    5809              : 
    5810           36 :     if (log->handle == NULL)
    5811              :         return DLT_RETURN_ERROR;
    5812              : 
    5813           36 :     if (log->handle->contextID2 == NULL)
    5814              :         return DLT_RETURN_ERROR;
    5815              : 
    5816              :     /* set userheader */
    5817           36 :     if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT) < DLT_RETURN_OK)
    5818              :         return DLT_RETURN_ERROR;
    5819              :     /* set usercontext */
    5820           36 :     dlt_set_id_v2(usercontext.apid, dlt_user.appID2, dlt_user.appID2len); /* application id */
    5821           36 :     usercontext.apidlen = dlt_user.appID2len;
    5822           36 :     dlt_set_id_v2(usercontext.ctid, log->handle->contextID2, log->handle->contextID2len); /* context id */
    5823           36 :     usercontext.ctidlen = log->handle->contextID2len;
    5824           36 :     usercontext.log_level_pos = log->handle->log_level_pos;
    5825           36 :     usercontext.pid = getpid();
    5826              : 
    5827           36 :     usercontext.log_level = (int8_t)log->log_level;
    5828           36 :     usercontext.trace_status = (int8_t)log->trace_status;
    5829              : 
    5830           36 :     if (log->context_description != NULL)
    5831           36 :         usercontext.description_length = (uint32_t)strlen(log->context_description);
    5832              :     else
    5833            0 :         usercontext.description_length = 0;
    5834              : 
    5835           36 :     if (dlt_user.dlt_is_file)
    5836              :         return DLT_RETURN_OK;
    5837              : 
    5838           36 :     usercontextSize = (int)sizeof(uint8_t) + usercontext.apidlen + (int)sizeof(uint8_t) + usercontext.ctidlen + 10
    5839              :                       + (int)sizeof(pid_t);
    5840           36 :     buffer = (uint8_t*)malloc((size_t)usercontextSize);
    5841           36 :     if (!buffer)
    5842              :         return DLT_RETURN_ERROR;
    5843              : 
    5844              :     memset(buffer, usercontext.apidlen, 1);
    5845              :     offset = 1;
    5846           36 :     memcpy(buffer + offset, usercontext.apid, usercontext.apidlen);
    5847           36 :     offset = offset + usercontext.apidlen;
    5848           36 :     memset(buffer + offset, usercontext.ctidlen, 1);
    5849              :     offset = offset + 1;
    5850           36 :     memcpy(buffer + offset, usercontext.ctid, usercontext.ctidlen);
    5851           36 :     offset = offset + usercontext.ctidlen;
    5852           36 :     memcpy(buffer + offset, &(usercontext.log_level_pos), sizeof(int32_t));
    5853           36 :     offset = offset + 4;
    5854           36 :     memcpy(buffer + offset, &(usercontext.log_level), sizeof(int8_t));
    5855           36 :     offset = offset + 1;
    5856           36 :     memcpy(buffer + offset, &(usercontext.trace_status), sizeof(int8_t));
    5857           36 :     offset = offset + 1;
    5858           36 :     memcpy(buffer + offset, &(usercontext.pid), sizeof(pid_t));
    5859           36 :     offset = offset + (int)sizeof(pid_t);
    5860           36 :     memcpy(buffer + offset, &(usercontext.description_length), sizeof(uint32_t));
    5861              :     offset = offset + 4;
    5862              : 
    5863           36 :     if (dlt_user.appID2len != 0)
    5864           36 :         ret = dlt_user_log_out3(
    5865              :             dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize,
    5866           36 :             log->context_description, usercontext.description_length);
    5867              : 
    5868              :     /* store message in ringbuffer, if an error has occured */
    5869           36 :     if ((ret != DLT_RETURN_OK) || (dlt_user.appID2len == 0))
    5870           36 :         ret = dlt_user_log_out_error_handling(
    5871           36 :             &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize, log->context_description,
    5872           36 :             usercontext.description_length);
    5873              : 
    5874           36 :     free(buffer);
    5875           36 :     return ret;
    5876              : }
    5877              : 
    5878          204 : DltReturnValue dlt_user_log_send_unregister_context(DltContextData* log)
    5879              : {
    5880              :     DltUserHeader userheader;
    5881              :     DltUserControlMsgUnregisterContext usercontext;
    5882              :     DltReturnValue ret;
    5883              : 
    5884          204 :     if (log == NULL)
    5885              :         return DLT_RETURN_WRONG_PARAMETER;
    5886              : 
    5887          204 :     if (log->handle == NULL)
    5888              :         return DLT_RETURN_WRONG_PARAMETER;
    5889              : 
    5890          204 :     if (log->handle->contextID[0] == '\0')
    5891              :         return DLT_RETURN_ERROR;
    5892              : 
    5893              :     /* set userheader */
    5894          204 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT) < DLT_RETURN_OK)
    5895              :         return DLT_RETURN_ERROR;
    5896              : 
    5897              :     /* set usercontext */
    5898          204 :     dlt_set_id(usercontext.apid, dlt_user.appID);         /* application id */
    5899          204 :     dlt_set_id(usercontext.ctid, log->handle->contextID); /* context id */
    5900          204 :     usercontext.pid = getpid();
    5901              : 
    5902          204 :     if (dlt_user.dlt_is_file)
    5903              :         return DLT_RETURN_OK;
    5904              : 
    5905          204 :     ret = dlt_user_log_out2(
    5906              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext),
    5907              :         sizeof(DltUserControlMsgUnregisterContext));
    5908              : 
    5909              :     /* store message in ringbuffer, if an error has occured */
    5910          204 :     if (ret < DLT_RETURN_OK)
    5911           12 :         return dlt_user_log_out_error_handling(
    5912              :             &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext), NULL, 0);
    5913              : 
    5914              :     return DLT_RETURN_OK;
    5915              : }
    5916              : 
    5917           35 : DltReturnValue dlt_user_log_send_unregister_context_v2(DltContextData* log)
    5918              : {
    5919              :     DltUserHeader userheader;
    5920              :     DltUserControlMsgUnregisterContextV2 usercontext;
    5921              :     DltReturnValue ret;
    5922              :     uint8_t* buffer;
    5923              :     int usercontextSize;
    5924              :     int offset = 0;
    5925              :     char apid_local[DLT_V2_ID_SIZE];
    5926              :     char ctid_local[DLT_V2_ID_SIZE];
    5927           35 :     usercontext.apid = apid_local;
    5928           35 :     usercontext.ctid = ctid_local;
    5929              : 
    5930           35 :     if (log == NULL)
    5931              :         return DLT_RETURN_WRONG_PARAMETER;
    5932              : 
    5933           35 :     if (log->handle == NULL)
    5934              :         return DLT_RETURN_WRONG_PARAMETER;
    5935              : 
    5936           35 :     if (log->handle->contextID2 == NULL)
    5937              :         return DLT_RETURN_ERROR;
    5938              : 
    5939              :     /* set userheader */
    5940           35 :     if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT) < DLT_RETURN_OK)
    5941              :         return DLT_RETURN_ERROR;
    5942              : 
    5943              :     /* set usercontext */
    5944           35 :     dlt_set_id_v2(usercontext.apid, dlt_user.appID2, dlt_user.appID2len); /* application id */
    5945           35 :     usercontext.apidlen = dlt_user.appID2len;
    5946           35 :     dlt_set_id_v2(usercontext.ctid, log->handle->contextID2, log->handle->contextID2len); /* context id */
    5947           35 :     usercontext.ctidlen = log->handle->contextID2len;
    5948           35 :     usercontext.pid = getpid();
    5949              : 
    5950           35 :     if (dlt_user.dlt_is_file)
    5951              :         return DLT_RETURN_OK;
    5952              : 
    5953           35 :     usercontextSize =
    5954           35 :         (int)sizeof(uint8_t) + usercontext.apidlen + (int)sizeof(uint8_t) + usercontext.ctidlen + (int)sizeof(pid_t);
    5955           35 :     buffer = (uint8_t*)malloc((size_t)usercontextSize);
    5956           35 :     if (!buffer)
    5957              :         return DLT_RETURN_ERROR;
    5958              : 
    5959              :     memset(buffer, usercontext.apidlen, 1);
    5960              :     offset = 1;
    5961           35 :     memcpy(buffer + offset, usercontext.apid, usercontext.apidlen);
    5962           35 :     offset = offset + usercontext.apidlen;
    5963           35 :     memset(buffer + offset, usercontext.ctidlen, 1);
    5964              :     offset = offset + 1;
    5965           35 :     memcpy(buffer + offset, usercontext.ctid, usercontext.ctidlen);
    5966           35 :     offset = offset + usercontext.ctidlen;
    5967           35 :     memcpy(buffer + offset, &(usercontext.pid), sizeof(pid_t));
    5968              :     offset = offset + (int)sizeof(pid_t);
    5969              : 
    5970           35 :     ret = dlt_user_log_out2(
    5971              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize);
    5972              : 
    5973              :     /* store message in ringbuffer, if an error has occured */
    5974           35 :     if (ret < DLT_RETURN_OK)
    5975           35 :         ret = dlt_user_log_out_error_handling(
    5976              :             &(userheader), sizeof(DltUserHeader), buffer, (size_t)usercontextSize, NULL, 0);
    5977           35 :     free(buffer);
    5978           35 :     return DLT_RETURN_OK;
    5979              : }
    5980              : 
    5981            0 : DltReturnValue dlt_send_app_ll_ts_limit(const char* apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
    5982              : {
    5983              :     DltUserHeader userheader;
    5984              :     DltUserControlMsgAppLogLevelTraceStatus usercontext;
    5985              :     DltReturnValue ret;
    5986              : 
    5987            0 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    5988            0 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    5989            0 :         return DLT_RETURN_ERROR;
    5990              :     }
    5991              : 
    5992            0 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    5993            0 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    5994            0 :         return DLT_RETURN_ERROR;
    5995              :     }
    5996              : 
    5997            0 :     if ((apid == NULL) || (apid[0] == '\0'))
    5998              :         return DLT_RETURN_ERROR;
    5999              : 
    6000              :     /* set userheader */
    6001            0 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS) < DLT_RETURN_OK)
    6002              :         return DLT_RETURN_ERROR;
    6003              : 
    6004              :     /* set usercontext */
    6005            0 :     dlt_set_id(usercontext.apid, apid); /* application id */
    6006            0 :     usercontext.log_level = loglevel;
    6007            0 :     usercontext.trace_status = tracestatus;
    6008              : 
    6009            0 :     if (dlt_user.dlt_is_file)
    6010              :         return DLT_RETURN_OK;
    6011              : 
    6012            0 :     ret = dlt_user_log_out2(
    6013              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext),
    6014              :         sizeof(DltUserControlMsgAppLogLevelTraceStatus));
    6015              : 
    6016              :     /* store message in ringbuffer, if an error has occured */
    6017            0 :     if (ret < DLT_RETURN_OK)
    6018            0 :         return dlt_user_log_out_error_handling(
    6019              :             &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus), NULL,
    6020              :             0);
    6021              : 
    6022              :     return DLT_RETURN_OK;
    6023              : }
    6024              : 
    6025            0 : DltReturnValue dlt_send_app_ll_ts_limit_v2(const char* apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
    6026              : {
    6027              :     DltUserHeader userheader;
    6028              :     DltUserControlMsgAppLogLevelTraceStatusV2 usercontext;
    6029              :     DltReturnValue ret;
    6030              :     char apid_local[DLT_V2_ID_SIZE];
    6031            0 :     usercontext.apid = apid_local;
    6032              : 
    6033            0 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    6034            0 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    6035            0 :         return DLT_RETURN_ERROR;
    6036              :     }
    6037              : 
    6038            0 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    6039            0 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    6040            0 :         return DLT_RETURN_ERROR;
    6041              :     }
    6042              : 
    6043            0 :     if ((apid == NULL) || (*apid == '\0'))
    6044              :         return DLT_RETURN_ERROR;
    6045              : 
    6046              :     /* set userheader */
    6047            0 :     if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_APP_LL_TS) < DLT_RETURN_OK)
    6048              :         return DLT_RETURN_ERROR;
    6049              : 
    6050              :     /* set usercontext */
    6051            0 :     size_t apidlen_sz = strlen(apid);
    6052            0 :     if (apidlen_sz > UINT8_MAX) {
    6053            0 :         dlt_vlog(LOG_ERR, "apidlen too large");
    6054            0 :         return DLT_RETURN_ERROR;
    6055              :     }
    6056            0 :     usercontext.apidlen = (uint8_t)apidlen_sz;
    6057            0 :     dlt_set_id_v2(usercontext.apid, apid, usercontext.apidlen); /* application id */
    6058            0 :     usercontext.log_level = loglevel;
    6059            0 :     usercontext.trace_status = tracestatus;
    6060              : 
    6061            0 :     size_t buffersize = sizeof(uint8_t) + usercontext.apidlen + sizeof(uint8_t) + sizeof(uint8_t);
    6062              :     uint8_t buffer[DLT_ID_SIZE + 3];
    6063              :     size_t offset = 0;
    6064              :     memcpy(buffer + offset, &(usercontext.apidlen), sizeof(uint8_t));
    6065              :     offset += sizeof(uint8_t);
    6066            0 :     if (usercontext.apid != NULL && usercontext.apidlen > 0) {
    6067              :         memcpy(buffer + offset, usercontext.apid, usercontext.apidlen);
    6068              :     }
    6069            0 :     offset += usercontext.apidlen;
    6070            0 :     memcpy(buffer + offset, &(usercontext.log_level), sizeof(uint8_t));
    6071            0 :     offset += sizeof(uint8_t);
    6072            0 :     memcpy(buffer + offset, &(usercontext.trace_status), sizeof(uint8_t));
    6073              : 
    6074            0 :     if (dlt_user.dlt_is_file)
    6075              :         return DLT_RETURN_OK;
    6076              : 
    6077            0 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), buffer, (size_t)buffersize);
    6078              : 
    6079              :     /* store message in ringbuffer, if an error has occured */
    6080            0 :     if (ret < DLT_RETURN_OK)
    6081            0 :         return dlt_user_log_out_error_handling(
    6082              :             &(userheader), sizeof(DltUserHeader), buffer, (size_t)buffersize, NULL, 0);
    6083              : 
    6084              :     return DLT_RETURN_OK;
    6085              : }
    6086              : 
    6087            4 : DltReturnValue dlt_user_log_send_log_mode(DltUserLogMode mode, uint8_t version)
    6088              : {
    6089              :     DltUserHeader userheader;
    6090              :     DltUserControlMsgLogMode logmode;
    6091              :     DltReturnValue ret;
    6092              : 
    6093            4 :     if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) {
    6094            0 :         dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode);
    6095            0 :         return DLT_RETURN_WRONG_PARAMETER;
    6096              :     }
    6097              : 
    6098              :     /* set userheader */
    6099            4 :     if (version == DLTProtocolV1) {
    6100            4 :         if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE) < DLT_RETURN_OK)
    6101              :             return DLT_RETURN_ERROR;
    6102            0 :     } else if (version == DLTProtocolV2) {
    6103            0 :         if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_LOG_MODE) < DLT_RETURN_OK)
    6104              :             return DLT_RETURN_ERROR;
    6105              :     } else {
    6106              :         return DLT_RETURN_ERROR;
    6107              :     }
    6108              : 
    6109              :     /* set data */
    6110            4 :     logmode.log_mode = (int8_t)mode;
    6111              : 
    6112            4 :     if (dlt_user.dlt_is_file)
    6113              :         return DLT_RETURN_OK;
    6114              : 
    6115            4 :     ret = dlt_user_log_out2(
    6116              :         dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
    6117              : 
    6118              :     /* store message in ringbuffer, if an error has occured */
    6119            4 :     if (ret < DLT_RETURN_OK)
    6120            0 :         return dlt_user_log_out_error_handling(
    6121              :             &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode), NULL, 0);
    6122              : 
    6123              :     return DLT_RETURN_OK;
    6124              : }
    6125              : 
    6126            1 : DltReturnValue dlt_user_log_send_marker()
    6127              : {
    6128              :     DltUserHeader userheader;
    6129              :     DltReturnValue ret;
    6130              : 
    6131              :     /* set userheader */
    6132            1 :     if (dlt_user.appID[0] != '\0') {
    6133            1 :         if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_MARKER) < DLT_RETURN_OK)
    6134              :             return DLT_RETURN_ERROR;
    6135            0 :     } else if (dlt_user.appID2len != 0) {
    6136            0 :         if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_MARKER) < DLT_RETURN_OK)
    6137              :             return DLT_RETURN_ERROR;
    6138              :     } else {
    6139              :         return DLT_RETURN_ERROR;
    6140              :     }
    6141              : 
    6142            1 :     if (dlt_user.dlt_is_file)
    6143              :         return DLT_RETURN_OK;
    6144              : 
    6145              :     /* log to FIFO */
    6146            1 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0);
    6147              : 
    6148              :     /* store message in ringbuffer, if an error has occured */
    6149            1 :     if (ret < DLT_RETURN_OK)
    6150            0 :         return dlt_user_log_out_error_handling(&(userheader), sizeof(DltUserHeader), NULL, 0, NULL, 0);
    6151              : 
    6152              :     return DLT_RETURN_OK;
    6153              : }
    6154              : 
    6155            0 : DltReturnValue dlt_user_print_msg(DltMessage* msg, DltContextData* log)
    6156              : {
    6157              :     uint8_t* databuffer_tmp;
    6158              :     uint32_t datasize_tmp;
    6159              :     uint32_t databuffersize_tmp;
    6160              :     static char text[DLT_USER_TEXT_LENGTH];
    6161              : 
    6162            0 :     if ((msg == NULL) || (log == NULL))
    6163              :         return DLT_RETURN_WRONG_PARAMETER;
    6164              : 
    6165              :     /* Save variables before print */
    6166            0 :     databuffer_tmp = msg->databuffer;
    6167            0 :     datasize_tmp = (uint32_t)msg->datasize;
    6168            0 :     databuffersize_tmp = (uint32_t)msg->databuffersize;
    6169              : 
    6170              :     /* Act like a receiver, convert header back to host format */
    6171            0 :     msg->standardheader->len = (uint16_t)DLT_BETOH_16(msg->standardheader->len);
    6172            0 :     dlt_message_get_extraparameters(msg, 0);
    6173              : 
    6174            0 :     msg->databuffer = log->buffer;
    6175            0 :     msg->datasize = log->size;
    6176            0 :     msg->databuffersize = log->size;
    6177              : 
    6178              :     /* Print message as ASCII */
    6179            0 :     if (dlt_message_print_ascii(msg, text, DLT_USER_TEXT_LENGTH, 0) == DLT_RETURN_ERROR)
    6180              :         return DLT_RETURN_ERROR;
    6181              : 
    6182              :     /* Restore variables and set len to BE*/
    6183            0 :     msg->databuffer = databuffer_tmp;
    6184            0 :     msg->databuffersize = (int32_t)databuffersize_tmp;
    6185            0 :     msg->datasize = (int32_t)datasize_tmp;
    6186              : 
    6187            0 :     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
    6188              : 
    6189            0 :     return DLT_RETURN_OK;
    6190              : }
    6191              : 
    6192            0 : DltReturnValue dlt_user_print_msg_v2(DltMessageV2* msg, DltContextData* log)
    6193              : {
    6194              :     uint8_t* databuffer_tmp;
    6195              :     int32_t datasize_tmp;
    6196              :     int32_t databuffersize_tmp;
    6197              :     static char text[DLT_USER_TEXT_LENGTH];
    6198            0 :     if ((msg == NULL) || (log == NULL))
    6199              :         return DLT_RETURN_WRONG_PARAMETER;
    6200              : 
    6201              :     /* Save variables before print */
    6202            0 :     databuffer_tmp = msg->databuffer;
    6203            0 :     datasize_tmp = msg->datasize;
    6204            0 :     databuffersize_tmp = msg->databuffersize;
    6205              : 
    6206              :     /* Act like a receiver, convert header back to host format */
    6207            0 :     msg->baseheaderv2->len = DLT_BETOH_16(msg->baseheaderv2->len);
    6208              :     // dlt_message_get_storageparameters_v2(msg, 0);
    6209              :     // dlt_message_get_extraparameters_v2(msg, 0);
    6210              : 
    6211            0 :     msg->databuffer = log->buffer;
    6212            0 :     if (log->size < 0) {
    6213              :         return DLT_RETURN_ERROR;
    6214              :     }
    6215            0 :     msg->datasize = log->size;
    6216            0 :     msg->databuffersize = log->size;
    6217              : 
    6218              :     /* Print message as ASCII */
    6219            0 :     if (dlt_message_print_ascii_v2(msg, text, DLT_USER_TEXT_LENGTH, 0) == DLT_RETURN_ERROR)
    6220              :         return DLT_RETURN_ERROR;
    6221              : 
    6222              :     /* Restore variables and set len to BE*/
    6223            0 :     msg->databuffer = databuffer_tmp;
    6224            0 :     msg->databuffersize = databuffersize_tmp;
    6225            0 :     msg->datasize = datasize_tmp;
    6226              : 
    6227            0 :     msg->baseheaderv2->len = DLT_HTOBE_16(msg->baseheaderv2->len);
    6228            0 :     return DLT_RETURN_OK;
    6229              : }
    6230              : 
    6231              : int dlt_get_extendedheadersize_v2(DltUser dlt_user_param, int contextIDSize)
    6232              : {
    6233              :     int size = 0;
    6234              :     /* Each variable-length field is: 1 byte length + N bytes data (NO null terminator) */
    6235           21 :     size += (1 + ((int)dlt_user_param.ecuID2len)) * ((int)dlt_user_param.with_ecu_id);
    6236           21 :     size += (int)(sizeof(uint32_t)) * ((int)dlt_user_param.with_session_id);
    6237           21 :     size += (1 + ((int)dlt_user_param.appID2len) + 1 + (contextIDSize)) * ((int)dlt_user_param.with_app_and_context_id);
    6238           21 :     size += (1 + ((int)dlt_user_param.filenamelen) + (int)sizeof(dlt_user_param.linenumber))
    6239           21 :             * ((int)dlt_user_param.with_filename_and_line_number);
    6240           21 :     size += (1 + ((int)dlt_user_param.tagbuffersize)) * ((int)dlt_user_param.with_tags);
    6241           21 :     size += (int)(sizeof(dlt_user_param.prlv)) * ((int)dlt_user_param.with_privacy_level);
    6242              :     // To Update: 8 with segmentation data size depending on type of frame (8, 4 or 0)
    6243           21 :     size += ((int)(sizeof(uint8_t)) + (int)(sizeof(uint8_t)) + 8) * ((int)dlt_user_param.with_segmentation);
    6244              : 
    6245              :     return size;
    6246              : }
    6247              : 
    6248        21009 : DltReturnValue dlt_user_log_check_user_message(void)
    6249              : {
    6250              :     int offset = 0;
    6251              :     int leave_while = 0;
    6252              :     int ret = 0;
    6253              :     int version = 0;
    6254              : 
    6255              :     uint32_t i;
    6256              :     int fd;
    6257              :     struct pollfd nfd[1];
    6258              : 
    6259              :     DltUserHeader* userheader;
    6260              :     DltReceiver* receiver = &(dlt_user.receiver);
    6261              : 
    6262              :     DltUserControlMsgLogLevel* usercontextll;
    6263              :     DltUserControlMsgInjection* usercontextinj;
    6264              :     DltUserControlMsgLogState* userlogstate;
    6265              :     unsigned char* userbuffer;
    6266              : 
    6267              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    6268              :     DltUserControlMsgTraceSettingMsg* trace_load_settings_user_messages;
    6269              :     uint32_t trace_load_settings_user_messages_count = 0;
    6270              :     uint32_t trace_load_settings_user_message_bytes_required = 0;
    6271              :     unsigned long trace_load_settings_alloc_size = 0;
    6272              : #endif
    6273              : 
    6274              :     /* For delayed calling of injection callback, to avoid deadlock */
    6275              :     DltUserInjectionCallback delayed_injection_callback;
    6276              :     DltUserLogLevelChangedCallback delayed_log_level_changed_callback;
    6277              :     unsigned char* delayed_inject_buffer = 0;
    6278              :     uint32_t delayed_inject_data_length = 0;
    6279              : 
    6280              :     /* Ensure that callback is null before searching for it */
    6281              :     delayed_injection_callback.injection_callback = 0;
    6282              :     delayed_injection_callback.injection_callback_with_id = 0;
    6283              :     delayed_injection_callback.service_id = 0;
    6284        21009 :     delayed_log_level_changed_callback.log_level_changed_callback = 0;
    6285        21009 :     delayed_log_level_changed_callback.log_level_changed_callback_v2 = 0;
    6286              :     delayed_injection_callback.data = 0;
    6287              : 
    6288              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    6289              :     fd = dlt_user.dlt_log_handle;
    6290              : #else /* DLT_LIB_USE_FIFO_IPC */
    6291        21009 :     fd = dlt_user.dlt_user_handle;
    6292              : #endif
    6293        21009 :     nfd[0].events = POLLIN;
    6294        21009 :     nfd[0].fd = fd;
    6295              : 
    6296        21009 :     if (fd >= 0) {
    6297              :         ret = poll(nfd, 1, DLT_USER_RECEIVE_MDELAY);
    6298           19 :         if (ret) {
    6299           17 :             if (nfd[0].revents & (POLLHUP | POLLNVAL | POLLERR)) {
    6300            0 :                 dlt_user.dlt_log_handle = DLT_FD_INIT;
    6301            0 :                 return DLT_RETURN_ERROR;
    6302              :             }
    6303              : 
    6304           17 :             if (dlt_receiver_receive(receiver) <= 0)
    6305              :                 /* No new message available */
    6306              :                 return DLT_RETURN_OK;
    6307              : 
    6308              :             /* look through buffer as long as data is in there */
    6309              :             while (1) {
    6310          167 :                 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
    6311              :                     break;
    6312              : 
    6313              :                 /* resync if necessary */
    6314              :                 offset = 0;
    6315              : 
    6316              :                 do {
    6317          150 :                     userheader = (DltUserHeader*)(receiver->buf + offset);
    6318              : 
    6319              :                     /* Check for user header pattern */
    6320          150 :                     if (dlt_user_check_userheader(userheader))
    6321              :                         break;
    6322              : 
    6323            0 :                     offset++;
    6324              : 
    6325            0 :                 } while (((int32_t)(sizeof(DltUserHeader)) + offset) <= receiver->bytesRcvd);
    6326              : 
    6327              :                 /* Check for user header pattern */
    6328          150 :                 if ((dlt_user_check_userheader(userheader) < 0) || (dlt_user_check_userheader(userheader) == 0))
    6329              :                     break;
    6330              : 
    6331              :                 /* Set new start offset */
    6332          150 :                 if (offset > 0) {
    6333            0 :                     receiver->buf += offset;
    6334            0 :                     receiver->bytesRcvd -= offset;
    6335              :                 }
    6336              : 
    6337          150 :                 version = dlt_get_version_from_userheader(userheader);
    6338              : 
    6339          150 :                 switch (userheader->message) {
    6340           63 :                 case DLT_USER_MESSAGE_LOG_LEVEL: {
    6341           63 :                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel))) {
    6342              :                         leave_while = 1;
    6343              :                         break;
    6344              :                     }
    6345              : 
    6346           63 :                     usercontextll = (DltUserControlMsgLogLevel*)(receiver->buf + sizeof(DltUserHeader));
    6347              : 
    6348              :                     /* Update log level and trace status */
    6349              :                     if (usercontextll != NULL) {
    6350           63 :                         dlt_mutex_lock();
    6351              : 
    6352           63 :                         if ((usercontextll->log_level_pos >= 0)
    6353           63 :                             && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries)) {
    6354           63 :                             if (dlt_user.dlt_ll_ts) {
    6355           63 :                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level =
    6356           63 :                                     (int8_t)usercontextll->log_level;
    6357           63 :                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status =
    6358           63 :                                     (int8_t)usercontextll->trace_status;
    6359              : 
    6360           63 :                                 if (dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
    6361            1 :                                     *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) =
    6362              :                                         (int8_t)usercontextll->log_level;
    6363              : 
    6364           63 :                                 if (dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
    6365            1 :                                     *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) =
    6366            1 :                                         (int8_t)usercontextll->trace_status;
    6367              : 
    6368           63 :                                 if (version == DLTProtocolV1) {
    6369           63 :                                     delayed_log_level_changed_callback.log_level_changed_callback =
    6370           63 :                                         dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_changed_callback;
    6371              : 
    6372           63 :                                     dlt_set_id(
    6373              :                                         delayed_log_level_changed_callback.contextID,
    6374           63 :                                         dlt_user.dlt_ll_ts[usercontextll->log_level_pos].contextID);
    6375              : 
    6376           63 :                                     delayed_log_level_changed_callback.log_level = (int8_t)usercontextll->log_level;
    6377           63 :                                     delayed_log_level_changed_callback.trace_status =
    6378           63 :                                         (int8_t)usercontextll->trace_status;
    6379            0 :                                 } else if (version == DLTProtocolV2) {
    6380            0 :                                     delayed_log_level_changed_callback.log_level_changed_callback_v2 =
    6381            0 :                                         dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_changed_callback_v2;
    6382              : 
    6383            0 :                                     delayed_log_level_changed_callback.contextID2len =
    6384            0 :                                         dlt_user.dlt_ll_ts[usercontextll->log_level_pos].contextID2len;
    6385              : 
    6386            0 :                                     dlt_set_id_v2(
    6387              :                                         delayed_log_level_changed_callback.contextID2,
    6388            0 :                                         dlt_user.dlt_ll_ts[usercontextll->log_level_pos].contextID2,
    6389              :                                         dlt_user.dlt_ll_ts[usercontextll->log_level_pos].contextID2len);
    6390              : 
    6391            0 :                                     delayed_log_level_changed_callback.log_level = (int8_t)usercontextll->log_level;
    6392            0 :                                     delayed_log_level_changed_callback.trace_status =
    6393            0 :                                         (int8_t)usercontextll->trace_status;
    6394              :                                 }
    6395              :                             }
    6396              :                         }
    6397              : 
    6398           63 :                         dlt_mutex_unlock();
    6399              :                     }
    6400              : 
    6401              :                     /* call callback outside of semaphore */
    6402           63 :                     if (version == DLTProtocolV1) {
    6403           63 :                         if (delayed_log_level_changed_callback.log_level_changed_callback != 0)
    6404            0 :                             delayed_log_level_changed_callback.log_level_changed_callback(
    6405              :                                 delayed_log_level_changed_callback.contextID,
    6406            0 :                                 (uint8_t)delayed_log_level_changed_callback.log_level,
    6407            0 :                                 (uint8_t)delayed_log_level_changed_callback.trace_status);
    6408              : 
    6409              :                         /* keep not read data in buffer */
    6410           63 :                         if (dlt_receiver_remove(receiver, sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel))
    6411              :                             == DLT_RETURN_ERROR)
    6412              :                             return DLT_RETURN_ERROR;
    6413            0 :                     } else if (version == DLTProtocolV2) {
    6414            0 :                         if (delayed_log_level_changed_callback.log_level_changed_callback_v2 != 0)
    6415            0 :                             delayed_log_level_changed_callback.log_level_changed_callback_v2(
    6416              :                                 delayed_log_level_changed_callback.contextID2,
    6417            0 :                                 (uint8_t)delayed_log_level_changed_callback.log_level,
    6418            0 :                                 (uint8_t)delayed_log_level_changed_callback.trace_status);
    6419              : 
    6420              :                         /* keep not read data in buffer */
    6421            0 :                         if (dlt_receiver_remove(receiver, sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel))
    6422              :                             == DLT_RETURN_ERROR)
    6423              :                             return DLT_RETURN_ERROR;
    6424              :                     }
    6425              :                 } break;
    6426            0 :                 case DLT_USER_MESSAGE_INJECTION: {
    6427              :                     /* At least, user header, user context, and service id and data_length of injected message is
    6428              :                      * available */
    6429            0 :                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection))) {
    6430              :                         leave_while = 1;
    6431              :                         break;
    6432              :                     }
    6433              : 
    6434            0 :                     usercontextinj = (DltUserControlMsgInjection*)(receiver->buf + sizeof(DltUserHeader));
    6435            0 :                     userbuffer =
    6436              :                         (unsigned char*)(receiver->buf + sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection));
    6437              : 
    6438              :                     if (userbuffer != NULL) {
    6439            0 :                         if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection)
    6440            0 :                                                             + usercontextinj->data_length_inject)) {
    6441              :                             leave_while = 1;
    6442              :                             break;
    6443              :                         }
    6444              : 
    6445            0 :                         dlt_mutex_lock();
    6446              : 
    6447            0 :                         if ((usercontextinj->data_length_inject > 0) && (dlt_user.dlt_ll_ts))
    6448              :                             /* Check if injection callback is registered for this context */
    6449            0 :                             for (i = 0; i < dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks; i++)
    6450            0 :                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table)
    6451            0 :                                     && (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id
    6452            0 :                                         == usercontextinj->service_id)) {
    6453              :                                     /* Prepare delayed injection callback call */
    6454            0 :                                     if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos]
    6455              :                                             .injection_table[i]
    6456            0 :                                             .injection_callback
    6457              :                                         != NULL) {
    6458              :                                         delayed_injection_callback.injection_callback =
    6459              :                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos]
    6460              :                                                 .injection_table[i]
    6461              :                                                 .injection_callback;
    6462            0 :                                     } else if (
    6463              :                                         dlt_user.dlt_ll_ts[usercontextinj->log_level_pos]
    6464              :                                             .injection_table[i]
    6465            0 :                                             .injection_callback_with_id
    6466              :                                         != NULL) {
    6467              :                                         delayed_injection_callback.injection_callback_with_id =
    6468              :                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos]
    6469              :                                                 .injection_table[i]
    6470              :                                                 .injection_callback_with_id;
    6471              :                                         delayed_injection_callback.data =
    6472            0 :                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].data;
    6473              :                                     }
    6474              : 
    6475              :                                     delayed_injection_callback.service_id = usercontextinj->service_id;
    6476              :                                     delayed_inject_data_length = usercontextinj->data_length_inject;
    6477            0 :                                     delayed_inject_buffer = malloc(delayed_inject_data_length);
    6478              : 
    6479            0 :                                     if (delayed_inject_buffer != NULL) {
    6480              :                                         memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
    6481              :                                     } else {
    6482            0 :                                         dlt_mutex_unlock();
    6483            0 :                                         dlt_log(LOG_WARNING, "malloc failed!\n");
    6484            0 :                                         return DLT_RETURN_ERROR;
    6485              :                                     }
    6486              : 
    6487              :                                     break;
    6488              :                                 }
    6489              : 
    6490            0 :                         dlt_mutex_unlock();
    6491              : 
    6492              :                         /* Delayed injection callback call */
    6493            0 :                         if ((delayed_inject_buffer != NULL)
    6494            0 :                             && (delayed_injection_callback.injection_callback != NULL)) {
    6495            0 :                             delayed_injection_callback.injection_callback(
    6496              :                                 delayed_injection_callback.service_id, delayed_inject_buffer,
    6497              :                                 delayed_inject_data_length);
    6498            0 :                             delayed_injection_callback.injection_callback = NULL;
    6499              :                         } else if (
    6500              :                             (delayed_inject_buffer != NULL)
    6501            0 :                             && (delayed_injection_callback.injection_callback_with_id != NULL)) {
    6502            0 :                             delayed_injection_callback.injection_callback_with_id(
    6503              :                                 delayed_injection_callback.service_id, delayed_inject_buffer,
    6504              :                                 delayed_inject_data_length, delayed_injection_callback.data);
    6505              :                             delayed_injection_callback.injection_callback_with_id = NULL;
    6506              :                         }
    6507              : 
    6508            0 :                         free(delayed_inject_buffer);
    6509              :                         delayed_inject_buffer = NULL;
    6510              : 
    6511              :                         /* keep not read data in buffer */
    6512            0 :                         if (dlt_receiver_remove(
    6513              :                                 receiver, (int)(sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection)
    6514            0 :                                                 + usercontextinj->data_length_inject))
    6515              :                             != DLT_RETURN_OK)
    6516              :                             return DLT_RETURN_ERROR;
    6517              :                     }
    6518              :                 } break;
    6519           87 :                 case DLT_USER_MESSAGE_LOG_STATE: {
    6520              :                     /* At least, user header, user context, and service id and data_length of injected message is
    6521              :                      * available */
    6522           87 :                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogState))) {
    6523              :                         leave_while = 1;
    6524              :                         break;
    6525              :                     }
    6526              : 
    6527           87 :                     userlogstate = (DltUserControlMsgLogState*)(receiver->buf + sizeof(DltUserHeader));
    6528           87 :                     dlt_user.log_state = userlogstate->log_state;
    6529              : 
    6530              :                     /* keep not read data in buffer */
    6531           87 :                     if (dlt_receiver_remove(receiver, (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogState)))
    6532              :                         == DLT_RETURN_ERROR)
    6533              :                         return DLT_RETURN_ERROR;
    6534              :                 } break;
    6535              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    6536              :                 case DLT_USER_MESSAGE_TRACE_LOAD: {
    6537              :                     /* TODO: Need update for version 2 */
    6538              :                     /*
    6539              :                      * at least user header and message length is available
    6540              :                      */
    6541              :                     trace_load_settings_user_message_bytes_required =
    6542              :                         (int32_t)(sizeof(DltUserHeader) + sizeof(uint32_t));
    6543              :                     if (receiver->bytesRcvd < (int32_t)trace_load_settings_user_message_bytes_required) {
    6544              :                         // Not enough data to read the message length
    6545              :                         leave_while = 1;
    6546              :                         break;
    6547              :                     }
    6548              : 
    6549              :                     // Read trace settings count from buffer.
    6550              :                     trace_load_settings_user_messages_count = (uint32_t)(*(receiver->buf + sizeof(DltUserHeader)));
    6551              :                     trace_load_settings_user_message_bytes_required +=
    6552              :                         (uint32_t)trace_load_settings_user_messages_count
    6553              :                         * (uint32_t)sizeof(DltUserControlMsgTraceSettingMsg);
    6554              :                     if (receiver->bytesRcvd < (int32_t)trace_load_settings_user_message_bytes_required) {
    6555              :                         // Not enough data to read trace settings
    6556              :                         leave_while = 1;
    6557              :                         break;
    6558              :                     }
    6559              : 
    6560              :                     trace_load_settings_user_messages =
    6561              :                         (DltUserControlMsgTraceSettingMsg*)(receiver->buf + sizeof(DltUserHeader) + sizeof(uint32_t));
    6562              : 
    6563              :                     pthread_rwlock_wrlock(&trace_load_rw_lock);
    6564              : 
    6565              :                     // Remove the default created at startup
    6566              :                     if (trace_load_settings != NULL) {
    6567              :                         free(trace_load_settings);
    6568              :                         trace_load_settings_count = 0;
    6569              :                         trace_load_settings = NULL;
    6570              :                     }
    6571              : 
    6572              :                     trace_load_settings_alloc_size =
    6573              :                         sizeof(DltTraceLoadSettings) * trace_load_settings_user_messages_count;
    6574              :                     trace_load_settings = malloc(trace_load_settings_alloc_size);
    6575              :                     if (trace_load_settings == NULL) {
    6576              :                         pthread_rwlock_unlock(&trace_load_rw_lock);
    6577              :                         dlt_vlog(
    6578              :                             LOG_EMERG,
    6579              :                             "Unable to allocate memory for trace load settings, no logging will be possible\n");
    6580              :                     } else {
    6581              :                         memset(trace_load_settings, 0, trace_load_settings_alloc_size);
    6582              :                         for (i = 0; i < trace_load_settings_user_messages_count; i++) {
    6583              :                             memcpy(trace_load_settings[i].apid, dlt_user.appID, DLT_ID_SIZE);
    6584              :                             memcpy(trace_load_settings[i].ctid, trace_load_settings_user_messages[i].ctid, DLT_ID_SIZE);
    6585              :                             trace_load_settings[i].soft_limit = trace_load_settings_user_messages[i].soft_limit;
    6586              :                             trace_load_settings[i].hard_limit = trace_load_settings_user_messages[i].hard_limit;
    6587              :                         }
    6588              : 
    6589              :                         /* Publish the newly installed trace_load_settings (protected by rwlock)
    6590              :                          * and then update the per-context pointer while holding the DLT mutex to
    6591              :                          * avoid races with concurrent context registration/unregistration.
    6592              :                          */
    6593              :                         trace_load_settings_count = trace_load_settings_user_messages_count;
    6594              :                         pthread_rwlock_unlock(&trace_load_rw_lock);
    6595              : 
    6596              :                         dlt_mutex_lock();
    6597              :                         for (i = 0; i < dlt_user.dlt_ll_ts_num_entries; ++i) {
    6598              :                             dlt_ll_ts_type* ctx_entry = &dlt_user.dlt_ll_ts[i];
    6599              :                             ctx_entry->trace_load_settings = dlt_find_runtime_trace_load_settings(
    6600              :                                 trace_load_settings, trace_load_settings_count, dlt_user.appID, ctx_entry->contextID);
    6601              :                         }
    6602              :                         dlt_mutex_unlock();
    6603              : 
    6604              :                         char** messages = malloc(trace_load_settings_count * sizeof(char*));
    6605              :                         if (messages == NULL) {
    6606              :                             pthread_rwlock_unlock(&trace_load_rw_lock);
    6607              :                             dlt_vlog(LOG_ERR, "unable to allocate memory for trace load message buffer\n");
    6608              :                         } else {
    6609              :                             uint32_t msg_count = 0U;
    6610              :                             for (i = 0U; i < trace_load_settings_count; i++) {
    6611              :                                 messages[i] = malloc(255 * sizeof(char));
    6612              :                                 if (messages[i] == NULL) {
    6613              :                                     dlt_vlog(
    6614              :                                         LOG_ERR,
    6615              :                                         "unable to allocate memory for trace load message buffer, index: %u, skipping "
    6616              :                                         "remaining entries\n",
    6617              :                                         i);
    6618              :                                     break;
    6619              :                                 }
    6620              :                                 ++msg_count;
    6621              :                                 snprintf(
    6622              :                                     messages[i], 255,
    6623              :                                     "Received trace load settings: apid=%.4s%s%.4s, soft_limit=%u, hard_limit=%u\n",
    6624              :                                     trace_load_settings[i].apid,
    6625              :                                     trace_load_settings[i].ctid[0] == '\0' ? "" : ", ctid=",
    6626              :                                     trace_load_settings[i].ctid[0] == '\0' ? "" : trace_load_settings[i].ctid,
    6627              :                                     trace_load_settings[i].soft_limit, trace_load_settings[i].hard_limit);
    6628              :                             }
    6629              :                             /* Messages are emitted outside of both the rwlock and the DLT mutex */
    6630              :                             for (i = 0U; i < msg_count; i++) {
    6631              :                                 dlt_user_output_internal_msg(DLT_LOG_INFO, messages[i], NULL);
    6632              :                                 free(messages[i]);
    6633              :                             }
    6634              :                             free(messages);
    6635              :                         }
    6636              :                         /* continue outer flow, rwlock already unlocked */
    6637              :                     }
    6638              : 
    6639              :                     /* keep not read data in buffer */
    6640              :                     if (dlt_receiver_remove(receiver, (int)trace_load_settings_user_message_bytes_required)
    6641              :                         == DLT_RETURN_ERROR) {
    6642              :                         return DLT_RETURN_ERROR;
    6643              :                     }
    6644              :                 } break;
    6645              : #endif
    6646            0 :                 default: {
    6647            0 :                     dlt_log(LOG_WARNING, "Invalid user message type received!\n");
    6648              :                     /* Ignore result */
    6649            0 :                     if (dlt_receiver_remove(receiver, sizeof(DltUserHeader)) == -1)
    6650            0 :                         dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
    6651              :                     /* In next invocation of while loop, a resync will be triggered if additional data was received */
    6652              :                 } break;
    6653              :                 } /* switch() */
    6654              : 
    6655          150 :                 if (leave_while == 1) {
    6656              :                     leave_while = 0;
    6657              :                     break;
    6658              :                 }
    6659              :             } /* while buffer*/
    6660              : 
    6661           17 :             if (dlt_receiver_move_to_begin(receiver) == DLT_RETURN_ERROR)
    6662              :                 return DLT_RETURN_ERROR;
    6663              :         } /* while receive */
    6664              : 
    6665              :     } /* if */
    6666              : 
    6667              :     return DLT_RETURN_OK;
    6668              : }
    6669              : 
    6670         6197 : DltReturnValue dlt_user_log_resend_buffer(void)
    6671              : {
    6672              :     int num, count;
    6673              :     int size;
    6674              :     DltReturnValue ret;
    6675              : 
    6676         6197 :     dlt_mutex_lock();
    6677              : 
    6678         6197 :     if ((dlt_user.appID[0] == '\0') && (dlt_user.appID2len == 0)) {
    6679            5 :         dlt_mutex_unlock();
    6680            5 :         return 0;
    6681              :     }
    6682              : 
    6683              :     /* Send content of ringbuffer */
    6684         6192 :     count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    6685         6192 :     dlt_mutex_unlock();
    6686              : 
    6687         6192 :     if (dlt_user.appID[0] == '\0') {
    6688            1 :         for (num = 0; num < count; num++) {
    6689            0 :             dlt_mutex_lock();
    6690            0 :             size = dlt_buffer_copy(&(dlt_user.startup_buffer), dlt_user.resend_buffer, dlt_user.log_buf_len);
    6691              : 
    6692            0 :             if (size > 0) {
    6693            0 :                 DltUserHeader* userheader = (DltUserHeader*)(dlt_user.resend_buffer);
    6694              : 
    6695              :                 /* Add application id to the messages of needed*/
    6696            0 :                 if (dlt_user_check_userheader(userheader)) {
    6697            0 :                     switch (userheader->message) {
    6698            0 :                     case DLT_USER_MESSAGE_REGISTER_CONTEXT: {
    6699              :                         DltUserControlMsgRegisterContext* usercontext =
    6700            0 :                             (DltUserControlMsgRegisterContext*)(dlt_user.resend_buffer + sizeof(DltUserHeader));
    6701              : 
    6702            0 :                         if ((usercontext != 0) && (usercontext->apid[0] == '\0'))
    6703            0 :                             dlt_set_id(usercontext->apid, dlt_user.appID);
    6704              : 
    6705              :                         break;
    6706              :                     }
    6707            0 :                     case DLT_USER_MESSAGE_LOG: {
    6708              :                         DltExtendedHeader* extendedHeader =
    6709            0 :                             (DltExtendedHeader*)(dlt_user.resend_buffer + sizeof(DltUserHeader)
    6710              :                                                  + sizeof(DltStandardHeader) + sizeof(DltStandardHeaderExtra));
    6711              : 
    6712              :                         if (((extendedHeader) != 0)
    6713            0 :                             && (extendedHeader->apid[0] == '\0')) /* if application id is empty, add it */
    6714            0 :                             dlt_set_id(extendedHeader->apid, dlt_user.appID);
    6715              : 
    6716              :                         break;
    6717              :                     }
    6718              :                     default: {
    6719              :                         break;
    6720              :                     }
    6721              :                     }
    6722              :                 }
    6723              : 
    6724              : #ifdef DLT_SHM_ENABLE
    6725              :                 dlt_shm_push(
    6726              :                     &dlt_user.dlt_shm, dlt_user.resend_buffer + sizeof(DltUserHeader), size - sizeof(DltUserHeader), 0,
    6727              :                     0, 0, 0);
    6728              : 
    6729              :                 ret = dlt_user_log_out3(
    6730              :                     dlt_user.dlt_log_handle, dlt_user.resend_buffer, sizeof(DltUserHeader), 0, 0, 0, 0);
    6731              : #else  /* DLT_SHM_ENABLE */
    6732            0 :                 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer, (size_t)size, 0, 0, 0, 0);
    6733              : #endif /* DLT_SHM_ENABLE */
    6734              :                 /* in case of error, keep message in ringbuffer */
    6735            0 :                 if (ret == DLT_RETURN_OK) {
    6736            0 :                     dlt_buffer_remove(&(dlt_user.startup_buffer));
    6737              :                 } else {
    6738            0 :                     if (ret == DLT_RETURN_PIPE_ERROR) {
    6739              :                         /* handle not open or pipe error */
    6740            0 :                         close(dlt_user.dlt_log_handle);
    6741            0 :                         dlt_user.dlt_log_handle = -1;
    6742              :                     }
    6743              : 
    6744              :                     /* keep message in ringbuffer */
    6745            0 :                     dlt_mutex_unlock();
    6746            0 :                     return ret;
    6747              :                 }
    6748              :             }
    6749            0 :             dlt_mutex_unlock();
    6750              :         }
    6751         6191 :     } else if (dlt_user.appID2len != 0) {
    6752              :         /* Initialize resend buffer for version 2*/
    6753              :         DltHtyp2ContentType msgcontent;
    6754            0 :         if (dlt_user.verbose_mode == 1) {
    6755              :             msgcontent = DLT_VERBOSE_DATA_MSG;
    6756              :         } else {
    6757              :             msgcontent = DLT_NON_VERBOSE_DATA_MSG;
    6758              :         }
    6759              : 
    6760            0 :         for (num = 0; num < count; num++) {
    6761            0 :             dlt_mutex_lock();
    6762            0 :             size = dlt_buffer_copy(&(dlt_user.startup_buffer), dlt_user.resend_buffer, dlt_user.log_buf_len);
    6763              : 
    6764            0 :             if (size > 0) {
    6765            0 :                 DltUserHeader* userheader = (DltUserHeader*)(dlt_user.resend_buffer);
    6766              : 
    6767              :                 /* Add application id to the messages of needed*/
    6768            0 :                 if (dlt_user_check_userheader(userheader)) {
    6769            0 :                     switch (userheader->message) {
    6770            0 :                     case DLT_USER_MESSAGE_REGISTER_CONTEXT: {
    6771              :                         DltUserControlMsgRegisterContextV2 usercontextv2;
    6772              :                         char resend_apid[DLT_V2_ID_SIZE];
    6773              :                         usercontextv2.apid = resend_apid;
    6774            0 :                         usercontextv2.apidlen = dlt_user.appID2len;
    6775            0 :                         dlt_set_id_v2(usercontextv2.apid, dlt_user.appID2, dlt_user.appID2len);
    6776              : 
    6777            0 :                         memcpy(dlt_user.resend_buffer + sizeof(DltUserHeader), &(usercontextv2.apidlen), 1);
    6778            0 :                         if (usercontextv2.apid != NULL && usercontextv2.apidlen > 0) {
    6779            0 :                             memcpy(
    6780            0 :                                 dlt_user.resend_buffer + sizeof(DltUserHeader) + 1, usercontextv2.apid,
    6781              :                                 usercontextv2.apidlen);
    6782              :                         }
    6783              :                         break;
    6784              :                     }
    6785            0 :                     case DLT_USER_MESSAGE_LOG: {
    6786              :                         int offset = 0;
    6787              :                         DltExtendedHeaderV2 extendedheaderv2;
    6788              :                         char resend_apid2[DLT_V2_ID_SIZE];
    6789            0 :                         extendedheaderv2.apid = resend_apid2;
    6790            0 :                         extendedheaderv2.apidlen = dlt_user.appID2len;
    6791            0 :                         dlt_set_id_v2(extendedheaderv2.apid, dlt_user.appID2, dlt_user.appID2len);
    6792            0 :                         if (dlt_user.with_ecu_id) {
    6793            0 :                             offset = dlt_user.ecuID2len + 1;
    6794              :                         };
    6795              :                         memcpy(
    6796            0 :                             dlt_user.resend_buffer + sizeof(DltUserHeader) + BASE_HEADER_V2_FIXED_SIZE
    6797            0 :                                 + dlt_message_get_extraparameters_size_v2(msgcontent) + offset,
    6798              :                             &(extendedheaderv2.apidlen), 1);
    6799              : 
    6800            0 :                         if (extendedheaderv2.apid != NULL && extendedheaderv2.apidlen > 0) {
    6801            0 :                             memcpy(
    6802            0 :                                 dlt_user.resend_buffer + sizeof(DltUserHeader) + BASE_HEADER_V2_FIXED_SIZE
    6803            0 :                                     + dlt_message_get_extraparameters_size_v2(msgcontent) + offset + 1,
    6804              :                                 extendedheaderv2.apid, extendedheaderv2.apidlen);
    6805              :                         }
    6806              :                         break;
    6807              :                     }
    6808              :                     default: {
    6809              :                         break;
    6810              :                     }
    6811              :                     }
    6812              :                 }
    6813              : 
    6814              : #ifdef DLT_SHM_ENABLE
    6815              :                 dlt_shm_push(
    6816              :                     &dlt_user.dlt_shm, dlt_user.resend_buffer + sizeof(DltUserHeader), size - sizeof(DltUserHeader), 0,
    6817              :                     0, 0, 0);
    6818              : 
    6819              :                 ret = dlt_user_log_out3(
    6820              :                     dlt_user.dlt_log_handle, dlt_user.resend_buffer, sizeof(DltUserHeader), 0, 0, 0, 0);
    6821              : #else
    6822            0 :                 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer, (size_t)size, 0, 0, 0, 0);
    6823              : #endif
    6824              : 
    6825              :                 /* in case of error, keep message in ringbuffer */
    6826            0 :                 if (ret == DLT_RETURN_OK) {
    6827            0 :                     dlt_buffer_remove(&(dlt_user.startup_buffer));
    6828              :                 } else {
    6829            0 :                     if (ret == DLT_RETURN_PIPE_ERROR) {
    6830              :                         /* handle not open or pipe error */
    6831            0 :                         close(dlt_user.dlt_log_handle);
    6832            0 :                         dlt_user.dlt_log_handle = -1;
    6833              :                     }
    6834              : 
    6835              :                     /* keep message in ringbuffer */
    6836            0 :                     dlt_mutex_unlock();
    6837            0 :                     return ret;
    6838              :                 }
    6839              :             }
    6840              : 
    6841            0 :             dlt_mutex_unlock();
    6842              :         }
    6843              :     }
    6844              : 
    6845              :     return DLT_RETURN_OK;
    6846              : }
    6847              : 
    6848           19 : void dlt_user_log_reattach_to_daemon(void)
    6849              : {
    6850              :     uint32_t num;
    6851              :     DltContext handle;
    6852              :     DltContextData log_new;
    6853              : 
    6854           19 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    6855            0 :         return;
    6856              :     }
    6857              : 
    6858              : 
    6859           19 :     if (dlt_user.dlt_log_handle < 0) {
    6860            0 :         dlt_user.dlt_log_handle = DLT_FD_INIT;
    6861              : 
    6862              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
    6863              :         /* try to open connection to dlt daemon */
    6864              :         dlt_initialize_socket_connection();
    6865              : 
    6866              :         if (dlt_user.connection_state != DLT_USER_CONNECTED)
    6867              :             /* return if not connected */
    6868              :             return;
    6869              : 
    6870              : #elif defined DLT_LIB_USE_VSOCK_IPC
    6871              :         dlt_initialize_vsock_connection();
    6872              : 
    6873              :         if (dlt_user.connection_state != DLT_USER_CONNECTED)
    6874              :             return;
    6875              : 
    6876              : #else /* DLT_LIB_USE_FIFO_IPC */
    6877              :         /* try to open pipe to dlt daemon */
    6878              :         int fd = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK);
    6879              : 
    6880            0 :         if (fd < 0)
    6881              :             return;
    6882              : 
    6883            0 :         dlt_user.dlt_log_handle = fd;
    6884              : #endif
    6885              : 
    6886            0 :         if (dlt_user_log_init(&handle, &log_new) < DLT_RETURN_OK)
    6887              :             return;
    6888              : 
    6889              : #ifdef DLT_SHM_ENABLE
    6890              : 
    6891              :         /* init shared memory */
    6892              :         if (dlt_shm_init_client(&dlt_user.dlt_shm, dltShmName) < DLT_RETURN_OK)
    6893              :             dlt_vnlog(
    6894              :                 LOG_WARNING, DLT_USER_BUFFER_LENGTH,
    6895              :                 "Logging disabled,"
    6896              :                 " Shared memory %s cannot be created!\n",
    6897              :                 dltShmName);
    6898              : 
    6899              : #endif
    6900              : 
    6901            0 :         dlt_log(LOG_NOTICE, "Logging (re-)enabled!\n");
    6902              : 
    6903              :         /* Re-register application */
    6904            0 :         if (dlt_user.appID[0] != '\0') {
    6905            0 :             if (dlt_user_log_send_register_application() < DLT_RETURN_ERROR)
    6906              :                 return;
    6907            0 :         } else if (dlt_user.appID2len != 0) {
    6908            0 :             if (dlt_user_log_send_register_application_v2() < DLT_RETURN_ERROR)
    6909              :                 return;
    6910              :         }
    6911              : 
    6912            0 :         dlt_mutex_lock();
    6913              : 
    6914              :         /* Re-register all stored contexts */
    6915            0 :         for (num = 0; num < dlt_user.dlt_ll_ts_num_entries; num++)
    6916              :             /* Re-register stored context */
    6917            0 :             if ((dlt_user.appID[0] != '\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0] != '\0')) {
    6918            0 :                 dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
    6919            0 :                 handle.log_level_pos = (int32_t)num;
    6920            0 :                 log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
    6921            0 :                 dlt_mutex_unlock();
    6922            0 :                 log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
    6923            0 :                 log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
    6924            0 :                 if (dlt_user_log_send_register_context(&log_new) < DLT_RETURN_ERROR)
    6925              :                     return;
    6926            0 :                 dlt_mutex_lock();
    6927            0 :             } else if (
    6928            0 :                 (dlt_user.appID2len != 0) && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID2[0] != 0)) {
    6929            0 :                 handle.contextID2len = dlt_user.dlt_ll_ts[num].contextID2len;
    6930              :                 /* Ensure handle.contextID2 points to a valid buffer before copying */
    6931            0 :                 handle.contextID2 = dlt_user.dlt_ll_ts[num].contextID2;
    6932            0 :                 dlt_set_id_v2(handle.contextID2, dlt_user.dlt_ll_ts[num].contextID2, handle.contextID2len);
    6933            0 :                 handle.log_level_pos = (int32_t)num;
    6934            0 :                 log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
    6935            0 :                 dlt_mutex_unlock();
    6936            0 :                 log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
    6937            0 :                 log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
    6938            0 :                 if (dlt_user_log_send_register_context_v2(&log_new) < DLT_RETURN_ERROR)
    6939              :                     return;
    6940            0 :                 dlt_mutex_lock();
    6941              :             }
    6942              : 
    6943              : 
    6944            0 :         dlt_mutex_unlock();
    6945              :     }
    6946              : }
    6947              : 
    6948            0 : DltReturnValue dlt_user_log_send_overflow(void)
    6949              : {
    6950            0 :     DltUserHeader userheader = {0};
    6951            0 :     DltUserControlMsgBufferOverflow userpayload = {0};
    6952            0 :     DltUserControlMsgBufferOverflowV2 userpayload2 = {0};
    6953              : 
    6954            0 :     if (dlt_user.dlt_is_file)
    6955              :         return DLT_RETURN_OK;
    6956              : 
    6957            0 :     if (dlt_user.appID[0] != '\0') {
    6958              :         /* set userheader */
    6959            0 :         if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW) < DLT_RETURN_OK)
    6960              :             return DLT_RETURN_ERROR;
    6961              : 
    6962              :         /* set user message parameters */
    6963              :         userpayload2.overflow_counter = dlt_user.overflow_counter;
    6964            0 :         userpayload2.apidlen = dlt_user.appID2len;
    6965            0 :         dlt_set_id_v2(userpayload2.apid, dlt_user.appID2, dlt_user.appID2len);
    6966            0 :         return dlt_user_log_out2(
    6967              :             dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(userpayload),
    6968              :             sizeof(DltUserControlMsgBufferOverflow));
    6969            0 :     } else if (dlt_user.appID2len != 0) {
    6970              :         /* set userheader */
    6971            0 :         if (dlt_user_set_userheader_v2(&userheader, DLT_USER_MESSAGE_OVERFLOW) < DLT_RETURN_OK)
    6972              :             return DLT_RETURN_ERROR;
    6973              : 
    6974              :         /* set user message parameters */
    6975            0 :         userpayload2.overflow_counter = dlt_user.overflow_counter;
    6976            0 :         userpayload2.apidlen = dlt_user.appID2len;
    6977            0 :         dlt_set_id_v2(userpayload2.apid, dlt_user.appID2, dlt_user.appID2len);
    6978              : 
    6979            0 :         int buffersize = (int)sizeof(uint32_t) + (int)sizeof(uint8_t) + (int)userpayload2.apidlen;
    6980            0 :         uint8_t buffer[buffersize];
    6981              :         memcpy(buffer, &(userpayload2.overflow_counter), sizeof(uint32_t));
    6982            0 :         memcpy(buffer + sizeof(uint32_t), &(userpayload2.apidlen), sizeof(uint8_t));
    6983              :         if (userpayload2.apid != NULL && userpayload2.apidlen > 0) {
    6984              :             memcpy(buffer + sizeof(uint32_t) + sizeof(uint8_t), userpayload2.apid, userpayload2.apidlen);
    6985              :         }
    6986              : 
    6987            0 :         return dlt_user_log_out2(
    6988              :             dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), buffer, (size_t)buffersize);
    6989              :     } else {
    6990              :         return DLT_RETURN_ERROR;
    6991              :     }
    6992              : }
    6993              : 
    6994            0 : DltReturnValue dlt_user_check_buffer(int* total_size, int* used_size)
    6995              : {
    6996            0 :     if ((total_size == NULL) || (used_size == NULL))
    6997              :         return DLT_RETURN_WRONG_PARAMETER;
    6998              : 
    6999            0 :     dlt_mutex_lock();
    7000              : 
    7001              : #ifdef DLT_SHM_ENABLE
    7002              :     *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
    7003              :     *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
    7004              : #else
    7005            0 :     *total_size = (int)dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
    7006            0 :     *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
    7007              : #endif
    7008              : 
    7009            0 :     dlt_mutex_unlock();
    7010            0 :     return DLT_RETURN_OK; /* ok */
    7011              : }
    7012              : 
    7013              : #ifdef DLT_TEST_ENABLE
    7014              : void dlt_user_test_corrupt_user_header(int enable)
    7015              : {
    7016              :     dlt_user.corrupt_user_header = enable;
    7017              : }
    7018              : void dlt_user_test_corrupt_message_size(int enable, int16_t size)
    7019              : {
    7020              :     dlt_user.corrupt_message_size = enable;
    7021              :     dlt_user.corrupt_message_size_size = size;
    7022              : }
    7023              : #endif
    7024              : 
    7025              : 
    7026        21002 : int dlt_start_threads()
    7027              : {
    7028              :     struct timespec time_to_wait, single_wait;
    7029              :     struct timespec now;
    7030              :     int signal_status = 1;
    7031        21002 :     atomic_bool dlt_housekeeper_running = false;
    7032              : 
    7033              :     /*
    7034              :      * Configure the condition varibale to use CLOCK_MONOTONIC.
    7035              :      * This makes sure we're protected against changes in the system clock
    7036              :      */
    7037              :     pthread_condattr_t attr;
    7038        21002 :     pthread_condattr_init(&attr);
    7039              : #if !defined(__APPLE__)
    7040        21002 :     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    7041              : #endif
    7042        21002 :     pthread_cond_init(&dlt_housekeeper_running_cond, &attr);
    7043              : 
    7044        21002 :     if (pthread_create(
    7045              :             &(dlt_housekeeperthread_handle), 0, dlt_user_housekeeperthread_function, &dlt_housekeeper_running)
    7046              :         != 0) {
    7047            0 :         dlt_log(LOG_CRIT, "Can't create housekeeper thread!\n");
    7048            0 :         return -1;
    7049              :     }
    7050              : 
    7051        21002 :     clock_gettime(CLOCK_MONOTONIC, &now);
    7052              :     /* wait at most 10s */
    7053        21002 :     time_to_wait.tv_sec = now.tv_sec + 10;
    7054              :     time_to_wait.tv_nsec = now.tv_nsec;
    7055              : 
    7056              :     /*
    7057              :      * wait until the house keeper is up and running
    7058              :      * Even though the condition variable and the while are
    7059              :      * using the same time out the while loop is not a no op.
    7060              :      * This is due to the fact that the pthread_cond_timedwait
    7061              :      * can be woken before time is up and dlt_housekeeper_running is not true yet.
    7062              :      * (spurious wakeup)
    7063              :      * To protect against this, a while loop with a timeout is added
    7064              :      * */
    7065              : 
    7066              :     // pthread_cond_timedwait has to be called on a locked mutex
    7067        21002 :     pthread_mutex_lock(&dlt_housekeeper_running_mutex);
    7068              : 
    7069        21002 :     while (!dlt_housekeeper_running && now.tv_sec <= time_to_wait.tv_sec) {
    7070              :         /*
    7071              :          * wait 500ms at a time
    7072              :          * this makes sure we don't block too long
    7073              :          * even if we missed the signal
    7074              :          */
    7075        20975 :         clock_gettime(CLOCK_MONOTONIC, &now);
    7076        20975 :         if (now.tv_nsec >= 500000000) {
    7077        10592 :             single_wait.tv_sec = now.tv_sec + 1;
    7078        10592 :             single_wait.tv_nsec = now.tv_nsec - 500000000;
    7079              :         } else {
    7080        10383 :             single_wait.tv_sec = now.tv_sec;
    7081        10383 :             single_wait.tv_nsec = now.tv_nsec + 500000000;
    7082              :         }
    7083              : 
    7084              :         signal_status =
    7085        20975 :             pthread_cond_timedwait(&dlt_housekeeper_running_cond, &dlt_housekeeper_running_mutex, &single_wait);
    7086              : 
    7087              :         /* otherwise it might be a spurious wakeup, try again until the time is over */
    7088        20975 :         if (signal_status == 0) {
    7089              :             break;
    7090              :         }
    7091              :     }
    7092              : 
    7093        21002 :     pthread_mutex_unlock(&dlt_housekeeper_running_mutex);
    7094              : 
    7095        21002 :     if (signal_status != 0 && !dlt_housekeeper_running) {
    7096            0 :         dlt_log(LOG_CRIT, "Failed to wait for house keeper thread!\n");
    7097            0 :         dlt_stop_threads();
    7098            0 :         return -1;
    7099              :     }
    7100              : 
    7101              : #ifdef DLT_NETWORK_TRACE_ENABLE
    7102              :     /* Start the segmented thread */
    7103        21002 :     if (pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL, dlt_user_trace_network_segmented_thread, NULL)) {
    7104            0 :         dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
    7105            0 :         return -1;
    7106              :     }
    7107              : #endif
    7108              :     return 0;
    7109              : }
    7110              : 
    7111        21002 : void dlt_stop_threads()
    7112              : {
    7113              :     int dlt_housekeeperthread_result = 0;
    7114              :     int joined = 0;
    7115              : 
    7116        21002 :     if (dlt_housekeeperthread_handle) {
    7117              :         /* do not ignore return value */
    7118              : #ifndef __ANDROID_API__
    7119        21002 :         dlt_housekeeperthread_result = pthread_cancel(dlt_housekeeperthread_handle);
    7120              : #else
    7121              : 
    7122              : #ifdef DLT_NETWORK_TRACE_ENABLE
    7123              :         dlt_lock_mutex(&mq_mutex);
    7124              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    7125              :         dlt_housekeeperthread_result = pthread_kill(dlt_housekeeperthread_handle, SIGUSR1);
    7126              :         dlt_user_cleanup_handler(NULL);
    7127              : #endif
    7128              : 
    7129              : 
    7130        21002 :         if (dlt_housekeeperthread_result != 0)
    7131            0 :             dlt_vlog(
    7132              :                 LOG_ERR, "ERROR %s(dlt_housekeeperthread_handle): %s\n",
    7133              : #ifndef __ANDROID_API__
    7134              :                 "pthread_cancel",
    7135              : #else
    7136              :                 "pthread_kill",
    7137              : #endif
    7138              :                 strerror(dlt_housekeeperthread_result));
    7139              :     }
    7140              : 
    7141              : #ifdef DLT_NETWORK_TRACE_ENABLE
    7142              :     int dlt_segmented_nwt_result = 0;
    7143              : 
    7144        21002 :     if (dlt_user.dlt_segmented_nwt_handle) {
    7145        21002 :         dlt_lock_mutex(&mq_mutex);
    7146        21002 :         pthread_cond_signal(&mq_init_condition);
    7147        21002 :         dlt_unlock_mutex(&mq_mutex);
    7148              : 
    7149        21002 :         dlt_segmented_nwt_result = pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
    7150              : 
    7151        21002 :         if (dlt_segmented_nwt_result != 0)
    7152            0 :             dlt_vlog(
    7153              :                 LOG_ERR, "ERROR pthread_cancel(dlt_user.dlt_segmented_nwt_handle): %s\n",
    7154              :                 strerror(dlt_segmented_nwt_result));
    7155              :     }
    7156              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    7157              :     /* make sure that the threads really finished working */
    7158        21002 :     if ((dlt_housekeeperthread_result == 0) && dlt_housekeeperthread_handle) {
    7159        21002 :         joined = pthread_join(dlt_housekeeperthread_handle, NULL);
    7160              : 
    7161        21002 :         if (joined != 0)
    7162            0 :             dlt_vlog(LOG_ERR, "ERROR pthread_join(dlt_housekeeperthread_handle, NULL): %s\n", strerror(joined));
    7163              : 
    7164        21002 :         dlt_housekeeperthread_handle = 0; /* set to invalid */
    7165              :     }
    7166              : 
    7167              : #ifdef DLT_NETWORK_TRACE_ENABLE
    7168        21002 :     if ((dlt_segmented_nwt_result == 0) && dlt_user.dlt_segmented_nwt_handle) {
    7169        21002 :         joined = pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL);
    7170              : 
    7171        21002 :         if (joined != 0)
    7172            0 :             dlt_vlog(LOG_ERR, "ERROR pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL): %s\n", strerror(joined));
    7173              : 
    7174        21002 :         dlt_user.dlt_segmented_nwt_handle = 0; /* set to invalid */
    7175              :     }
    7176              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    7177        21002 : }
    7178              : 
    7179            0 : static void dlt_fork_child_fork_handler()
    7180              : {
    7181            0 :     g_dlt_is_child = 1;
    7182            0 :     dlt_user_init_state = INIT_UNITIALIZED;
    7183            0 :     dlt_user.dlt_log_handle = -1;
    7184            0 :     dlt_user.local_pid = -1;
    7185              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    7186              :     pthread_rwlock_unlock(&trace_load_rw_lock);
    7187              : #endif
    7188            0 : }
    7189              : 
    7190              : 
    7191              : #if defined(DLT_TRACE_LOAD_CTRL_ENABLE)
    7192              : static DltReturnValue dlt_user_output_internal_msg(
    7193              :     const DltLogLevelType loglevel, const char* const text, void* const params)
    7194              : {
    7195              :     (void)params;  // parameter is not needed
    7196              :     static DltContext handle;
    7197              :     DltContextData log;
    7198              :     int ret;
    7199              :     int sent_size = 0;
    7200              : 
    7201              :     if (!handle.contextID[0]) {
    7202              :         // Register Special Context ID for output DLT library internal message
    7203              :         ret = dlt_register_context(&handle, DLT_TRACE_LOAD_CONTEXT_ID, "DLT user library internal context");
    7204              :         if (ret < DLT_RETURN_OK) {
    7205              :             return ret;
    7206              :         }
    7207              :     }
    7208              : 
    7209              :     if (dlt_user.verbose_mode == 0) {
    7210              :         return DLT_RETURN_ERROR;
    7211              :     }
    7212              : 
    7213              :     if (loglevel < DLT_USER_LOG_LEVEL_NOT_SET || loglevel >= DLT_LOG_MAX) {
    7214              :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    7215              :         return DLT_RETURN_WRONG_PARAMETER;
    7216              :     }
    7217              : 
    7218              :     if (text == NULL) {
    7219              :         return DLT_RETURN_WRONG_PARAMETER;
    7220              :     }
    7221              : 
    7222              :     ret = dlt_user_log_write_start(&handle, &log, loglevel);
    7223              : 
    7224              :     // Ok means below threshold
    7225              :     // see src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp::sloggerinfo_callback for reference
    7226              :     if (ret == DLT_RETURN_OK) {
    7227              :         return ret;
    7228              :     }
    7229              : 
    7230              :     if (ret != DLT_RETURN_TRUE) {
    7231              :         dlt_vlog(LOG_ERR, "Loglevel %d is disabled", loglevel);
    7232              :     }
    7233              : 
    7234              : 
    7235              :     if (log.buffer == NULL) {
    7236              :         return DLT_RETURN_LOGGING_DISABLED;
    7237              :     }
    7238              : 
    7239              :     ret = dlt_user_log_write_string(&log, text);
    7240              :     if (ret < DLT_RETURN_OK) {
    7241              :         return ret;
    7242              :     }
    7243              : 
    7244              :     ret = dlt_user_log_send_log(&log, DLT_TYPE_LOG, &sent_size);
    7245              : 
    7246              :     /* Return number of bytes if message was successfully sent */
    7247              :     return (ret == DLT_RETURN_OK) ? sent_size : ret;
    7248              : }
    7249              : #endif
    7250              : 
    7251         1462 : DltReturnValue dlt_user_log_out_error_handling(
    7252              :     void* ptr1, size_t len1, void* ptr2, size_t len2, void* ptr3, size_t len3)
    7253              : {
    7254              :     DltReturnValue ret = DLT_RETURN_ERROR;
    7255         1462 :     size_t msg_size = len1 + len2 + len3;
    7256              : 
    7257              :     /* Original mutex-protected buffer implementation */
    7258         1462 :     dlt_mutex_lock();
    7259         1462 :     ret = dlt_buffer_check_size(&(dlt_user.startup_buffer), (int)msg_size);
    7260         1462 :     dlt_mutex_unlock();
    7261              : 
    7262         1462 :     dlt_mutex_lock();
    7263              : 
    7264         1462 :     if (dlt_buffer_push3(
    7265              :             &(dlt_user.startup_buffer), ptr1, (unsigned int)len1, ptr2, (unsigned int)len2, ptr3, (unsigned int)len3)
    7266              :         == DLT_RETURN_ERROR) {
    7267            0 :         if (dlt_user.overflow_counter == 0)
    7268            0 :             dlt_log(LOG_WARNING, "Buffer full! Messages will be discarded.\n");
    7269              : 
    7270              :         ret = DLT_RETURN_BUFFER_FULL;
    7271              :     }
    7272              : 
    7273         1462 :     dlt_mutex_unlock();
    7274         1462 :     return ret;
    7275              : }
    7276              : 
    7277         6098 : DltReturnValue dlt_user_is_logLevel_enabled(DltContext* handle, DltLogLevelType loglevel)
    7278              : {
    7279         6098 :     if ((loglevel < DLT_LOG_DEFAULT) || (loglevel >= DLT_LOG_MAX)) {
    7280              :         return DLT_RETURN_WRONG_PARAMETER;
    7281              :     }
    7282              : 
    7283         6094 :     dlt_mutex_lock();
    7284         6094 :     if ((handle == NULL) || (handle->log_level_ptr == NULL)) {
    7285           10 :         dlt_mutex_unlock();
    7286           10 :         return DLT_RETURN_WRONG_PARAMETER;
    7287              :     }
    7288              : 
    7289         6084 :     if ((loglevel <= (DltLogLevelType)(*(handle->log_level_ptr))) && (loglevel != DLT_LOG_OFF)) {
    7290         6030 :         dlt_mutex_unlock();
    7291         6030 :         return DLT_RETURN_TRUE;
    7292              :     }
    7293              : 
    7294           54 :     dlt_mutex_unlock();
    7295           54 :     return DLT_RETURN_LOGGING_DISABLED;
    7296              : }
        

Generated by: LCOV version 2.0-1