LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 58.0 % 1748 1014
Test Date: 2025-09-09 04:46:32 Functions: 80.4 % 138 111

            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 <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
      31              : 
      32              : #if !defined (__WIN32__)
      33              : #   include <syslog.h> /* for LOG_... */
      34              : #   include <semaphore.h>
      35              : #   include <pthread.h> /* POSIX Threads */
      36              : #endif
      37              : 
      38              : #include <sys/time.h>
      39              : #include <math.h>
      40              : 
      41              : #include <sys/stat.h>
      42              : #include <fcntl.h>
      43              : #include <errno.h>
      44              : 
      45              : #include <sys/uio.h> /* writev() */
      46              : #include <poll.h>
      47              : 
      48              : #include <limits.h>
      49              : #ifdef linux
      50              : #   include <sys/prctl.h> /* for PR_SET_NAME */
      51              : #endif
      52              : 
      53              : #include <sys/types.h> /* needed for getpid() */
      54              : #include <unistd.h>
      55              : 
      56              : #include <stdbool.h>
      57              : 
      58              : #include <stdatomic.h>
      59              : 
      60              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
      61              : #   include <sys/socket.h>
      62              : #endif
      63              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
      64              : #   include <sys/un.h>
      65              : #endif
      66              : #ifdef DLT_LIB_USE_VSOCK_IPC
      67              : #   ifdef linux
      68              : #       include <linux/vm_sockets.h>
      69              : #   endif
      70              : #   ifdef __QNX__
      71              : #       include <vm_sockets.h>
      72              : #   endif
      73              : #endif
      74              : 
      75              : #include "dlt_user.h"
      76              : #include "dlt_common.h"
      77              : #include "dlt_log.h"
      78              : #include "dlt_user_shared.h"
      79              : #include "dlt_user_shared_cfg.h"
      80              : #include "dlt_user_cfg.h"
      81              : 
      82              : #ifdef DLT_FATAL_LOG_RESET_ENABLE
      83              : #   define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL) \
      84              :     do {                                   \
      85              :         if (LOGLEVEL == DLT_LOG_FATAL) {   \
      86              :             int *p = NULL;                 \
      87              :             *p = 0;                        \
      88              :         }                                  \
      89              :     } while (false)
      90              : #else /* DLT_FATAL_LOG_RESET_ENABLE */
      91              : #   define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL)
      92              : #endif /* DLT_FATAL_LOG_RESET_ENABLE */
      93              : 
      94              : enum InitState {
      95              :     INIT_UNITIALIZED,
      96              :     INIT_IN_PROGRESS,
      97              :     INIT_ERROR,
      98              :     INIT_DONE
      99              : };
     100              : 
     101              : static DltUser dlt_user;
     102              : static _Atomic enum InitState dlt_user_init_state = INIT_UNITIALIZED;
     103              : #define DLT_USER_INITIALIZED (dlt_user_init_state == INIT_DONE)
     104              : #define DLT_USER_INIT_ERROR (dlt_user_init_state == INIT_ERROR)
     105              : #define DLT_USER_INITIALIZED_NOT_FREEING (DLT_USER_INITIALIZED && (dlt_user_freeing == 0))
     106              : 
     107              : static _Atomic int dlt_user_freeing = 0;
     108              : static bool dlt_user_file_reach_max = false;
     109              : 
     110              : #ifdef DLT_LIB_USE_FIFO_IPC
     111              : static char dlt_user_dir[DLT_PATH_MAX];
     112              : static char dlt_daemon_fifo[DLT_PATH_MAX];
     113              : #endif
     114              : 
     115              : static pthread_mutex_t dlt_mutex;
     116              : static pthread_mutexattr_t dlt_mutex_attr;
     117              : static pthread_t dlt_housekeeperthread_handle;
     118              : 
     119              : /* Sync housekeeper thread start */
     120              : pthread_mutex_t dlt_housekeeper_running_mutex = PTHREAD_MUTEX_INITIALIZER;
     121              : pthread_cond_t dlt_housekeeper_running_cond;
     122              : 
     123              : /* calling dlt_user_atexit_handler() second time fails with error message */
     124              : static int atexit_registered = 0;
     125              : 
     126              : /* used to disallow DLT usage in fork() child */
     127              : static int g_dlt_is_child = 0;
     128              : /* String truncate message */
     129              : static const char STR_TRUNCATED_MESSAGE[] = "... <<Message truncated, too long>>";
     130              : 
     131              : /* Enum for type of string */
     132              : enum StringType
     133              : {
     134              :     ASCII_STRING = 0,
     135              :     UTF8_STRING = 1
     136              : };
     137              : 
     138              : /* Data type holding "Variable Info" (VARI) properties
     139              :  * Some of the supported data types (eg. bool, string, raw) have only "name", but not "unit".
     140              :  */
     141              : typedef struct VarInfo
     142              : {
     143              :     const char *name;  // the "name" attribute (can be NULL)
     144              :     const char *unit;  // the "unit" attribute (can be NULL)
     145              :     bool with_unit;    // true if the "unit" field is to be considered
     146              : } VarInfo;
     147              : 
     148              : #define DLT_UNUSED(x) (void)(x)
     149              : 
     150              : /* Network trace */
     151              : #ifdef DLT_NETWORK_TRACE_ENABLE
     152              : #define DLT_USER_SEGMENTED_THREAD (1<<2)
     153              : 
     154              : /* Segmented Network Trace */
     155              : #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
     156              : #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
     157              : #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
     158              : 
     159              : /* Mutex to wait on while message queue is not initialized */
     160              : pthread_mutex_t mq_mutex = PTHREAD_MUTEX_INITIALIZER;
     161              : pthread_cond_t mq_init_condition;
     162              : #endif /* DLT_NETWORK_TRACE_ENABLE */
     163              : 
     164        42532 : void dlt_lock_mutex(pthread_mutex_t *mutex)
     165              : {
     166        42532 :     int32_t lock_mutex_result = pthread_mutex_lock(mutex);
     167              : 
     168        42532 :     if (lock_mutex_result != 0)
     169            0 :         dlt_vlog(LOG_ERR,
     170              :                  "Mutex lock failed unexpected pid=%i with result %i!\n",
     171              :                  getpid(), lock_mutex_result);
     172        42532 : }
     173              : 
     174        63798 : void dlt_unlock_mutex(pthread_mutex_t *mutex)
     175              : {
     176        63798 :     pthread_mutex_unlock(mutex);
     177        63798 : }
     178              : 
     179              : /* Structure to pass data to segmented thread */
     180              : typedef struct
     181              : {
     182              :     DltContext *handle;
     183              :     uint32_t id;
     184              :     DltNetworkTraceType nw_trace_type;
     185              :     uint32_t header_len;
     186              :     void *header;
     187              :     uint32_t payload_len;
     188              :     void *payload;
     189              : } s_segmented_data;
     190              : 
     191              : /* Function prototypes for internally used functions */
     192              : static void dlt_user_housekeeperthread_function(void *ptr);
     193              : static void dlt_user_atexit_handler(void);
     194              : static DltReturnValue dlt_user_log_init(DltContext *handle, DltContextData *log);
     195              : static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype, int *sent_size);
     196              : static DltReturnValue dlt_user_log_send_register_application(void);
     197              : static DltReturnValue dlt_user_log_send_unregister_application(void);
     198              : static DltReturnValue dlt_user_log_send_register_context(DltContextData *log);
     199              : static DltReturnValue dlt_user_log_send_unregister_context(DltContextData *log);
     200              : static DltReturnValue dlt_send_app_ll_ts_limit(const char *apid,
     201              :                                                DltLogLevelType loglevel,
     202              :                                                DltTraceStatusType tracestatus);
     203              : static DltReturnValue dlt_user_log_send_log_mode(DltUserLogMode mode);
     204              : static DltReturnValue dlt_user_log_send_marker();
     205              : static DltReturnValue dlt_user_print_msg(DltMessage *msg, DltContextData *log);
     206              : static DltReturnValue dlt_user_log_check_user_message(void);
     207              : static void dlt_user_log_reattach_to_daemon(void);
     208              : static DltReturnValue dlt_user_log_send_overflow(void);
     209              : static DltReturnValue dlt_user_log_out_error_handling(void *ptr1,
     210              :                                                       size_t len1,
     211              :                                                       void *ptr2,
     212              :                                                       size_t len2,
     213              :                                                       void *ptr3,
     214              :                                                       size_t len3);
     215              : static void dlt_user_cleanup_handler(void *arg);
     216              : static int dlt_start_threads();
     217              : static void dlt_stop_threads();
     218              : static void dlt_fork_child_fork_handler();
     219              : #ifdef DLT_NETWORK_TRACE_ENABLE
     220              : static void dlt_user_trace_network_segmented_thread(void *unused);
     221              : static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
     222              : #endif
     223              : 
     224              : static DltReturnValue dlt_user_log_write_string_utils_attr(DltContextData *log, const char *text, const enum StringType type, const char *name, bool with_var_info);
     225              : static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, size_t length, const enum StringType type, const char *name, bool with_var_info);
     226              : 
     227              : 
     228              : static DltReturnValue dlt_unregister_app_util(bool force_sending_messages);
     229              : 
     230              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     231              : /* For trace load control feature */
     232              : static DltReturnValue dlt_user_output_internal_msg(DltLogLevelType loglevel, const char *text, void* params);
     233              : DltTraceLoadSettings* trace_load_settings = NULL;
     234              : uint32_t trace_load_settings_count = 0;
     235              : pthread_rwlock_t trace_load_rw_lock = PTHREAD_RWLOCK_INITIALIZER;
     236              : #endif
     237              : 
     238            7 : DltReturnValue dlt_user_check_library_version(const char *user_major_version, const char *user_minor_version)
     239              : {
     240              :     char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
     241              :     char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
     242              : 
     243            7 :     dlt_get_major_version(lib_major_version, DLT_USER_MAX_LIB_VERSION_LENGTH);
     244            7 :     dlt_get_minor_version(lib_minor_version, DLT_USER_MAX_LIB_VERSION_LENGTH);
     245              : 
     246            7 :     if ((strcmp(lib_major_version, user_major_version) != 0) || (strcmp(lib_minor_version, user_minor_version) != 0)) {
     247            0 :         dlt_vnlog(LOG_WARNING,
     248              :                   DLT_USER_BUFFER_LENGTH,
     249              :                   "DLT Library version check failed! Installed DLT library version is %s.%s - Application using DLT library version %s.%s\n",
     250              :                   lib_major_version,
     251              :                   lib_minor_version,
     252              :                   user_major_version,
     253              :                   user_minor_version);
     254              : 
     255            0 :         return DLT_RETURN_ERROR;
     256              :     }
     257              : 
     258              :     return DLT_RETURN_OK;
     259              : }
     260              : 
     261              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
     262              : static DltReturnValue dlt_socket_set_nonblock_and_linger(int sockfd)
     263              : {
     264              :     int status;
     265              :     struct linger l_opt;
     266              : 
     267              :     status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
     268              :     if (status == -1) {
     269              :         dlt_log(LOG_INFO, "Socket cannot be changed to NON BLOCK\n");
     270              :         return DLT_RETURN_ERROR;
     271              :     }
     272              : 
     273              :     l_opt.l_onoff = 1;
     274              :     l_opt.l_linger = 10;
     275              : 
     276              :     if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &l_opt, sizeof l_opt) < 0)
     277              :         dlt_log(LOG_WARNING, "Failed to set socket linger option\n");
     278              : 
     279              :     return DLT_RETURN_OK;
     280              : }
     281              : #endif
     282              : 
     283              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
     284              : static DltReturnValue dlt_initialize_socket_connection(void)
     285              : {
     286              :     struct sockaddr_un remote;
     287              :     char dltSockBaseDir[DLT_IPC_PATH_MAX];
     288              : 
     289              :     DLT_SEM_LOCK();
     290              :     int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
     291              : 
     292              :     if (sockfd == DLT_FD_INIT) {
     293              :         dlt_log(LOG_CRIT, "Failed to create socket\n");
     294              :         DLT_SEM_FREE();
     295              :         return DLT_RETURN_ERROR;
     296              :     }
     297              : 
     298              :     if (dlt_socket_set_nonblock_and_linger(sockfd) != DLT_RETURN_OK) {
     299              :         close(sockfd);
     300              :         DLT_SEM_FREE();
     301              :         return DLT_RETURN_ERROR;
     302              :     }
     303              : 
     304              :     remote.sun_family = AF_UNIX;
     305              :     snprintf(dltSockBaseDir, DLT_IPC_PATH_MAX, "%s/dlt", DLT_USER_IPC_PATH);
     306              :     strncpy(remote.sun_path, dltSockBaseDir, sizeof(remote.sun_path));
     307              : 
     308              :     if (strlen(DLT_USER_IPC_PATH) > DLT_IPC_PATH_MAX)
     309              :         dlt_vlog(LOG_INFO,
     310              :                  "Provided path too long...trimming it to path[%s]\n",
     311              :                  dltSockBaseDir);
     312              : 
     313              :     if (connect(sockfd, (struct sockaddr *)&remote, sizeof(remote)) == -1) {
     314              :         if (dlt_user.connection_state != DLT_USER_RETRY_CONNECT) {
     315              :             dlt_vlog(LOG_INFO,
     316              :                      "Socket %s cannot be opened (errno=%d). Retrying later...\n",
     317              :                      dltSockBaseDir, errno);
     318              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
     319              :         }
     320              : 
     321              :         close(sockfd);
     322              :         dlt_user.dlt_log_handle = -1;
     323              :     }
     324              :     else {
     325              :         dlt_user.dlt_log_handle = sockfd;
     326              :         dlt_user.connection_state = DLT_USER_CONNECTED;
     327              : 
     328              :         if (dlt_receiver_init(&(dlt_user.receiver),
     329              :                               sockfd,
     330              :                               DLT_RECEIVE_SOCKET,
     331              :                               DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) {
     332              :             dlt_user_init_state = INIT_UNITIALIZED;
     333              :             close(sockfd);
     334              :             DLT_SEM_FREE();
     335              :             return DLT_RETURN_ERROR;
     336              :         }
     337              :     }
     338              : 
     339              :     DLT_SEM_FREE();
     340              : 
     341              :     return DLT_RETURN_OK;
     342              : }
     343              : #elif defined DLT_LIB_USE_VSOCK_IPC
     344              : static DltReturnValue dlt_initialize_vsock_connection()
     345              : {
     346              :     struct sockaddr_vm remote;
     347              : 
     348              :     DLT_SEM_LOCK();
     349              :     int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
     350              : 
     351              :     if (sockfd == DLT_FD_INIT) {
     352              :         dlt_log(LOG_CRIT, "Failed to create VSOCK socket\n");
     353              :         DLT_SEM_FREE();
     354              :         return DLT_RETURN_ERROR;
     355              :     }
     356              : 
     357              :     memset(&remote, 0, sizeof(remote));
     358              :     remote.svm_family = AF_VSOCK;
     359              :     remote.svm_port = DLT_VSOCK_PORT;
     360              :     remote.svm_cid = VMADDR_CID_HOST;
     361              : 
     362              :     if (connect(sockfd, (struct sockaddr *)&remote, sizeof(remote)) == -1) {
     363              :         if (dlt_user.connection_state != DLT_USER_RETRY_CONNECT) {
     364              :             dlt_vlog(LOG_INFO, "VSOCK socket cannot be opened. Retrying later...\n");
     365              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
     366              :         }
     367              : 
     368              :         close(sockfd);
     369              :         dlt_user.dlt_log_handle = -1;
     370              :     }
     371              :     else {
     372              :         /* Set to non-blocking after connect() to avoid EINPROGRESS. DltUserConntextionState
     373              :            needs "connecting" state if connect() should be non-blocking. */
     374              :         if (dlt_socket_set_nonblock_and_linger(sockfd) != DLT_RETURN_OK) {
     375              :             close(sockfd);
     376              :             DLT_SEM_FREE();
     377              :             return DLT_RETURN_ERROR;
     378              :         }
     379              : 
     380              :         dlt_user.dlt_log_handle = sockfd;
     381              :         dlt_user.connection_state = DLT_USER_CONNECTED;
     382              : 
     383              :         if (dlt_receiver_init(&(dlt_user.receiver),
     384              :                               sockfd,
     385              :                               DLT_RECEIVE_SOCKET,
     386              :                               DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) {
     387              :             dlt_user_init_state = INIT_UNITIALIZED;
     388              :             close(sockfd);
     389              :             DLT_SEM_FREE();
     390              :             return DLT_RETURN_ERROR;
     391              :         }
     392              :     }
     393              : 
     394              :     DLT_SEM_FREE();
     395              : 
     396              :     return DLT_RETURN_OK;
     397              : }
     398              : #else /* DLT_LIB_USE_FIFO_IPC */
     399        21266 : static DltReturnValue dlt_initialize_fifo_connection(void)
     400              : {
     401              :     char filename[DLT_PATH_MAX];
     402              :     int ret;
     403              : 
     404              :     snprintf(dlt_user_dir, DLT_PATH_MAX, "%s/dltpipes", dltFifoBaseDir);
     405              :     snprintf(dlt_daemon_fifo, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir);
     406        21266 :     ret = mkdir(dlt_user_dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_ISVTX);
     407              : 
     408        21266 :     if ((ret == -1) && (errno != EEXIST)) {
     409            0 :         dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "FIFO user dir %s cannot be created!\n", dlt_user_dir);
     410            0 :         return DLT_RETURN_ERROR;
     411              :     }
     412              : 
     413              :     /* if dlt pipes directory is created by the application also chmod the directory */
     414        21266 :     if (ret == 0) {
     415              :         /* S_ISGID cannot be set by mkdir, let's reassign right bits */
     416            1 :         ret = chmod(dlt_user_dir,
     417              :                     S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH | S_ISGID |
     418              :                     S_ISVTX);
     419              : 
     420            1 :         if (ret == -1) {
     421            0 :             dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "FIFO user dir %s cannot be chmoded!\n", dlt_user_dir);
     422            0 :             return DLT_RETURN_ERROR;
     423              :         }
     424              :     }
     425              : 
     426              :     /* create and open DLT user FIFO */
     427        21266 :     snprintf(filename, DLT_PATH_MAX, "%s/dlt%d", dlt_user_dir, getpid());
     428              : 
     429              :     /* Try to delete existing pipe, ignore result of unlink */
     430        21266 :     unlink(filename);
     431              : 
     432        21266 :     ret = mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP);
     433              : 
     434        21266 :     if (ret == -1)
     435            0 :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Loging disabled, FIFO user %s cannot be created!\n", filename);
     436              : 
     437              :     /* S_IWGRP cannot be set by mkfifo (???), let's reassign right bits */
     438        21266 :     ret = chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP);
     439              : 
     440        21266 :     if (ret == -1) {
     441            0 :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "FIFO user %s cannot be chmoded!\n", dlt_user_dir);
     442            0 :         return DLT_RETURN_ERROR;
     443              :     }
     444              : 
     445        21266 :     dlt_user.dlt_user_handle = open(filename, O_RDWR | O_NONBLOCK | O_CLOEXEC);
     446              : 
     447        21266 :     if (dlt_user.dlt_user_handle == DLT_FD_INIT) {
     448            0 :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled, FIFO user %s cannot be opened!\n", filename);
     449            0 :         unlink(filename);
     450            0 :         return DLT_RETURN_OK;
     451              :     }
     452              : 
     453              :     /* open DLT output FIFO */
     454        21266 :     dlt_user.dlt_log_handle = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC);
     455              : 
     456        21266 :     if (dlt_user.dlt_log_handle == -1)
     457              :         /* This is a normal usecase. It is OK that the daemon (and thus the FIFO /tmp/dlt)
     458              :          * starts later and some DLT users have already been started before.
     459              :          * Thus it is OK if the FIFO can't be opened. */
     460        21259 :         dlt_vnlog(LOG_INFO, DLT_USER_BUFFER_LENGTH, "FIFO %s cannot be opened. Retrying later...\n",
     461              :                   dlt_daemon_fifo);
     462              : 
     463              :     return DLT_RETURN_OK;
     464              : }
     465              : #endif
     466              : 
     467     64169875 : DltReturnValue dlt_init(void)
     468              : {
     469              :     /* process is exiting. Do not allocate new resources. */
     470     64169875 :     if (dlt_user_freeing != 0) {
     471              : #ifndef DLT_UNIT_TESTS
     472              :         dlt_vlog(LOG_INFO, "%s logging disabled, process is exiting\n", __func__);
     473              : #endif
     474              :         /* return negative value, to stop the current log */
     475              :         return DLT_RETURN_LOGGING_DISABLED;
     476              :     }
     477              : 
     478              :     /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS.
     479              :      * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED
     480              :      * That way it's no problem, if two threads enter this function, because only the very first one will
     481              :      * pass fully. The other one will immediately return, because when it executes the atomic function
     482              :      * dlt_user_init_state won't be INIT_UNITIALIZED anymore.
     483              :      * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running.
     484              :      * Furthermore, this makes sure we enter some function only when dlt_init is fully done.
     485              :      * */
     486              :     enum InitState expectedInitState = INIT_UNITIALIZED;
     487     13058448 :     if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS))) {
     488              :         return DLT_RETURN_OK;
     489              :     }
     490              : 
     491              :     /* check environment variables */
     492        21266 :     dlt_check_envvar();
     493              : 
     494              :     /* Check logging mode and internal log file is opened or not*/
     495        21266 :     if (logging_mode == DLT_LOG_TO_FILE && logging_handle == NULL) {
     496            0 :         dlt_log_init(logging_mode);
     497              :     }
     498              : 
     499              :     /* Initialize common part of dlt_init()/dlt_init_file() */
     500        21266 :     if (dlt_init_common() == DLT_RETURN_ERROR) {
     501            0 :         dlt_user_init_state = INIT_ERROR;
     502            0 :         dlt_free();
     503            0 :         return DLT_RETURN_ERROR;
     504              :     }
     505              : 
     506        21266 :     dlt_user.dlt_is_file = 0;
     507        21266 :     dlt_user.filesize_max = UINT_MAX;
     508        21266 :     dlt_user_file_reach_max = false;
     509              : 
     510        21266 :     dlt_user.overflow = 0;
     511        21266 :     dlt_user.overflow_counter = 0;
     512              : #ifdef DLT_SHM_ENABLE
     513              :     memset(&(dlt_user.dlt_shm), 0, sizeof(DltShm));
     514              : 
     515              :     /* init shared memory */
     516              :     if (dlt_shm_init_client(&(dlt_user.dlt_shm), dltShmName) < DLT_RETURN_OK)
     517              :         dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled,"
     518              :                   " Shared memory %s cannot be created!\n", dltShmName);
     519              : 
     520              : #endif
     521              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     522              :     pthread_rwlock_wrlock(&trace_load_rw_lock);
     523              : 
     524              :     trace_load_settings = malloc(sizeof(DltTraceLoadSettings));
     525              :     if (trace_load_settings == NULL) {
     526              :         dlt_vlog(LOG_ERR, "Failed to allocate memory for trace load settings\n");
     527              :         dlt_user_init_state = INIT_UNITIALIZED;
     528              :         return DLT_RETURN_ERROR;
     529              :     }
     530              :     memset(trace_load_settings, 0, sizeof(DltTraceLoadSettings));
     531              :     trace_load_settings[0].soft_limit = DLT_TRACE_LOAD_CLIENT_SOFT_LIMIT_DEFAULT;
     532              :     trace_load_settings[0].hard_limit = DLT_TRACE_LOAD_CLIENT_HARD_LIMIT_DEFAULT;
     533              :     strncpy(trace_load_settings[0].apid, dlt_user.appID, DLT_ID_SIZE);
     534              :     trace_load_settings_count = 1;
     535              : 
     536              :     pthread_rwlock_unlock(&trace_load_rw_lock);
     537              : 
     538              : #endif
     539              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
     540              : 
     541              :     if (dlt_initialize_socket_connection() != DLT_RETURN_OK) {
     542              :         /* We could connect to the pipe, but not to the socket, which is normally */
     543              :         /* open before by the DLT daemon => bad failure => return error code */
     544              :         /* in case application is started before daemon, it is expected behaviour */
     545              :         dlt_user_init_state = INIT_ERROR;
     546              :         dlt_free();
     547              :         return DLT_RETURN_ERROR;
     548              :     }
     549              : 
     550              : #elif defined DLT_LIB_USE_VSOCK_IPC
     551              : 
     552              :     if (dlt_initialize_vsock_connection() != DLT_RETURN_OK) {
     553              :         dlt_user_init_state = INIT_ERROR;
     554              :         dlt_free();
     555              :         return DLT_RETURN_ERROR;
     556              :     }
     557              : 
     558              : #else /* DLT_LIB_USE_FIFO_IPC */
     559              : 
     560        21266 :     if (dlt_initialize_fifo_connection() != DLT_RETURN_OK) {
     561            0 :         dlt_user_init_state = INIT_ERROR;
     562            0 :         dlt_free();
     563            0 :         return DLT_RETURN_ERROR;
     564              :     }
     565              : 
     566        21266 :     if (dlt_receiver_init(&(dlt_user.receiver),
     567              :                           dlt_user.dlt_user_handle,
     568              :                           DLT_RECEIVE_FD,
     569              :                           DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) {
     570            0 :         dlt_user_init_state = INIT_ERROR;
     571            0 :         dlt_free();
     572            0 :         return DLT_RETURN_ERROR;
     573              :     }
     574              : 
     575              : #endif
     576              : 
     577              : #ifdef DLT_NETWORK_TRACE_ENABLE
     578              :     /* These will be lazy initialized only when needed */
     579        21266 :     dlt_user.dlt_segmented_queue_read_handle = -1;
     580        21266 :     dlt_user.dlt_segmented_queue_write_handle = -1;
     581              : 
     582        21266 :     pthread_cond_init(&mq_init_condition, NULL);
     583              : #endif
     584              : 
     585        21266 :     if (dlt_start_threads() < 0) {
     586            0 :         dlt_user_init_state = INIT_ERROR;
     587            0 :         dlt_free();
     588            0 :         return DLT_RETURN_ERROR;
     589              :     }
     590              : 
     591              :     /* prepare for fork() call */
     592        21266 :     pthread_atfork(NULL, NULL, &dlt_fork_child_fork_handler);
     593              : 
     594        21266 :     atomic_store(&dlt_user_init_state, INIT_DONE);
     595              : 
     596        21266 :     return DLT_RETURN_OK;
     597              : }
     598              : 
     599            0 : DltReturnValue dlt_get_appid(char *appid)
     600              : {
     601            0 :     if (appid != NULL) {
     602              :         strncpy(appid, dlt_user.appID, 4);
     603            0 :         return DLT_RETURN_OK;
     604              :     } else {
     605            0 :         dlt_log(LOG_ERR, "Invalid parameter.\n");
     606            0 :         return DLT_RETURN_WRONG_PARAMETER;
     607              :     }
     608              : }
     609              : 
     610            0 : DltReturnValue dlt_init_file(const char *name)
     611              : {
     612              :     /* check null pointer */
     613            0 :     if (!name)
     614              :         return DLT_RETURN_WRONG_PARAMETER;
     615              : 
     616              :     /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS.
     617              :      * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED
     618              :      * That way it's no problem, if two threads enter this function, because only the very first one will
     619              :      * pass fully. The other one will immediately return, because when it executes the atomic function
     620              :      * dlt_user_init_state won't be INIT_UNITIALIZED anymore.
     621              :      * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running.
     622              :      * Furthermore, this makes sure we enter some function only when dlt_init is fully done.
     623              :      * */
     624              :     enum InitState expectedInitState = INIT_UNITIALIZED;
     625            0 :     if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS)))
     626              :         return DLT_RETURN_OK;
     627              : 
     628              :     /* Initialize common part of dlt_init()/dlt_init_file() */
     629            0 :     if (dlt_init_common() == DLT_RETURN_ERROR) {
     630              :         expectedInitState = INIT_UNITIALIZED;
     631              :         return DLT_RETURN_ERROR;
     632              :     }
     633              : 
     634            0 :     dlt_user.dlt_is_file = 1;
     635              : 
     636              :     /* open DLT output file */
     637            0 :     dlt_user.dlt_log_handle = open(name, O_WRONLY | O_CREAT,
     638              :                                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
     639              : 
     640            0 :     if (dlt_user.dlt_log_handle == -1) {
     641            0 :         dlt_vnlog(LOG_ERR, DLT_USER_BUFFER_LENGTH, "Log file %s cannot be opened!\n", name);
     642            0 :         dlt_user.dlt_is_file = 0;
     643            0 :         return DLT_RETURN_ERROR;
     644              :     }
     645            0 :     atomic_store(&dlt_user_init_state, INIT_DONE);
     646              : 
     647            0 :     return DLT_RETURN_OK;
     648              : }
     649              : 
     650            0 : DltReturnValue dlt_set_filesize_max(unsigned int filesize)
     651              : {
     652            0 :     if (dlt_user.dlt_is_file == 0)
     653              :     {
     654            0 :         dlt_vlog(LOG_ERR, "%s: Library is not configured to log to file\n",
     655              :                  __func__);
     656            0 :         return DLT_RETURN_ERROR;
     657              :     }
     658              : 
     659            0 :     if (filesize == 0) {
     660            0 :         dlt_user.filesize_max = UINT_MAX;
     661              :     }
     662              :     else {
     663            0 :         dlt_user.filesize_max = filesize;
     664              :     }
     665            0 :     dlt_vlog(LOG_DEBUG, "%s: Defined filesize_max is [%d]\n", __func__,
     666              :              dlt_user.filesize_max);
     667              : 
     668            0 :     return DLT_RETURN_OK;
     669              : }
     670              : 
     671              : #ifdef DLT_NETWORK_TRACE_ENABLE
     672            0 : DltReturnValue dlt_init_message_queue(void)
     673              : {
     674            0 :     dlt_lock_mutex(&mq_mutex);
     675              : 
     676            0 :     if ((dlt_user.dlt_segmented_queue_read_handle >= 0) &&
     677            0 :         (dlt_user.dlt_segmented_queue_write_handle >= 0)) {
     678              :         /* Already intialized */
     679            0 :         dlt_unlock_mutex(&mq_mutex);
     680            0 :         return DLT_RETURN_OK;
     681              :     }
     682              : 
     683              :     /* Generate per process name for queue */
     684              :     char queue_name[NAME_MAX];
     685            0 :     snprintf(queue_name, NAME_MAX, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
     686              : 
     687              :     /* Maximum queue size is 10, limit to size of pointers */
     688              :     struct mq_attr mqatr;
     689            0 :     mqatr.mq_flags = 0;
     690            0 :     mqatr.mq_maxmsg = 10;
     691            0 :     mqatr.mq_msgsize = sizeof(s_segmented_data *);
     692            0 :     mqatr.mq_curmsgs = 0;
     693              : 
     694              :     /**
     695              :      * Create the message queue. It must be newly created
     696              :      * if old one was left by a crashing process.
     697              :      * */
     698            0 :     dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT | O_RDONLY | O_EXCL,
     699              :                                                        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
     700              :                                                        &mqatr);
     701              : 
     702            0 :     if (dlt_user.dlt_segmented_queue_read_handle < 0) {
     703            0 :         if (errno == EEXIST) {
     704            0 :             dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
     705              : 
     706            0 :             if (mq_unlink(queue_name) < 0)
     707            0 :                 dlt_vnlog(LOG_CRIT, 256, "Could not delete existing message queue!: %s \n", strerror(errno));
     708              :             else /* Retry */
     709              : 
     710            0 :                 dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name,
     711              :                                                                    O_CREAT | O_RDONLY | O_EXCL,
     712              :                                                                    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
     713              :                                                                    &mqatr);
     714              :         }
     715              : 
     716            0 :         if (dlt_user.dlt_segmented_queue_read_handle < 0) {
     717            0 :             dlt_vnlog(LOG_CRIT, 256, "Can't create message queue read handle!: %s \n", strerror(errno));
     718            0 :             dlt_unlock_mutex(&mq_mutex);
     719            0 :             return DLT_RETURN_ERROR;
     720              :         }
     721              :     }
     722              : 
     723            0 :     dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY | O_NONBLOCK);
     724              : 
     725            0 :     if (dlt_user.dlt_segmented_queue_write_handle < 0) {
     726              : 
     727            0 :         dlt_vnlog(LOG_CRIT, 256, "Can't open message queue write handle!: %s \n", strerror(errno));
     728            0 :         dlt_unlock_mutex(&mq_mutex);
     729            0 :         return DLT_RETURN_ERROR;
     730              :     }
     731              : 
     732            0 :     pthread_cond_signal(&mq_init_condition);
     733            0 :     dlt_unlock_mutex(&mq_mutex);
     734            0 :     return DLT_RETURN_OK;
     735              : }
     736              : #endif /* DLT_NETWORK_TRACE_ENABLE */
     737              : 
     738              : /* Return true if verbose mode is to be used for this DltContextData */
     739              : static inline bool is_verbose_mode(int8_t dltuser_verbose_mode, const DltContextData* log)
     740              : {
     741        11776 :     return (dltuser_verbose_mode == 1) || (log != NULL && log->verbose_mode);
     742              : }
     743              : 
     744        21267 : DltReturnValue dlt_init_common(void)
     745              : {
     746              :     char *env_local_print;
     747              :     char *env_initial_log_level;
     748              :     char *env_buffer_min;
     749              :     uint32_t buffer_min = DLT_USER_RINGBUFFER_MIN_SIZE;
     750              :     char *env_buffer_max;
     751              :     uint32_t buffer_max = DLT_USER_RINGBUFFER_MAX_SIZE;
     752              :     char *env_buffer_step;
     753              :     uint32_t buffer_step = DLT_USER_RINGBUFFER_STEP_SIZE;
     754              :     char *env_disable_extended_header_for_nonverbose;
     755              :     char *env_log_buffer_len;
     756              :     uint32_t buffer_max_configured = 0;
     757              :     uint32_t header_size = 0;
     758              : 
     759              :     // already initialized, nothing to do
     760        21267 :     if (DLT_USER_INITIALIZED) {
     761              :         return DLT_RETURN_OK;
     762              :     }
     763              : 
     764              :     /* Binary semaphore for threads */
     765        42532 :     if ((pthread_mutexattr_init(&dlt_mutex_attr) != 0) ||
     766        42532 :         (pthread_mutexattr_settype(&dlt_mutex_attr, PTHREAD_MUTEX_ERRORCHECK) != 0) ||
     767        21266 :         (pthread_mutex_init(&dlt_mutex, &dlt_mutex_attr) != 0)) {
     768            0 :         dlt_user_init_state = INIT_UNITIALIZED;
     769            0 :         return DLT_RETURN_ERROR;
     770              :     }
     771              : 
     772              :     /* set to unknown state of connected client */
     773        21266 :     dlt_user.log_state = -1;
     774              : 
     775              :     /* set pid cache to none until we need it */
     776        21266 :     dlt_user.local_pid = -1;
     777              : 
     778        21266 :     dlt_user.dlt_log_handle = -1;
     779        21266 :     dlt_user.dlt_user_handle = DLT_FD_INIT;
     780              : 
     781        21266 :     dlt_set_id(dlt_user.ecuID, DLT_USER_DEFAULT_ECU_ID);
     782        21266 :     dlt_set_id(dlt_user.appID, "");
     783              : 
     784        21266 :     dlt_user.application_description = NULL;
     785              : 
     786              :     /* Verbose mode is enabled by default */
     787        21266 :     dlt_user.verbose_mode = 1;
     788              : 
     789              :     /* header_size is used for resend buffer
     790              :      * so it won't include DltStorageHeader
     791              :      */
     792              :     header_size = sizeof(DltUserHeader) + sizeof(DltStandardHeader) +
     793              :                 sizeof(DltStandardHeaderExtra);
     794              : 
     795              :     /* Use extended header for non verbose is enabled by default */
     796        21266 :     dlt_user.use_extended_header_for_non_verbose =
     797              :             DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE;
     798              : 
     799              :     /* Use extended header for non verbose is modified as per environment variable */
     800              :     env_disable_extended_header_for_nonverbose =
     801        21266 :             getenv(DLT_USER_ENV_DISABLE_EXTENDED_HEADER_FOR_NONVERBOSE);
     802              : 
     803        21266 :     if (env_disable_extended_header_for_nonverbose) {
     804            0 :         if (strcmp(env_disable_extended_header_for_nonverbose, "1") == 0)
     805            0 :             dlt_user.use_extended_header_for_non_verbose =
     806              :                     DLT_USER_NO_USE_EXTENDED_HEADER_FOR_NONVERBOSE;
     807              :     }
     808              : 
     809        21266 :     if (dlt_user.use_extended_header_for_non_verbose ==
     810              :             DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE)
     811              :         header_size += (uint32_t) sizeof(DltExtendedHeader);
     812              : 
     813              :     /* With session id is enabled by default */
     814        21266 :     dlt_user.with_session_id = DLT_USER_WITH_SESSION_ID;
     815              : 
     816              :     /* With timestamp is enabled by default */
     817        21266 :     dlt_user.with_timestamp = DLT_USER_WITH_TIMESTAMP;
     818              : 
     819              :     /* With timestamp is enabled by default */
     820        21266 :     dlt_user.with_ecu_id = DLT_USER_WITH_ECU_ID;
     821              : 
     822              :     /* Local print is disabled by default */
     823        21266 :     dlt_user.enable_local_print = 0;
     824              : 
     825        21266 :     dlt_user.local_print_mode = DLT_PM_UNSET;
     826              : 
     827        21266 :     dlt_user.timeout_at_exit_handler = DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
     828              : 
     829        21266 :     env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
     830              : 
     831        21266 :     if (env_local_print) {
     832            0 :         if (strcmp(env_local_print, "AUTOMATIC") == 0)
     833            0 :             dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
     834            0 :         else if (strcmp(env_local_print, "FORCE_ON") == 0)
     835            0 :             dlt_user.local_print_mode = DLT_PM_FORCE_ON;
     836            0 :         else if (strcmp(env_local_print, "FORCE_OFF") == 0)
     837            0 :             dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
     838              :     }
     839              : 
     840        21266 :     env_initial_log_level = getenv("DLT_INITIAL_LOG_LEVEL");
     841              : 
     842        21266 :     if (env_initial_log_level != NULL) {
     843            0 :         if (dlt_env_extract_ll_set(&env_initial_log_level, &dlt_user.initial_ll_set) != 0)
     844            0 :             dlt_vlog(LOG_WARNING,
     845              :                      "Unable to parse initial set of log-levels from environment! Env:\n%s\n",
     846              :                      getenv("DLT_INITIAL_LOG_LEVEL"));
     847              :     }
     848              : 
     849              :     /* Initialize LogLevel/TraceStatus field */
     850        21266 :     DLT_SEM_LOCK();
     851        21266 :     dlt_user.dlt_ll_ts = NULL;
     852        21266 :     dlt_user.dlt_ll_ts_max_num_entries = 0;
     853        21266 :     dlt_user.dlt_ll_ts_num_entries = 0;
     854              : 
     855              : 
     856        21266 :     env_buffer_min = getenv(DLT_USER_ENV_BUFFER_MIN_SIZE);
     857        21266 :     env_buffer_max = getenv(DLT_USER_ENV_BUFFER_MAX_SIZE);
     858        21266 :     env_buffer_step = getenv(DLT_USER_ENV_BUFFER_STEP_SIZE);
     859              : 
     860        21266 :     if (env_buffer_min != NULL) {
     861            0 :         buffer_min = (uint32_t)strtol(env_buffer_min, NULL, 10);
     862              : 
     863            0 :         if ((errno == EINVAL) || (errno == ERANGE)) {
     864            0 :             dlt_vlog(LOG_ERR,
     865              :                      "Wrong value specified for %s. Using default\n",
     866              :                      DLT_USER_ENV_BUFFER_MIN_SIZE);
     867              :             buffer_min = DLT_USER_RINGBUFFER_MIN_SIZE;
     868              :         }
     869              :     }
     870              : 
     871        21266 :     if (env_buffer_max != NULL) {
     872            0 :         buffer_max = (uint32_t)strtol(env_buffer_max, NULL, 10);
     873              : 
     874            0 :         if ((errno == EINVAL) || (errno == ERANGE)) {
     875            0 :             dlt_vlog(LOG_ERR,
     876              :                      "Wrong value specified for %s. Using default\n",
     877              :                      DLT_USER_ENV_BUFFER_MAX_SIZE);
     878              :             buffer_max = DLT_USER_RINGBUFFER_MAX_SIZE;
     879              :         }
     880              :     }
     881              : 
     882        21266 :     if (env_buffer_step != NULL) {
     883            0 :         buffer_step = (uint32_t)strtol(env_buffer_step, NULL, 10);
     884              : 
     885            0 :         if ((errno == EINVAL) || (errno == ERANGE)) {
     886            0 :             dlt_vlog(LOG_ERR,
     887              :                      "Wrong value specified for %s. Using default\n",
     888              :                      DLT_USER_ENV_BUFFER_STEP_SIZE);
     889              :             buffer_step = DLT_USER_RINGBUFFER_STEP_SIZE;
     890              :         }
     891              :     }
     892              : 
     893              :     /* init log buffer size */
     894        21266 :     dlt_user.log_buf_len = DLT_USER_BUF_MAX_SIZE;
     895        21266 :     env_log_buffer_len = getenv(DLT_USER_ENV_LOG_MSG_BUF_LEN);
     896              : 
     897        21266 :     if (env_log_buffer_len != NULL) {
     898            7 :         buffer_max_configured = (uint32_t)strtol(env_log_buffer_len, NULL, 10);
     899              : 
     900            7 :         if (buffer_max_configured > DLT_LOG_MSG_BUF_MAX_SIZE) {
     901            0 :             dlt_user.log_buf_len = DLT_LOG_MSG_BUF_MAX_SIZE;
     902            0 :             dlt_vlog(LOG_WARNING,
     903              :                      "Configured size exceeds maximum allowed size,restricting to max [65535 bytes]\n");
     904              :         }
     905              :         else {
     906            7 :             dlt_user.log_buf_len = (uint16_t) buffer_max_configured;
     907            7 :             dlt_vlog(LOG_INFO,
     908              :                      "Configured buffer size to [%u bytes]\n",
     909              :                      buffer_max_configured);
     910              :         }
     911              :     }
     912              : 
     913        21266 :     if (dlt_user.resend_buffer == NULL) {
     914        21266 :         dlt_user.resend_buffer = calloc(sizeof(unsigned char),
     915        21266 :                                         (dlt_user.log_buf_len + header_size));
     916              : 
     917        21266 :         if (dlt_user.resend_buffer == NULL) {
     918            0 :             dlt_user_init_state = INIT_UNITIALIZED;
     919            0 :             DLT_SEM_FREE();
     920            0 :             dlt_vlog(LOG_ERR, "cannot allocate memory for resend buffer\n");
     921            0 :             return DLT_RETURN_ERROR;
     922              :         }
     923              :     }
     924              : 
     925        21266 :     dlt_user.disable_injection_msg = 0;
     926        21266 :     if (getenv(DLT_USER_ENV_DISABLE_INJECTION_MSG)) {
     927            0 :         dlt_log(LOG_WARNING, "Injection message is disabled\n");
     928            0 :         dlt_user.disable_injection_msg = 1;
     929              :     }
     930              : 
     931        21266 :     if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer),
     932              :                                 buffer_min,
     933              :                                 buffer_max,
     934              :                                 buffer_step) == DLT_RETURN_ERROR) {
     935            0 :         dlt_user_init_state = INIT_UNITIALIZED;
     936            0 :         DLT_SEM_FREE();
     937            0 :         return DLT_RETURN_ERROR;
     938              :     }
     939              : 
     940        21266 :     DLT_SEM_FREE();
     941              : 
     942        21266 :     signal(SIGPIPE, SIG_IGN);                  /* ignore pipe signals */
     943              : 
     944        21266 :     if (atexit_registered == 0) {
     945            8 :         atexit_registered = 1;
     946            8 :         atexit(dlt_user_atexit_handler);
     947              :     }
     948              : 
     949              : #ifdef DLT_TEST_ENABLE
     950              :     dlt_user.corrupt_user_header = 0;
     951              :     dlt_user.corrupt_message_size = 0;
     952              :     dlt_user.corrupt_message_size_size = 0;
     953              : #endif
     954              : 
     955              :     return DLT_RETURN_OK;
     956              : }
     957              : 
     958            8 : void dlt_user_atexit_handler(void)
     959              : {
     960              :     /* parent will do clean-up */
     961            8 :     if (g_dlt_is_child)
     962              :         return;
     963              : 
     964            8 :     if (!DLT_USER_INITIALIZED) {
     965            1 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
     966              :         /* close file */
     967            1 :         dlt_log_free();
     968            1 :         return;
     969              :     }
     970              : 
     971              :     /* Try to resend potential log messages in the user buffer */
     972            7 :     int count = dlt_user_atexit_blow_out_user_buffer();
     973              : 
     974            7 :     if (count != 0)
     975            1 :         dlt_vnlog(LOG_WARNING, 128, "Lost log messages in user buffer when exiting: %i\n", count);
     976              : 
     977              :     /* Unregister app (this also unregisters all contexts in daemon) */
     978              :     /* Ignore return value */
     979            7 :     dlt_unregister_app_util(false);
     980              : 
     981              :     /* Cleanup */
     982              :     /* Ignore return value */
     983            7 :     dlt_free();
     984              : 
     985              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     986              :     pthread_rwlock_destroy(&trace_load_rw_lock);
     987              : #endif
     988              : }
     989              : 
     990            7 : int dlt_user_atexit_blow_out_user_buffer(void)
     991              : {
     992              : 
     993              :     int count, ret;
     994              :     struct timespec ts;
     995              : 
     996            7 :     uint32_t exitTime = dlt_uptime() + dlt_user.timeout_at_exit_handler;
     997              : 
     998              :     /* Send content of ringbuffer */
     999            7 :     DLT_SEM_LOCK();
    1000            7 :     count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1001            7 :     DLT_SEM_FREE();
    1002              : 
    1003            7 :     if (count > 0) {
    1004          101 :         while (dlt_uptime() < exitTime) {
    1005          100 :             if (dlt_user.dlt_log_handle == -1) {
    1006              :                 /* Reattach to daemon if neccesary */
    1007          100 :                 dlt_user_log_reattach_to_daemon();
    1008              : 
    1009          100 :                 if ((dlt_user.dlt_log_handle != -1) && (dlt_user.overflow_counter)) {
    1010            0 :                     if (dlt_user_log_send_overflow() == 0) {
    1011            0 :                         dlt_vnlog(LOG_WARNING,
    1012              :                                   DLT_USER_BUFFER_LENGTH,
    1013              :                                   "%u messages discarded!\n",
    1014              :                                   dlt_user.overflow_counter);
    1015            0 :                         dlt_user.overflow_counter = 0;
    1016              :                     }
    1017              :                 }
    1018              :             }
    1019              : 
    1020          100 :             if (dlt_user.dlt_log_handle != -1) {
    1021            0 :                 ret = dlt_user_log_resend_buffer();
    1022              : 
    1023            0 :                 if (ret == 0) {
    1024            0 :                     DLT_SEM_LOCK();
    1025            0 :                     count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1026            0 :                     DLT_SEM_FREE();
    1027              : 
    1028            0 :                     return count;
    1029              :                 }
    1030              :             }
    1031              : 
    1032          100 :             ts.tv_sec = 0;
    1033          100 :             ts.tv_nsec = DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP;
    1034          100 :             nanosleep(&ts, NULL);
    1035              :         }
    1036              : 
    1037            1 :         DLT_SEM_LOCK();
    1038            1 :         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1039            1 :         DLT_SEM_FREE();
    1040              :     }
    1041              : 
    1042              :     return count;
    1043              : }
    1044              : 
    1045              : static void dlt_user_free_buffer(unsigned char **buffer)
    1046              : {
    1047        27276 :     if (*buffer) {
    1048            2 :         free(*buffer);
    1049        27265 :         *buffer = NULL;
    1050              :     }
    1051              : }
    1052              : 
    1053        65369 : DltReturnValue dlt_free(void)
    1054              : {
    1055              :     uint32_t i;
    1056              :     int ret = 0;
    1057              :     int expected = 0;
    1058              : #ifdef DLT_LIB_USE_FIFO_IPC
    1059              :     char filename[DLT_PATH_MAX];
    1060              : #endif
    1061              : 
    1062              :     /* library is freeing its resources. Avoid to allocate it in dlt_init() */
    1063        65369 :     if (!(atomic_compare_exchange_strong(&dlt_user_freeing, &expected, 1))) {
    1064              :         /* resources are already being freed. Do nothing and return. */
    1065              :         return DLT_RETURN_ERROR;
    1066              :     }
    1067              : 
    1068              :     // no need to free when not initialized and no error occurred.
    1069              :     // on error some resources might have been allocated, so free them.
    1070        65369 :     if (!DLT_USER_INITIALIZED && !DLT_USER_INIT_ERROR) {
    1071        44103 :         dlt_user_freeing = 0;
    1072        44103 :         return DLT_RETURN_ERROR;
    1073              :     }
    1074              : 
    1075        21266 :     DLT_SEM_LOCK();
    1076              : 
    1077        21266 :     dlt_stop_threads();
    1078              : 
    1079        21266 :     dlt_user_init_state = INIT_UNITIALIZED;
    1080              : 
    1081              : #ifdef DLT_LIB_USE_FIFO_IPC
    1082              : 
    1083        21266 :     if (dlt_user.dlt_user_handle != DLT_FD_INIT) {
    1084        21266 :         close(dlt_user.dlt_user_handle);
    1085        21266 :         dlt_user.dlt_user_handle = DLT_FD_INIT;
    1086        21266 :         snprintf(filename, DLT_PATH_MAX, "%s/dlt%d", dlt_user_dir, getpid());
    1087        21266 :         unlink(filename);
    1088              :     }
    1089              : 
    1090              : #endif
    1091              : 
    1092              : #ifdef DLT_SHM_ENABLE
    1093              :     /* free shared memory */
    1094              :     dlt_shm_free_client(&dlt_user.dlt_shm);
    1095              : #endif
    1096              : 
    1097        21266 :     if (dlt_user.dlt_log_handle != -1) {
    1098              :         /* close log file/output fifo to daemon */
    1099              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    1100              :         ret = shutdown(dlt_user.dlt_log_handle, SHUT_WR);
    1101              : 
    1102              :         if (ret < 0) {
    1103              :             dlt_vlog(LOG_WARNING, "%s: shutdown failed: %s\n", __func__, strerror(errno));
    1104              :         }
    1105              :         else {
    1106              :             ssize_t bytes_read = 0;
    1107              :             int prev_errno = 0;
    1108              :             struct pollfd nfd[1];
    1109              :             nfd[0].events = POLLIN;
    1110              :             nfd[0].fd = dlt_user.dlt_log_handle;
    1111              : 
    1112              :             while (1) {
    1113              :                 ret = poll(nfd, 1, DLT_USER_RECEIVE_MDELAY);
    1114              : 
    1115              :                 /* In case failure of polling or reaching timeout,
    1116              :                  * continue to close socket anyway.
    1117              :                  * */
    1118              :                 if (ret < 0) {
    1119              :                     dlt_vlog(LOG_WARNING, "[%s] Failed to poll with error [%s]\n",
    1120              :                             __func__, strerror(errno));
    1121              :                     break;
    1122              :                 }
    1123              :                 else if (ret == 0) {
    1124              :                     dlt_vlog(LOG_DEBUG, "[%s] Polling timeout\n", __func__);
    1125              :                     break;
    1126              :                 }
    1127              :                 else {
    1128              :                     /* It could take some time to get the socket is shutdown
    1129              :                      * So it means there could be some data available to read.
    1130              :                      * Try to consume the data and poll the socket again.
    1131              :                      * If read fails, time to close the socket then.
    1132              :                      */
    1133              :                     dlt_vlog(LOG_DEBUG, "[%s] polling returns [%d] with revent [0x%x]."
    1134              :                             "There are something to read\n", __func__, ret, (unsigned int)nfd[0].revents);
    1135              : 
    1136              :                     bytes_read = read(dlt_user.dlt_log_handle, dlt_user.resend_buffer, dlt_user.log_buf_len);
    1137              :                     prev_errno = errno;
    1138              : 
    1139              :                     if (bytes_read < 0) {
    1140              :                         dlt_vlog(LOG_WARNING, "[%s] Failed to read with error [%s]\n",
    1141              :                                 __func__, strerror(prev_errno));
    1142              : 
    1143              :                         if ((prev_errno == EAGAIN) || (EWOULDBLOCK != EAGAIN && prev_errno == EWOULDBLOCK))
    1144              :                             continue;
    1145              :                         else
    1146              :                             break;
    1147              :                     }
    1148              :                     if (bytes_read >= 0) {
    1149              :                         dlt_vlog(LOG_DEBUG, "%s - %d: %d bytes read from resend buffer\n",
    1150              :                                 __func__, __LINE__, (int)bytes_read);
    1151              :                         if (!bytes_read)
    1152              :                             break;
    1153              :                         dlt_vlog(LOG_NOTICE, "[%s] data is still readable... [%zd] bytes read\n",
    1154              :                                 __func__, bytes_read);
    1155              :                     }
    1156              :                 }
    1157              :             }
    1158              :         }
    1159              : 
    1160              : #endif
    1161            6 :         ret = close(dlt_user.dlt_log_handle);
    1162              : 
    1163            6 :         if (ret < 0)
    1164            0 :             dlt_vlog(LOG_WARNING, "%s: close failed: %s\n", __func__, strerror(errno));
    1165              : 
    1166            6 :         dlt_user.dlt_log_handle = -1;
    1167              :     }
    1168              : 
    1169        21266 :     dlt_receiver_free(&(dlt_user.receiver));
    1170              : 
    1171              :     dlt_user_free_buffer(&(dlt_user.resend_buffer));
    1172        21266 :     dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
    1173              : 
    1174              :     /* Clear and free local stored application information */
    1175        21266 :     if (dlt_user.application_description != NULL)
    1176            0 :         free(dlt_user.application_description);
    1177        21266 :     dlt_user.application_description = NULL;
    1178              : 
    1179        21266 :     if (dlt_user.dlt_ll_ts) {
    1180        10521 :         for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1181        10500 :             if (dlt_user.dlt_ll_ts[i].context_description != NULL) {
    1182            1 :                 free (dlt_user.dlt_ll_ts[i].context_description);
    1183            1 :                 dlt_user.dlt_ll_ts[i].context_description = NULL;
    1184              :             }
    1185              : 
    1186        10500 :             if (dlt_user.dlt_ll_ts[i].log_level_ptr != NULL) {
    1187            1 :                 free(dlt_user.dlt_ll_ts[i].log_level_ptr);
    1188            1 :                 dlt_user.dlt_ll_ts[i].log_level_ptr = NULL;
    1189              :             }
    1190              : 
    1191        10500 :             if (dlt_user.dlt_ll_ts[i].trace_status_ptr != NULL) {
    1192            1 :                 free(dlt_user.dlt_ll_ts[i].trace_status_ptr);
    1193            1 :                 dlt_user.dlt_ll_ts[i].trace_status_ptr = NULL;
    1194              :             }
    1195              : 
    1196        10500 :             if (dlt_user.dlt_ll_ts[i].injection_table != NULL) {
    1197            0 :                 free(dlt_user.dlt_ll_ts[i].injection_table);
    1198            0 :                 dlt_user.dlt_ll_ts[i].injection_table = NULL;
    1199              :             }
    1200              : 
    1201        10500 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1202        10500 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0;
    1203              :         }
    1204              : 
    1205           21 :         free(dlt_user.dlt_ll_ts);
    1206           21 :         dlt_user.dlt_ll_ts = NULL;
    1207           21 :         dlt_user.dlt_ll_ts_max_num_entries = 0;
    1208           21 :         dlt_user.dlt_ll_ts_num_entries = 0;
    1209              :     }
    1210              : 
    1211        21266 :     dlt_env_free_ll_set(&dlt_user.initial_ll_set);
    1212              : 
    1213              : #ifdef DLT_NETWORK_TRACE_ENABLE
    1214              :     char queue_name[NAME_MAX];
    1215        21266 :     snprintf(queue_name, NAME_MAX, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
    1216              : 
    1217              :     /**
    1218              :      * Ignore errors from these, to not to spam user if dlt_free
    1219              :      * is accidentally called multiple times.
    1220              :      */
    1221        21266 :     if (dlt_user.dlt_segmented_queue_write_handle > 0)
    1222            0 :         mq_close(dlt_user.dlt_segmented_queue_write_handle);
    1223              : 
    1224        21266 :     if (dlt_user.dlt_segmented_queue_read_handle > 0)
    1225            0 :         mq_close(dlt_user.dlt_segmented_queue_read_handle);
    1226              : 
    1227        21266 :     if ((dlt_user.dlt_segmented_queue_write_handle > 0) ||
    1228        21266 :         (dlt_user.dlt_segmented_queue_read_handle > 0))
    1229            0 :         mq_unlink(queue_name);
    1230              : 
    1231        21266 :     dlt_user.dlt_segmented_queue_write_handle = DLT_FD_INIT;
    1232        21266 :     dlt_user.dlt_segmented_queue_read_handle = DLT_FD_INIT;
    1233              : 
    1234        21266 :     pthread_cond_destroy(&mq_init_condition);
    1235              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    1236              : 
    1237              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1238              :     if (trace_load_settings != NULL) {
    1239              :         free(trace_load_settings);
    1240              :         trace_load_settings = NULL;
    1241              :     }
    1242              :     trace_load_settings_count = 0;
    1243              : #endif
    1244              : 
    1245        21266 :     DLT_SEM_FREE();
    1246        21266 :     pthread_mutex_destroy(&dlt_mutex);
    1247              : 
    1248              :     /* allow the user app to do dlt_init() again. */
    1249              :     /* The flag is unset only to keep almost the same behaviour as before, on EntryNav */
    1250              :     /* This should be removed for other projects (see documentation of dlt_free() */
    1251        21266 :     dlt_user_freeing = 0;
    1252              : 
    1253        21266 :     return DLT_RETURN_OK;
    1254              : }
    1255              : 
    1256            7 : DltReturnValue dlt_check_library_version(const char *user_major_version, const char *user_minor_version)
    1257              : {
    1258            7 :     return dlt_user_check_library_version(user_major_version, user_minor_version);
    1259              : }
    1260              : 
    1261          176 : DltReturnValue dlt_register_app(const char *apid, const char *description)
    1262              : {
    1263              :     DltReturnValue ret = DLT_RETURN_OK;
    1264              : 
    1265              :     /* forbid dlt usage in child after fork */
    1266          176 :     if (g_dlt_is_child)
    1267              :         return DLT_RETURN_ERROR;
    1268              : 
    1269          176 :     if (!DLT_USER_INITIALIZED) {
    1270            8 :         if (dlt_init() < 0) {
    1271            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    1272            0 :             return DLT_RETURN_ERROR;
    1273              :         }
    1274              :     }
    1275              : 
    1276          176 :     if ((apid == NULL) || (apid[0] == '\0'))
    1277              :         return DLT_RETURN_WRONG_PARAMETER;
    1278              : 
    1279              :     /* check if application already registered */
    1280              :     /* if yes do not register again */
    1281          172 :     if (apid[1] == 0) {
    1282            2 :         if (apid[0] == dlt_user.appID[0])
    1283              :             return DLT_RETURN_OK;
    1284              :     }
    1285          170 :     else if (apid[2] == 0)
    1286              :     {
    1287            2 :         if ((apid[0] == dlt_user.appID[0]) &&
    1288            0 :             (apid[1] == dlt_user.appID[1]))
    1289              :             return DLT_RETURN_OK;
    1290              :     }
    1291          168 :     else if (apid[3] == 0)
    1292              :     {
    1293            2 :         if ((apid[0] == dlt_user.appID[0]) &&
    1294            0 :             (apid[1] == dlt_user.appID[1]) &&
    1295            0 :             (apid[2] == dlt_user.appID[2]))
    1296              :             return DLT_RETURN_OK;
    1297              :     }
    1298          166 :     else if ((apid[0] == dlt_user.appID[0]) &&
    1299            1 :              (apid[1] == dlt_user.appID[1]) &&
    1300            1 :              (apid[2] == dlt_user.appID[2]) &&
    1301            1 :              (apid[3] == dlt_user.appID[3]))
    1302              :     {
    1303              :         return DLT_RETURN_OK;
    1304              :     }
    1305              : 
    1306          171 :     DLT_SEM_LOCK();
    1307              : 
    1308              :     /* Store locally application id and application description */
    1309          171 :     dlt_set_id(dlt_user.appID, apid);
    1310              : 
    1311          171 :     if (dlt_user.application_description != NULL)
    1312            0 :         free(dlt_user.application_description);
    1313              : 
    1314          171 :     dlt_user.application_description = NULL;
    1315              : 
    1316          171 :     if (description != NULL) {
    1317          171 :         size_t desc_len = strlen(description);
    1318          171 :         dlt_user.application_description = malloc(desc_len + 1);
    1319              : 
    1320          171 :         if (dlt_user.application_description) {
    1321              :             strncpy(dlt_user.application_description, description, desc_len + 1);
    1322              :         } else {
    1323            0 :             DLT_SEM_FREE();
    1324            0 :             return DLT_RETURN_ERROR;
    1325              :         }
    1326              :     }
    1327              : 
    1328          171 :     DLT_SEM_FREE();
    1329              : 
    1330              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1331              :     strncpy(trace_load_settings[0].apid, dlt_user.appID, DLT_ID_SIZE);
    1332              : #endif
    1333              : 
    1334          171 :     ret = dlt_user_log_send_register_application();
    1335              : 
    1336          171 :     if ((ret == DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1))
    1337            7 :         ret = dlt_user_log_resend_buffer();
    1338              : 
    1339              :     return ret;
    1340              : }
    1341              : 
    1342          203 : DltReturnValue dlt_register_context(DltContext *handle, const char *contextid, const char *description)
    1343              : {
    1344              :     /* check nullpointer */
    1345          203 :     if (handle == NULL)
    1346              :         return DLT_RETURN_WRONG_PARAMETER;
    1347              : 
    1348              :     /* forbid dlt usage in child after fork */
    1349          197 :     if (g_dlt_is_child)
    1350              :         return DLT_RETURN_ERROR;
    1351              : 
    1352          197 :     if (!DLT_USER_INITIALIZED) {
    1353            0 :         if (dlt_init() < 0) {
    1354            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    1355            0 :             return DLT_RETURN_ERROR;
    1356              :         }
    1357              :     }
    1358              : 
    1359          197 :     if ((contextid == NULL) || (contextid[0] == '\0'))
    1360              :         return DLT_RETURN_WRONG_PARAMETER;
    1361              : 
    1362          189 :     return dlt_register_context_ll_ts(handle,
    1363              :                                       contextid,
    1364              :                                       description,
    1365              :                                       DLT_USER_LOG_LEVEL_NOT_SET,
    1366              :                                       DLT_USER_TRACE_STATUS_NOT_SET);
    1367              : }
    1368              : 
    1369          216 : DltReturnValue dlt_register_context_ll_ts_llccb(DltContext *handle,
    1370              :                                                 const char *contextid,
    1371              :                                                 const char *description,
    1372              :                                                 int loglevel,
    1373              :                                                 int tracestatus,
    1374              :                                                 void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE],
    1375              :                                                                                        uint8_t log_level,
    1376              :                                                                                        uint8_t trace_status))
    1377              : {
    1378              :     DltContextData log;
    1379              :     uint32_t i;
    1380              :     int envLogLevel = DLT_USER_LOG_LEVEL_NOT_SET;
    1381              : 
    1382              :     /*check nullpointer */
    1383          216 :     if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0'))
    1384              :         return DLT_RETURN_WRONG_PARAMETER;
    1385              : 
    1386              :     /* forbid dlt usage in child after fork */
    1387          209 :     if (g_dlt_is_child)
    1388              :         return DLT_RETURN_ERROR;
    1389              : 
    1390          209 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    1391            2 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    1392            2 :         return DLT_RETURN_WRONG_PARAMETER;
    1393              :     }
    1394              : 
    1395          207 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    1396            2 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    1397            2 :         return DLT_RETURN_WRONG_PARAMETER;
    1398              :     }
    1399              : 
    1400          205 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    1401              :         return DLT_RETURN_ERROR;
    1402              : 
    1403              :     /* Reset message counter */
    1404          205 :     handle->mcnt = 0;
    1405              : 
    1406              :     /* Store context id in log level/trace status field */
    1407              : 
    1408              :     /* Check if already registered, else register context */
    1409          205 :     DLT_SEM_LOCK();
    1410              : 
    1411              :     /* Check of double context registration removed */
    1412              :     /* Double registration is already checked by daemon */
    1413              : 
    1414              :     /* Allocate or expand context array */
    1415          205 :     if (dlt_user.dlt_ll_ts == NULL) {
    1416           21 :         dlt_user.dlt_ll_ts = (dlt_ll_ts_type *)malloc(sizeof(dlt_ll_ts_type) * DLT_USER_CONTEXT_ALLOC_SIZE);
    1417              : 
    1418           21 :         if (dlt_user.dlt_ll_ts == NULL) {
    1419            0 :             DLT_SEM_FREE();
    1420            0 :             return DLT_RETURN_ERROR;
    1421              :         }
    1422              : 
    1423           21 :         dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
    1424              : 
    1425              :         /* Initialize new entries */
    1426        10521 :         for (i = 0; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1427        10500 :             dlt_set_id(dlt_user.dlt_ll_ts[i].contextID, "");
    1428              : 
    1429              :             /* At startup, logging and tracing is locally enabled */
    1430              :             /* the correct log level/status is set after received from daemon */
    1431        10500 :             dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1432        10500 :             dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1433              : 
    1434        10500 :             dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
    1435        10500 :             dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
    1436              : 
    1437        10500 :             dlt_user.dlt_ll_ts[i].context_description = 0;
    1438              : 
    1439        10500 :             dlt_user.dlt_ll_ts[i].injection_table = 0;
    1440        10500 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1441        10500 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0;
    1442              :         }
    1443              :     }
    1444          184 :     else if ((dlt_user.dlt_ll_ts_num_entries % DLT_USER_CONTEXT_ALLOC_SIZE) == 0)
    1445              :     {
    1446              :         /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
    1447              :         dlt_ll_ts_type *old_ll_ts;
    1448              :         uint32_t old_max_entries;
    1449              : 
    1450              :         old_ll_ts = dlt_user.dlt_ll_ts;
    1451            0 :         old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
    1452              : 
    1453            0 :         dlt_user.dlt_ll_ts_max_num_entries = ((dlt_user.dlt_ll_ts_num_entries
    1454            0 :                                                / DLT_USER_CONTEXT_ALLOC_SIZE) + 1)
    1455            0 :             * DLT_USER_CONTEXT_ALLOC_SIZE;
    1456            0 :         dlt_user.dlt_ll_ts = (dlt_ll_ts_type *)malloc(sizeof(dlt_ll_ts_type) *
    1457            0 :                                                       dlt_user.dlt_ll_ts_max_num_entries);
    1458              : 
    1459            0 :         if (dlt_user.dlt_ll_ts == NULL) {
    1460            0 :             dlt_user.dlt_ll_ts = old_ll_ts;
    1461            0 :             dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
    1462            0 :             DLT_SEM_FREE();
    1463            0 :             return DLT_RETURN_ERROR;
    1464              :         }
    1465              : 
    1466            0 :         memcpy(dlt_user.dlt_ll_ts, old_ll_ts, sizeof(dlt_ll_ts_type) * dlt_user.dlt_ll_ts_num_entries);
    1467            0 :         free(old_ll_ts);
    1468              : 
    1469              :         /* Initialize new entries */
    1470            0 :         for (i = dlt_user.dlt_ll_ts_num_entries; i < dlt_user.dlt_ll_ts_max_num_entries; i++) {
    1471            0 :             dlt_set_id(dlt_user.dlt_ll_ts[i].contextID, "");
    1472              : 
    1473              :             /* At startup, logging and tracing is locally enabled */
    1474              :             /* the correct log level/status is set after received from daemon */
    1475            0 :             dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1476            0 :             dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1477              : 
    1478            0 :             dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
    1479            0 :             dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
    1480              : 
    1481            0 :             dlt_user.dlt_ll_ts[i].context_description = 0;
    1482              : 
    1483            0 :             dlt_user.dlt_ll_ts[i].injection_table = 0;
    1484            0 :             dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
    1485            0 :             dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0;
    1486              :         }
    1487              :     }
    1488              : 
    1489              :     /* New context entry to be initialized */
    1490              :     dlt_ll_ts_type *ctx_entry;
    1491          205 :     ctx_entry = &dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries];
    1492              : 
    1493              :     /* Store locally context id and context description */
    1494          205 :     dlt_set_id(ctx_entry->contextID, contextid);
    1495              : 
    1496          205 :     if (ctx_entry->context_description != 0)
    1497            0 :         free(ctx_entry->context_description);
    1498              : 
    1499          205 :     ctx_entry->context_description = 0;
    1500              : 
    1501          205 :     if (description != 0) {
    1502          205 :         size_t desc_len = strlen(description);
    1503          205 :         ctx_entry->context_description = malloc(desc_len + 1);
    1504              : 
    1505          205 :         if (ctx_entry->context_description == 0) {
    1506            0 :             DLT_SEM_FREE();
    1507            0 :             return DLT_RETURN_ERROR;
    1508              :         }
    1509              : 
    1510              :         strncpy(ctx_entry->context_description, description, desc_len + 1);
    1511              :     }
    1512              : 
    1513          205 :     if (ctx_entry->log_level_ptr == 0) {
    1514          205 :         ctx_entry->log_level_ptr = malloc(sizeof(int8_t));
    1515              : 
    1516          205 :         if (ctx_entry->log_level_ptr == 0) {
    1517            0 :             DLT_SEM_FREE();
    1518            0 :             return DLT_RETURN_ERROR;
    1519              :         }
    1520              :     }
    1521              : 
    1522          205 :     if (ctx_entry->trace_status_ptr == 0) {
    1523          205 :         ctx_entry->trace_status_ptr = malloc(sizeof(int8_t));
    1524              : 
    1525          205 :         if (ctx_entry->trace_status_ptr == 0) {
    1526            0 :             DLT_SEM_FREE();
    1527            0 :             return DLT_RETURN_ERROR;
    1528              :         }
    1529              :     }
    1530              : 
    1531              :     /* check if the log level is set in the environement */
    1532          205 :     envLogLevel = dlt_env_adjust_ll_from_env(&dlt_user.initial_ll_set,
    1533              :                                              dlt_user.appID,
    1534              :                                              contextid,
    1535              :                                              DLT_USER_LOG_LEVEL_NOT_SET);
    1536              : 
    1537          205 :     if (envLogLevel != DLT_USER_LOG_LEVEL_NOT_SET) {
    1538            0 :         ctx_entry->log_level = (int8_t) envLogLevel;
    1539              :         loglevel = envLogLevel;
    1540              :     }
    1541          205 :     else if (loglevel != DLT_USER_LOG_LEVEL_NOT_SET)
    1542              :     {
    1543           16 :         ctx_entry->log_level = (int8_t) loglevel;
    1544              :     }
    1545              : 
    1546          205 :     if (tracestatus != DLT_USER_TRACE_STATUS_NOT_SET)
    1547           15 :         ctx_entry->trace_status = (int8_t) tracestatus;
    1548              : 
    1549              :     /* Prepare transfer struct */
    1550          205 :     dlt_set_id(handle->contextID, contextid);
    1551          205 :     handle->log_level_pos = (int32_t) dlt_user.dlt_ll_ts_num_entries;
    1552              : 
    1553          205 :     handle->log_level_ptr = ctx_entry->log_level_ptr;
    1554          205 :     handle->trace_status_ptr = ctx_entry->trace_status_ptr;
    1555              : 
    1556          205 :     log.context_description = ctx_entry->context_description;
    1557              : 
    1558          205 :     *(ctx_entry->log_level_ptr) = ctx_entry->log_level;
    1559          205 :     *(ctx_entry->trace_status_ptr) = ctx_entry->trace_status = (int8_t) tracestatus;
    1560          205 :     ctx_entry->log_level_changed_callback = dlt_log_level_changed_callback;
    1561              : 
    1562          205 :     log.log_level = loglevel;
    1563          205 :     log.trace_status = tracestatus;
    1564              : 
    1565          205 :     dlt_user.dlt_ll_ts_num_entries++;
    1566              : 
    1567          205 :     DLT_SEM_FREE();
    1568              : 
    1569          205 :     return dlt_user_log_send_register_context(&log);
    1570              : }
    1571              : 
    1572          216 : DltReturnValue dlt_register_context_ll_ts(DltContext *handle,
    1573              :                                           const char *contextid,
    1574              :                                           const char *description,
    1575              :                                           int loglevel,
    1576              :                                           int tracestatus)
    1577              : {
    1578          216 :     return dlt_register_context_ll_ts_llccb(handle,
    1579              :                                             contextid,
    1580              :                                             description,
    1581              :                                             loglevel,
    1582              :                                             tracestatus,
    1583              :                                             NULL);
    1584              : 
    1585              : }
    1586              : 
    1587            0 : DltReturnValue dlt_register_context_llccb(DltContext *handle,
    1588              :                                           const char *contextid,
    1589              :                                           const char *description,
    1590              :                                           void (*dlt_log_level_changed_callback)(char context_id[DLT_ID_SIZE],
    1591              :                                                                                  uint8_t log_level,
    1592              :                                                                                  uint8_t trace_status))
    1593              : {
    1594            0 :     if ((handle == NULL) || (contextid == NULL) || (contextid[0] == '\0'))
    1595              :         return DLT_RETURN_WRONG_PARAMETER;
    1596              : 
    1597              :     /* forbid dlt usage in child after fork */
    1598            0 :     if (g_dlt_is_child)
    1599              :         return DLT_RETURN_ERROR;
    1600              : 
    1601            0 :     if (!DLT_USER_INITIALIZED) {
    1602            0 :         if (dlt_init() < 0) {
    1603            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    1604            0 :             return DLT_RETURN_ERROR;
    1605              :         }
    1606              :     }
    1607              : 
    1608            0 :     return dlt_register_context_ll_ts_llccb(handle,
    1609              :                                             contextid,
    1610              :                                             description,
    1611              :                                             DLT_USER_LOG_LEVEL_NOT_SET,
    1612              :                                             DLT_USER_TRACE_STATUS_NOT_SET,
    1613              :                                             dlt_log_level_changed_callback);
    1614              : }
    1615              : 
    1616              : /* If force_sending_messages is set to true, do not clean appIDs when there are
    1617              :  * still data in startup_buffer. atexit_handler will free the appIDs */
    1618          181 : DltReturnValue dlt_unregister_app_util(bool force_sending_messages)
    1619              : {
    1620              :     DltReturnValue ret = DLT_RETURN_OK;
    1621              : 
    1622              :     /* forbid dlt usage in child after fork */
    1623          181 :     if (g_dlt_is_child) {
    1624              :         return DLT_RETURN_ERROR;
    1625              :     }
    1626              : 
    1627          181 :     if (!DLT_USER_INITIALIZED) {
    1628            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    1629            0 :         return DLT_RETURN_ERROR;
    1630              :     }
    1631              : 
    1632              :     /* Inform daemon to unregister application and all of its contexts */
    1633          181 :     ret = dlt_user_log_send_unregister_application();
    1634              : 
    1635          181 :     DLT_SEM_LOCK();
    1636              : 
    1637          181 :     int count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    1638              : 
    1639          181 :     if (!force_sending_messages ||
    1640            7 :         (force_sending_messages && (count == 0))) {
    1641              :         /* Clear and free local stored application information */
    1642          180 :         dlt_set_id(dlt_user.appID, "");
    1643              : 
    1644          180 :         if (dlt_user.application_description != NULL) {
    1645          171 :             free(dlt_user.application_description);
    1646              :         }
    1647              : 
    1648          180 :         dlt_user.application_description = NULL;
    1649              :     }
    1650              : 
    1651          181 :     DLT_SEM_FREE();
    1652              : 
    1653              :     return ret;
    1654              : }
    1655              : 
    1656          167 : DltReturnValue dlt_unregister_app(void)
    1657              : {
    1658          167 :     return dlt_unregister_app_util(false);
    1659              : }
    1660              : 
    1661            7 : DltReturnValue dlt_unregister_app_flush_buffered_logs(void)
    1662              : {
    1663              :     DltReturnValue ret = DLT_RETURN_OK;
    1664              : 
    1665              :     /* forbid dlt usage in child after fork */
    1666            7 :     if (g_dlt_is_child)
    1667              :         return DLT_RETURN_ERROR;
    1668              : 
    1669            7 :     if (!DLT_USER_INITIALIZED) {
    1670            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    1671            0 :         return DLT_RETURN_ERROR;
    1672              :     }
    1673              : 
    1674            7 :     if (dlt_user.dlt_log_handle != -1) {
    1675              :         do
    1676            6 :             ret = dlt_user_log_resend_buffer();
    1677            6 :         while ((ret != DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1));
    1678              :     }
    1679              : 
    1680            7 :     return dlt_unregister_app_util(true);
    1681              : }
    1682              : 
    1683          204 : DltReturnValue dlt_unregister_context(DltContext *handle)
    1684              : {
    1685              :     DltContextData log;
    1686              :     DltReturnValue ret = DLT_RETURN_OK;
    1687              : 
    1688              :     /* forbid dlt usage in child after fork */
    1689          204 :     if (g_dlt_is_child) {
    1690              :         return DLT_RETURN_ERROR;
    1691              :     }
    1692              : 
    1693          204 :     log.handle = NULL;
    1694          204 :     log.context_description = NULL;
    1695              : 
    1696          204 :     if (dlt_user_log_init(handle, &log) <= DLT_RETURN_ERROR) {
    1697              :         return DLT_RETURN_ERROR;
    1698              :     }
    1699              : 
    1700          204 :     DLT_SEM_LOCK();
    1701              : 
    1702          204 :     handle->log_level_ptr = NULL;
    1703          204 :     handle->trace_status_ptr = NULL;
    1704              : 
    1705          204 :     if (dlt_user.dlt_ll_ts != NULL) {
    1706              :         /* Clear and free local stored context information */
    1707          204 :         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
    1708              : 
    1709          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
    1710          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
    1711              : 
    1712          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description != NULL) {
    1713          204 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
    1714              :         }
    1715              : 
    1716          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr != NULL) {
    1717          204 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
    1718          204 :             dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = NULL;
    1719              :         }
    1720              : 
    1721          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr != NULL) {
    1722          204 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
    1723          204 :             dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = NULL;
    1724              :         }
    1725              : 
    1726          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = NULL;
    1727              : 
    1728          204 :         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table != NULL) {
    1729            0 :             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
    1730            0 :             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = NULL;
    1731              :         }
    1732              : 
    1733          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0;
    1734          204 :         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_changed_callback = 0;
    1735              :     }
    1736              : 
    1737          204 :     DLT_SEM_FREE();
    1738              : 
    1739              :     /* Inform daemon to unregister context */
    1740          204 :     ret = dlt_user_log_send_unregister_context(&log);
    1741              : 
    1742          204 :     return ret;
    1743              : }
    1744              : 
    1745            0 : DltReturnValue dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
    1746              : {
    1747              :     uint32_t i;
    1748              : 
    1749              :     /* forbid dlt usage in child after fork */
    1750            0 :     if (g_dlt_is_child)
    1751              :         return DLT_RETURN_ERROR;
    1752              : 
    1753            0 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    1754            0 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    1755            0 :         return DLT_RETURN_WRONG_PARAMETER;
    1756              :     }
    1757              : 
    1758            0 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    1759            0 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    1760            0 :         return DLT_RETURN_WRONG_PARAMETER;
    1761              :     }
    1762              : 
    1763            0 :     if (!DLT_USER_INITIALIZED) {
    1764            0 :         if (dlt_init() < 0) {
    1765            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    1766            0 :             return DLT_RETURN_ERROR;
    1767              :         }
    1768              :     }
    1769              : 
    1770            0 :     DLT_SEM_LOCK();
    1771              : 
    1772            0 :     if (dlt_user.dlt_ll_ts == NULL) {
    1773            0 :         DLT_SEM_FREE();
    1774            0 :         return DLT_RETURN_ERROR;
    1775              :     }
    1776              : 
    1777              :     /* Update local structures */
    1778            0 :     for (i = 0; i < dlt_user.dlt_ll_ts_num_entries; i++) {
    1779            0 :         dlt_user.dlt_ll_ts[i].log_level = loglevel;
    1780            0 :         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
    1781              : 
    1782            0 :         if (dlt_user.dlt_ll_ts[i].log_level_ptr)
    1783            0 :             *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
    1784              : 
    1785            0 :         if (dlt_user.dlt_ll_ts[i].trace_status_ptr)
    1786            0 :             *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
    1787              :     }
    1788              : 
    1789            0 :     DLT_SEM_FREE();
    1790              : 
    1791              :     /* Inform DLT server about update */
    1792            0 :     return dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
    1793              : }
    1794              : 
    1795            1 : int dlt_get_log_state()
    1796              : {
    1797            1 :     return dlt_user.log_state;
    1798              : }
    1799              : 
    1800            4 : DltReturnValue dlt_set_log_mode(DltUserLogMode mode)
    1801              : {
    1802              :     DLT_UNUSED(mode);
    1803              : 
    1804              :     /* forbid dlt usage in child after fork */
    1805            4 :     if (g_dlt_is_child)
    1806              :         return DLT_RETURN_ERROR;
    1807              : 
    1808            4 :     if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) {
    1809            0 :         dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode);
    1810            0 :         return DLT_RETURN_WRONG_PARAMETER;
    1811              :     }
    1812              : 
    1813            4 :     if (!DLT_USER_INITIALIZED) {
    1814            0 :         if (dlt_init() < 0) {
    1815            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    1816            0 :             return DLT_RETURN_ERROR;
    1817              :         }
    1818              :     }
    1819              : 
    1820            4 :     return dlt_user_log_send_log_mode(mode);
    1821              : }
    1822              : 
    1823            0 : int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds)
    1824              : {
    1825              :     /* forbid dlt usage in child after fork */
    1826            0 :     if (g_dlt_is_child)
    1827              :         return DLT_RETURN_ERROR;
    1828              : 
    1829            0 :     if (DLT_USER_INITIALIZED == 0)
    1830            0 :         if (dlt_init() < 0)
    1831              :             return -1;
    1832              : 
    1833            0 :     dlt_user.timeout_at_exit_handler = timeout_in_milliseconds * 10;
    1834            0 :     return 0;
    1835              : }
    1836              : 
    1837              : /* ********************************************************************************************* */
    1838              : 
    1839         6001 : DltReturnValue dlt_user_log_write_start_init(DltContext *handle,
    1840              :                                                     DltContextData *log,
    1841              :                                                     DltLogLevelType loglevel,
    1842              :                                                     bool is_verbose)
    1843              : {
    1844              :     DLT_LOG_FATAL_RESET_TRAP(loglevel);
    1845              : 
    1846              :     /* initialize values */
    1847         6001 :     if ((dlt_user_log_init(handle, log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL))
    1848              :         return DLT_RETURN_ERROR;
    1849              : 
    1850         6001 :     log->args_num = 0;
    1851         6001 :     log->log_level = loglevel;
    1852         6001 :     log->size = 0;
    1853         6001 :     log->use_timestamp = DLT_AUTO_TIMESTAMP;
    1854         6001 :     log->verbose_mode = is_verbose;
    1855              : 
    1856         6001 :     return DLT_RETURN_TRUE;
    1857              : }
    1858              : 
    1859              : static DltReturnValue dlt_user_log_write_start_internal(DltContext *handle,
    1860              :                                                         DltContextData *log,
    1861              :                                                         DltLogLevelType loglevel,
    1862              :                                                         uint32_t messageid,
    1863              :                                                         bool is_verbose);
    1864              : 
    1865         5926 : inline DltReturnValue dlt_user_log_write_start(DltContext *handle, DltContextData *log, DltLogLevelType loglevel)
    1866              : {
    1867         6036 :     return dlt_user_log_write_start_internal(handle, log, loglevel, DLT_USER_DEFAULT_MSGID, true);
    1868              : }
    1869              : 
    1870           23 : DltReturnValue dlt_user_log_write_start_id(DltContext *handle,
    1871              :                                            DltContextData *log,
    1872              :                                            DltLogLevelType loglevel,
    1873              :                                            uint32_t messageid)
    1874              : {
    1875           23 :     return dlt_user_log_write_start_internal(handle, log, loglevel, messageid, false);
    1876              : }
    1877              : 
    1878         6059 : DltReturnValue dlt_user_log_write_start_internal(DltContext *handle,
    1879              :                                            DltContextData *log,
    1880              :                                            DltLogLevelType loglevel,
    1881              :                                            uint32_t messageid,
    1882              :                                            bool is_verbose)
    1883              : {
    1884              :     int ret = DLT_RETURN_TRUE;
    1885              : 
    1886              :     /* check nullpointer */
    1887         6059 :     if ((handle == NULL) || (log == NULL))
    1888              :         return DLT_RETURN_WRONG_PARAMETER;
    1889              : 
    1890              :     /* forbid dlt usage in child after fork */
    1891         6053 :     if (g_dlt_is_child)
    1892              :         return DLT_RETURN_ERROR;
    1893              : 
    1894              :     /* check log levels */
    1895              :     ret = dlt_user_is_logLevel_enabled(handle, loglevel);
    1896              : 
    1897              :     if (ret == DLT_RETURN_WRONG_PARAMETER) {
    1898              :         return DLT_RETURN_WRONG_PARAMETER;
    1899         6040 :     } else if (ret == DLT_RETURN_LOGGING_DISABLED) {
    1900           39 :         log->handle = NULL;
    1901           39 :         return DLT_RETURN_OK;
    1902              :     }
    1903              : 
    1904         6001 :     ret = dlt_user_log_write_start_init(handle, log, loglevel, is_verbose);
    1905         6001 :     if (ret == DLT_RETURN_TRUE) {
    1906              :         /* initialize values */
    1907         6001 :         if ((NULL != log->buffer))
    1908              :         {
    1909            0 :             free(log->buffer);
    1910            0 :             log->buffer = NULL;
    1911              :         }
    1912              :         else
    1913              :         {
    1914         6001 :             log->buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len);
    1915              :         }
    1916              : 
    1917         6001 :         if (log->buffer == NULL) {
    1918            0 :             dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    1919            0 :             return DLT_RETURN_ERROR;
    1920              :         }
    1921              :         else
    1922              :         {
    1923              :             /* In non-verbose mode, insert message id */
    1924        12002 :             if (!is_verbose_mode(dlt_user.verbose_mode, log)) {
    1925            3 :                 if ((sizeof(uint32_t)) > dlt_user.log_buf_len)
    1926              :                     return DLT_RETURN_USER_BUFFER_FULL;
    1927              : 
    1928              :                 /* Write message id */
    1929              :                 memcpy(log->buffer, &(messageid), sizeof(uint32_t));
    1930            3 :                 log->size = sizeof(uint32_t);
    1931              : 
    1932              :                 /* as the message id is part of each message in non-verbose mode,
    1933              :                 * it doesn't increment the argument counter in extended header (if used) */
    1934              :             }
    1935              :         }
    1936              :     }
    1937              : 
    1938              :     return ret;
    1939              : }
    1940              : 
    1941            0 : DltReturnValue dlt_user_log_write_start_w_given_buffer(DltContext *handle,
    1942              :                                                        DltContextData *log,
    1943              :                                                        DltLogLevelType loglevel,
    1944              :                                                        char *buffer,
    1945              :                                                        size_t size,
    1946              :                                                        int32_t args_num)
    1947              : {
    1948              :     int ret = DLT_RETURN_TRUE;
    1949              : 
    1950              :     /* check nullpointer */
    1951            0 :     if ((handle == NULL) || (log == NULL) || (buffer == NULL))
    1952              :         return DLT_RETURN_WRONG_PARAMETER;
    1953              : 
    1954              :     /* discard unexpected parameters */
    1955            0 :     if ((size <= 0) || (size > dlt_user.log_buf_len) || (args_num <= 0))
    1956              :         return DLT_RETURN_WRONG_PARAMETER;
    1957              : 
    1958              :     /* forbid dlt usage in child after fork */
    1959            0 :     if (g_dlt_is_child)
    1960              :         return DLT_RETURN_ERROR;
    1961              : 
    1962              :     /* discard non-verbose mode */
    1963            0 :     if (dlt_user.verbose_mode == 0)
    1964              :         return DLT_RETURN_ERROR;
    1965              : 
    1966            0 :     ret = dlt_user_log_write_start_init(handle, log, loglevel, true);
    1967            0 :     if (ret == DLT_RETURN_TRUE) {
    1968            0 :         log->buffer = (unsigned char *)buffer;
    1969            0 :         log->size = size;
    1970            0 :         log->args_num = args_num;
    1971              :     }
    1972              : 
    1973              :     return ret;
    1974              :  }
    1975              : 
    1976         6008 : DltReturnValue dlt_user_log_write_finish(DltContextData *log)
    1977              : {
    1978              :     int ret = DLT_RETURN_ERROR;
    1979              : 
    1980         6008 :     if (log == NULL)
    1981              :         return DLT_RETURN_WRONG_PARAMETER;
    1982              : 
    1983         6008 :     ret = dlt_user_log_send_log(log, DLT_TYPE_LOG, NULL);
    1984              : 
    1985              :     dlt_user_free_buffer(&(log->buffer));
    1986              : 
    1987              :     return ret;
    1988              : }
    1989              : 
    1990            0 : DltReturnValue dlt_user_log_write_finish_w_given_buffer(DltContextData *log)
    1991              : {
    1992              :     int ret = DLT_RETURN_ERROR;
    1993              : 
    1994            0 :     if (log == NULL)
    1995              :         return DLT_RETURN_WRONG_PARAMETER;
    1996              : 
    1997            0 :     ret = dlt_user_log_send_log(log, DLT_TYPE_LOG, NULL);
    1998              : 
    1999            0 :     return ret;
    2000              : }
    2001              : 
    2002           38 : static DltReturnValue dlt_user_log_write_raw_internal(DltContextData *log, const void *data, uint16_t length, DltFormatType type, const char *name, bool with_var_info)
    2003              : {
    2004              :     /* check nullpointer */
    2005           38 :     if ((log == NULL) || ((data == NULL) && (length != 0)))
    2006              :         return DLT_RETURN_WRONG_PARAMETER;
    2007              : 
    2008              :     /* Have to cast type to signed type because some compilers assume that DltFormatType is unsigned and issue a warning */
    2009           31 :     if (((int16_t)type < DLT_FORMAT_DEFAULT) || (type >= DLT_FORMAT_MAX)) {
    2010            0 :         dlt_vlog(LOG_ERR, "Format type %u is outside valid range", type);
    2011            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2012              :     }
    2013              : 
    2014           31 :     if (!DLT_USER_INITIALIZED) {
    2015            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    2016            0 :         return DLT_RETURN_ERROR;
    2017              :     }
    2018              : 
    2019           31 :     const uint16_t name_size = (name != NULL) ? strlen(name)+1 : 0;
    2020              : 
    2021           31 :     size_t needed_size = length + sizeof(uint16_t);
    2022           31 :     if ((log->size + needed_size) > dlt_user.log_buf_len)
    2023              :         return DLT_RETURN_USER_BUFFER_FULL;
    2024              : 
    2025           29 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2026           29 :         uint32_t type_info = DLT_TYPE_INFO_RAWD;
    2027              : 
    2028           29 :         needed_size += sizeof(uint32_t);  // Type Info field
    2029           29 :         if (with_var_info) {
    2030            6 :             needed_size += sizeof(uint16_t);  // length of name
    2031            6 :             needed_size += name_size;  // the name itself
    2032              : 
    2033            6 :             type_info |= DLT_TYPE_INFO_VARI;
    2034              :         }
    2035           29 :         if ((log->size + needed_size) > dlt_user.log_buf_len)
    2036            0 :             return DLT_RETURN_USER_BUFFER_FULL;
    2037              : 
    2038              :         // Genivi extension: put formatting hints into the unused (for RAWD) TYLE + SCOD fields.
    2039              :         // The SCOD field holds the base (hex or bin); the TYLE field holds the column width (8bit..64bit).
    2040           29 :         if ((type >= DLT_FORMAT_HEX8) && (type <= DLT_FORMAT_HEX64)) {
    2041            8 :             type_info |= DLT_SCOD_HEX;
    2042            8 :             type_info += type;
    2043              :         }
    2044           21 :         else if ((type >= DLT_FORMAT_BIN8) && (type <= DLT_FORMAT_BIN16))
    2045              :         {
    2046            4 :             type_info |= DLT_SCOD_BIN;
    2047            4 :             type_info += type - DLT_FORMAT_BIN8 + 1;
    2048              :         }
    2049              : 
    2050           29 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2051           29 :         log->size += sizeof(uint32_t);
    2052              :     }
    2053              : 
    2054           29 :     memcpy(log->buffer + log->size, &length, sizeof(uint16_t));
    2055           29 :     log->size += sizeof(uint16_t);
    2056              : 
    2057           29 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2058           29 :         if (with_var_info) {
    2059              :             // Write length of "name" attribute.
    2060              :             // We assume that the protocol allows zero-sized strings here (which this code will create
    2061              :             // when the input pointer is NULL).
    2062            6 :             memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t));
    2063            6 :             log->size += sizeof(uint16_t);
    2064              : 
    2065              :             // Write name string itself.
    2066              :             // Must not use NULL as source pointer for memcpy. This check assures that.
    2067            6 :             if (name_size != 0) {
    2068            4 :                 memcpy(log->buffer + log->size, name, name_size);
    2069            4 :                 log->size += name_size;
    2070              :             }
    2071              :         }
    2072              :     }
    2073              : 
    2074           29 :     if (data != NULL) {
    2075           27 :         memcpy(log->buffer + log->size, data, length);
    2076           27 :         log->size += length;
    2077           27 :         log->args_num++;
    2078              :     }
    2079              : 
    2080              :     return DLT_RETURN_OK;
    2081              : }
    2082              : 
    2083           13 : DltReturnValue dlt_user_log_write_raw(DltContextData *log, void *data, uint16_t length)
    2084              : {
    2085           13 :     return dlt_user_log_write_raw_internal(log, data, length, DLT_FORMAT_DEFAULT, NULL, false);
    2086              : }
    2087              : 
    2088           19 : DltReturnValue dlt_user_log_write_raw_formatted(DltContextData *log, void *data, uint16_t length, DltFormatType type)
    2089              : {
    2090           19 :     return dlt_user_log_write_raw_internal(log, data, length, type, NULL, false);
    2091              : }
    2092              : 
    2093            3 : DltReturnValue dlt_user_log_write_raw_attr(DltContextData *log, const void *data, uint16_t length, const char *name)
    2094              : {
    2095            3 :     return dlt_user_log_write_raw_internal(log, data, length, DLT_FORMAT_DEFAULT, name, true);
    2096              : }
    2097              : 
    2098            3 : DltReturnValue dlt_user_log_write_raw_formatted_attr(DltContextData *log, const void *data, uint16_t length, DltFormatType type, const char *name)
    2099              : {
    2100            3 :     return dlt_user_log_write_raw_internal(log, data, length, type, name, true);
    2101              : }
    2102              : 
    2103              : // Generic implementation for all "simple" types, possibly with attributes
    2104        11760 : static DltReturnValue dlt_user_log_write_generic_attr(DltContextData *log, const void *datap, size_t datalen, uint32_t type_info, const VarInfo *varinfo)
    2105              : {
    2106        11760 :     if (log == NULL)
    2107              :         return DLT_RETURN_WRONG_PARAMETER;
    2108              : 
    2109        11749 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2110            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    2111            0 :         return DLT_RETURN_ERROR;
    2112              :     }
    2113              : 
    2114              :     size_t needed_size = datalen;
    2115        11749 :     if ((log->size + needed_size) > dlt_user.log_buf_len)
    2116              :         return DLT_RETURN_USER_BUFFER_FULL;
    2117              : 
    2118        11747 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2119              :         bool with_var_info = (varinfo != NULL);
    2120              : 
    2121              :         uint16_t name_size;
    2122              :         uint16_t unit_size;
    2123              : 
    2124        11745 :         needed_size += sizeof(uint32_t);  // Type Info field
    2125        11745 :         if (with_var_info) {
    2126           89 :             name_size = (varinfo->name != NULL) ? strlen(varinfo->name)+1 : 0;
    2127           89 :             unit_size = (varinfo->unit != NULL) ? strlen(varinfo->unit)+1 : 0;
    2128              : 
    2129           89 :             needed_size += sizeof(uint16_t);      // length of name
    2130           89 :             needed_size += name_size;             // the name itself
    2131           89 :             if (varinfo->with_unit) {
    2132           86 :                 needed_size += sizeof(uint16_t);  // length of unit
    2133           86 :                 needed_size += unit_size;         // the unit itself
    2134              :             }
    2135              : 
    2136           89 :             type_info |= DLT_TYPE_INFO_VARI;
    2137              :         }
    2138        11745 :         if ((log->size + needed_size) > dlt_user.log_buf_len)
    2139            0 :             return DLT_RETURN_USER_BUFFER_FULL;
    2140              : 
    2141        11745 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2142        11745 :         log->size += sizeof(uint32_t);
    2143              : 
    2144        11745 :         if (with_var_info) {
    2145              :             // Write lengths of name/unit strings
    2146              :             // We assume here that the protocol allows zero-sized strings here (which occur
    2147              :             // when the input pointers are NULL).
    2148           89 :             memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t));
    2149           89 :             log->size += sizeof(uint16_t);
    2150           89 :             if (varinfo->with_unit) {
    2151           86 :                 memcpy(log->buffer + log->size, &unit_size, sizeof(uint16_t));
    2152           86 :                 log->size += sizeof(uint16_t);
    2153              :             }
    2154              : 
    2155              :             // Write name/unit strings themselves
    2156              :             // Must not use NULL as source pointer for memcpy.
    2157           89 :             if (name_size != 0) {
    2158           64 :                 memcpy(log->buffer + log->size, varinfo->name, name_size);
    2159           64 :                 log->size += name_size;
    2160              :             }
    2161           89 :             if (unit_size != 0) {
    2162           62 :                 memcpy(log->buffer + log->size, varinfo->unit, unit_size);
    2163           62 :                 log->size += unit_size;
    2164              :             }
    2165              :         }
    2166              :     }
    2167              : 
    2168        11747 :     memcpy(log->buffer + log->size, datap, datalen);
    2169        11747 :     log->size += datalen;
    2170              : 
    2171        11747 :     log->args_num++;
    2172              : 
    2173        11747 :     return DLT_RETURN_OK;
    2174              : }
    2175              : 
    2176              : // Generic implementation for all "simple" types
    2177          112 : static DltReturnValue dlt_user_log_write_generic_formatted(DltContextData *log, const void *datap, size_t datalen, uint32_t type_info, DltFormatType type)
    2178              : {
    2179          112 :     if (log == NULL)
    2180              :         return DLT_RETURN_WRONG_PARAMETER;
    2181              : 
    2182              :     /* Have to cast type to signed type because some compilers assume that DltFormatType is unsigned and issue a warning */
    2183           84 :     if (((int16_t)type < DLT_FORMAT_DEFAULT) || (type >= DLT_FORMAT_MAX)) {
    2184            0 :         dlt_vlog(LOG_ERR, "Format type %d is outside valid range", type);
    2185            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2186              :     }
    2187              : 
    2188           84 :     if (!DLT_USER_INITIALIZED) {
    2189            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    2190            0 :         return DLT_RETURN_ERROR;
    2191              :     }
    2192              : 
    2193              :     size_t needed_size = datalen;
    2194           84 :     if ((log->size + needed_size) > dlt_user.log_buf_len)
    2195              :         return DLT_RETURN_USER_BUFFER_FULL;
    2196              : 
    2197           84 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2198           84 :         needed_size += sizeof(uint32_t);  // Type Info field
    2199           84 :         if ((log->size + needed_size) > dlt_user.log_buf_len)
    2200              :             return DLT_RETURN_USER_BUFFER_FULL;
    2201              : 
    2202              :         // Genivi extension: put formatting hints into the unused (for SINT/UINT/FLOA) SCOD field.
    2203           84 :         if ((type >= DLT_FORMAT_HEX8) && (type <= DLT_FORMAT_HEX64))
    2204           48 :             type_info |= DLT_SCOD_HEX;
    2205              : 
    2206           36 :         else if ((type >= DLT_FORMAT_BIN8) && (type <= DLT_FORMAT_BIN16))
    2207           24 :             type_info |= DLT_SCOD_BIN;
    2208              : 
    2209           84 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2210           84 :         log->size += sizeof(uint32_t);
    2211              :     }
    2212              : 
    2213           84 :     memcpy(log->buffer + log->size, datap, datalen);
    2214           84 :     log->size += datalen;
    2215              : 
    2216           84 :     log->args_num++;
    2217              : 
    2218           84 :     return DLT_RETURN_OK;
    2219              : }
    2220              : 
    2221            7 : DltReturnValue dlt_user_log_write_float32(DltContextData *log, float32_t data)
    2222              : {
    2223              :     if (sizeof(float32_t) != 4)
    2224              :         return DLT_RETURN_ERROR;
    2225              : 
    2226              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
    2227            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float32_t), type_info, NULL);
    2228              : }
    2229              : 
    2230            7 : DltReturnValue dlt_user_log_write_float64(DltContextData *log, float64_t data)
    2231              : {
    2232              :     if (sizeof(float64_t) != 8)
    2233              :         return DLT_RETURN_ERROR;
    2234              : 
    2235              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
    2236            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float64_t), type_info, NULL);
    2237              : }
    2238              : 
    2239            7 : DltReturnValue dlt_user_log_write_float32_attr(DltContextData *log, float32_t data, const char *name, const char *unit)
    2240              : {
    2241              :     if (sizeof(float32_t) != 4)
    2242              :         return DLT_RETURN_ERROR;
    2243              : 
    2244              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
    2245            7 :     const VarInfo var_info = { name, unit, true };
    2246            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float32_t), type_info, &var_info);
    2247              : }
    2248              : 
    2249            7 : DltReturnValue dlt_user_log_write_float64_attr(DltContextData *log, float64_t data, const char *name, const char *unit)
    2250              : {
    2251              :     if (sizeof(float64_t) != 8)
    2252              :         return DLT_RETURN_ERROR;
    2253              : 
    2254              :     uint32_t type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
    2255            7 :     const VarInfo var_info = { name, unit, true };
    2256            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(float64_t), type_info, &var_info);
    2257              : }
    2258              : 
    2259           35 : DltReturnValue dlt_user_log_write_uint(DltContextData *log, unsigned int data)
    2260              : {
    2261           35 :     if (log == NULL)
    2262              :         return DLT_RETURN_WRONG_PARAMETER;
    2263              : 
    2264           34 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2265            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    2266            0 :         return DLT_RETURN_ERROR;
    2267              :     }
    2268              : 
    2269              :     switch (sizeof(unsigned int)) {
    2270              :     case 1:
    2271              :     {
    2272              :         return dlt_user_log_write_uint8(log, (uint8_t)data);
    2273              :         break;
    2274              :     }
    2275              :     case 2:
    2276              :     {
    2277              :         return dlt_user_log_write_uint16(log, (uint16_t)data);
    2278              :         break;
    2279              :     }
    2280           34 :     case 4:
    2281              :     {
    2282           34 :         return dlt_user_log_write_uint32(log, (uint32_t)data);
    2283              :         break;
    2284              :     }
    2285              :     case 8:
    2286              :     {
    2287              :         return dlt_user_log_write_uint64(log, (uint64_t)data);
    2288              :         break;
    2289              :     }
    2290              :     default:
    2291              :     {
    2292              :         return DLT_RETURN_ERROR;
    2293              :         break;
    2294              :     }
    2295              :     }
    2296              : 
    2297              :     return DLT_RETURN_OK;
    2298              : }
    2299              : 
    2300            4 : DltReturnValue dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
    2301              : {
    2302              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
    2303            4 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, NULL);
    2304              : }
    2305              : 
    2306            4 : DltReturnValue dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
    2307              : {
    2308              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
    2309            4 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint16_t), type_info, NULL);
    2310              : }
    2311              : 
    2312        11580 : DltReturnValue dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
    2313              : {
    2314              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
    2315        11580 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint32_t), type_info, NULL);
    2316              : }
    2317              : 
    2318            4 : DltReturnValue dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
    2319              : {
    2320              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
    2321            4 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint64_t), type_info, NULL);
    2322              : }
    2323              : 
    2324            7 : DltReturnValue dlt_user_log_write_uint_attr(DltContextData *log, unsigned int data, const char *name, const char *unit)
    2325              : {
    2326            7 :     if (log == NULL)
    2327              :         return DLT_RETURN_WRONG_PARAMETER;
    2328              : 
    2329            7 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2330            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__);
    2331            0 :         return DLT_RETURN_ERROR;
    2332              :     }
    2333              : 
    2334              :     switch (sizeof(unsigned int)) {
    2335              :     case 1:
    2336              :     {
    2337              :         return dlt_user_log_write_uint8_attr(log, (uint8_t)data, name, unit);
    2338              :         break;
    2339              :     }
    2340              :     case 2:
    2341              :     {
    2342              :         return dlt_user_log_write_uint16_attr(log, (uint16_t)data, name, unit);
    2343              :         break;
    2344              :     }
    2345            7 :     case 4:
    2346              :     {
    2347            7 :         return dlt_user_log_write_uint32_attr(log, (uint32_t)data, name, unit);
    2348              :         break;
    2349              :     }
    2350              :     case 8:
    2351              :     {
    2352              :         return dlt_user_log_write_uint64_attr(log, (uint64_t)data, name, unit);
    2353              :         break;
    2354              :     }
    2355              :     default:
    2356              :     {
    2357              :         return DLT_RETURN_ERROR;
    2358              :         break;
    2359              :     }
    2360              :     }
    2361              : 
    2362              :     return DLT_RETURN_OK;
    2363              : }
    2364              : 
    2365            7 : DltReturnValue dlt_user_log_write_uint8_attr(DltContextData *log, uint8_t data, const char *name, const char *unit)
    2366              : {
    2367              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
    2368            7 :     const VarInfo var_info = { name, unit, true };
    2369            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, &var_info);
    2370              : }
    2371              : 
    2372            7 : DltReturnValue dlt_user_log_write_uint16_attr(DltContextData *log, uint16_t data, const char *name, const char *unit)
    2373              : {
    2374              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
    2375            7 :     const VarInfo var_info = { name, unit, true };
    2376            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint16_t), type_info, &var_info);
    2377              : }
    2378              : 
    2379           18 : DltReturnValue dlt_user_log_write_uint32_attr(DltContextData *log, uint32_t data, const char *name, const char *unit)
    2380              : {
    2381              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
    2382           18 :     const VarInfo var_info = { name, unit, true };
    2383           18 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint32_t), type_info, &var_info);
    2384              : }
    2385              : 
    2386            7 : DltReturnValue dlt_user_log_write_uint64_attr(DltContextData *log, uint64_t data, const char *name, const char *unit)
    2387              : {
    2388              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
    2389            7 :     const VarInfo var_info = { name, unit, true };
    2390            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint64_t), type_info, &var_info);
    2391              : }
    2392              : 
    2393           28 : DltReturnValue dlt_user_log_write_uint8_formatted(DltContextData *log, uint8_t data, DltFormatType type)
    2394              : {
    2395              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
    2396           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint8_t), type_info, type);
    2397              : }
    2398              : 
    2399           28 : DltReturnValue dlt_user_log_write_uint16_formatted(DltContextData *log, uint16_t data, DltFormatType type)
    2400              : {
    2401              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
    2402           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint16_t), type_info, type);
    2403              : }
    2404              : 
    2405           28 : DltReturnValue dlt_user_log_write_uint32_formatted(DltContextData *log, uint32_t data, DltFormatType type)
    2406              : {
    2407              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
    2408           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint32_t), type_info, type);
    2409              : }
    2410              : 
    2411           28 : DltReturnValue dlt_user_log_write_uint64_formatted(DltContextData *log, uint64_t data, DltFormatType type)
    2412              : {
    2413              :     uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
    2414           28 :     return dlt_user_log_write_generic_formatted(log, &data, sizeof(uint64_t), type_info, type);
    2415              : }
    2416              : 
    2417            0 : DltReturnValue dlt_user_log_write_ptr(DltContextData *log, void *data)
    2418              : {
    2419            0 :     if (log == NULL)
    2420              :         return DLT_RETURN_WRONG_PARAMETER;
    2421              : 
    2422            0 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2423            0 :         dlt_vlog(LOG_WARNING, "%s user_initialised false\n", __FUNCTION__);
    2424            0 :         return DLT_RETURN_ERROR;
    2425              :     }
    2426              : 
    2427              :     switch (sizeof(void *)) {
    2428              :     case 4:
    2429              :         return dlt_user_log_write_uint32_formatted(log,
    2430              :                                                    (uintptr_t) data,
    2431              :                                                    DLT_FORMAT_HEX32);
    2432              :         break;
    2433            0 :     case 8:
    2434            0 :         return dlt_user_log_write_uint64_formatted(log,
    2435              :                                                    (uintptr_t) data,
    2436              :                                                    DLT_FORMAT_HEX64);
    2437              :         break;
    2438              :     default:
    2439              :         ;     /* skip */
    2440              :     }
    2441              : 
    2442              :     return DLT_RETURN_OK;
    2443              : }
    2444              : 
    2445           37 : DltReturnValue dlt_user_log_write_int(DltContextData *log, int data)
    2446              : {
    2447           37 :     if (log == NULL)
    2448              :         return DLT_RETURN_WRONG_PARAMETER;
    2449              : 
    2450           36 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2451            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    2452            0 :         return DLT_RETURN_ERROR;
    2453              :     }
    2454              : 
    2455              :     switch (sizeof(int)) {
    2456              :     case 1:
    2457              :     {
    2458              :         return dlt_user_log_write_int8(log, (int8_t)data);
    2459              :         break;
    2460              :     }
    2461              :     case 2:
    2462              :     {
    2463              :         return dlt_user_log_write_int16(log, (int16_t)data);
    2464              :         break;
    2465              :     }
    2466           36 :     case 4:
    2467              :     {
    2468           36 :         return dlt_user_log_write_int32(log, (int32_t)data);
    2469              :         break;
    2470              :     }
    2471              :     case 8:
    2472              :     {
    2473              :         return dlt_user_log_write_int64(log, (int64_t)data);
    2474              :         break;
    2475              :     }
    2476              :     default:
    2477              :     {
    2478              :         return DLT_RETURN_ERROR;
    2479              :         break;
    2480              :     }
    2481              :     }
    2482              : 
    2483              :     return DLT_RETURN_OK;
    2484              : }
    2485              : 
    2486            6 : DltReturnValue dlt_user_log_write_int8(DltContextData *log, int8_t data)
    2487              : {
    2488              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
    2489            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int8_t), type_info, NULL);
    2490              : }
    2491              : 
    2492            6 : DltReturnValue dlt_user_log_write_int16(DltContextData *log, int16_t data)
    2493              : {
    2494              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
    2495            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int16_t), type_info, NULL);
    2496              : }
    2497              : 
    2498           42 : DltReturnValue dlt_user_log_write_int32(DltContextData *log, int32_t data)
    2499              : {
    2500              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
    2501           42 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int32_t), type_info, NULL);
    2502              : }
    2503              : 
    2504            6 : DltReturnValue dlt_user_log_write_int64(DltContextData *log, int64_t data)
    2505              : {
    2506              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
    2507            6 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int64_t), type_info, NULL);
    2508              : }
    2509              : 
    2510            7 : DltReturnValue dlt_user_log_write_int_attr(DltContextData *log, int data, const char *name, const char *unit)
    2511              : {
    2512            7 :     if (log == NULL)
    2513              :         return DLT_RETURN_WRONG_PARAMETER;
    2514              : 
    2515            7 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2516            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__);
    2517            0 :         return DLT_RETURN_ERROR;
    2518              :     }
    2519              : 
    2520              :     switch (sizeof(int)) {
    2521              :     case 1:
    2522              :     {
    2523              :         return dlt_user_log_write_int8_attr(log, (int8_t)data, name, unit);
    2524              :         break;
    2525              :     }
    2526              :     case 2:
    2527              :     {
    2528              :         return dlt_user_log_write_int16_attr(log, (int16_t)data, name, unit);
    2529              :         break;
    2530              :     }
    2531            7 :     case 4:
    2532              :     {
    2533            7 :         return dlt_user_log_write_int32_attr(log, (int32_t)data, name, unit);
    2534              :         break;
    2535              :     }
    2536              :     case 8:
    2537              :     {
    2538              :         return dlt_user_log_write_int64_attr(log, (int64_t)data, name, unit);
    2539              :         break;
    2540              :     }
    2541              :     default:
    2542              :     {
    2543              :         return DLT_RETURN_ERROR;
    2544              :         break;
    2545              :     }
    2546              :     }
    2547              : 
    2548              :     return DLT_RETURN_OK;
    2549              : }
    2550              : 
    2551            7 : DltReturnValue dlt_user_log_write_int8_attr(DltContextData *log, int8_t data, const char *name, const char *unit)
    2552              : {
    2553              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
    2554            7 :     const VarInfo var_info = { name, unit, true };
    2555            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int8_t), type_info, &var_info);
    2556              : }
    2557              : 
    2558            7 : DltReturnValue dlt_user_log_write_int16_attr(DltContextData *log, int16_t data, const char *name, const char *unit)
    2559              : {
    2560              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
    2561            7 :     const VarInfo var_info = { name, unit, true };
    2562            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int16_t), type_info, &var_info);
    2563              : }
    2564              : 
    2565           14 : DltReturnValue dlt_user_log_write_int32_attr(DltContextData *log, int32_t data, const char *name, const char *unit)
    2566              : {
    2567              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
    2568           14 :     const VarInfo var_info = { name, unit, true };
    2569           14 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int32_t), type_info, &var_info);
    2570              : }
    2571              : 
    2572            7 : DltReturnValue dlt_user_log_write_int64_attr(DltContextData *log, int64_t data, const char *name, const char *unit)
    2573              : {
    2574              :     uint32_t type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
    2575            7 :     const VarInfo var_info = { name, unit, true };
    2576            7 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(int64_t), type_info, &var_info);
    2577              : }
    2578              : 
    2579            3 : DltReturnValue dlt_user_log_write_bool(DltContextData *log, uint8_t data)
    2580              : {
    2581              :     uint32_t type_info = DLT_TYPE_INFO_BOOL | DLT_TYLE_8BIT;
    2582            3 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, NULL);
    2583              : }
    2584              : 
    2585            3 : DltReturnValue dlt_user_log_write_bool_attr(DltContextData *log, uint8_t data, const char *name)
    2586              : {
    2587              :     uint32_t type_info = DLT_TYPE_INFO_BOOL | DLT_TYLE_8BIT;
    2588            3 :     const VarInfo var_info = { name, NULL, false };
    2589            3 :     return dlt_user_log_write_generic_attr(log, &data, sizeof(uint8_t), type_info, &var_info);
    2590              : }
    2591              : 
    2592        11686 : DltReturnValue dlt_user_log_write_string(DltContextData *log, const char *text)
    2593              : {
    2594        11686 :     return dlt_user_log_write_string_utils_attr(log, text, ASCII_STRING, NULL, false);
    2595              : }
    2596              : 
    2597            7 : DltReturnValue dlt_user_log_write_string_attr(DltContextData *log, const char *text, const char *name)
    2598              : {
    2599            7 :     return dlt_user_log_write_string_utils_attr(log, text, ASCII_STRING, name, true);
    2600              : }
    2601              : 
    2602            2 : DltReturnValue dlt_user_log_write_sized_string(DltContextData *log, const char *text, uint16_t length)
    2603              : {
    2604            2 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, ASCII_STRING, NULL, false);
    2605              : }
    2606              : 
    2607            6 : DltReturnValue dlt_user_log_write_sized_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name)
    2608              : {
    2609            6 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, ASCII_STRING, name, true);
    2610              : }
    2611              : 
    2612            7 : DltReturnValue dlt_user_log_write_constant_string(DltContextData *log, const char *text)
    2613              : {
    2614              :     /* Send parameter only in verbose mode */
    2615            8 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_string(log, text) : DLT_RETURN_OK;
    2616              : }
    2617              : 
    2618            5 : DltReturnValue dlt_user_log_write_constant_string_attr(DltContextData *log, const char *text, const char *name)
    2619              : {
    2620              :     /* Send parameter only in verbose mode */
    2621            6 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_string_attr(log, text, name) : DLT_RETURN_OK;
    2622              : }
    2623              : 
    2624            1 : DltReturnValue dlt_user_log_write_sized_constant_string(DltContextData *log, const char *text, uint16_t length)
    2625              : {
    2626              :     /* Send parameter only in verbose mode */
    2627            1 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_string(log, text, length) : DLT_RETURN_OK;
    2628              : }
    2629              : 
    2630            3 : DltReturnValue dlt_user_log_write_sized_constant_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name)
    2631              : {
    2632              :     /* Send parameter only in verbose mode */
    2633            3 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_string_attr(log, text, length, name) : DLT_RETURN_OK;
    2634              : }
    2635              : 
    2636           21 : DltReturnValue dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
    2637              : {
    2638           21 :     return dlt_user_log_write_string_utils_attr(log, text, UTF8_STRING, NULL, false);
    2639              : }
    2640              : 
    2641            7 : DltReturnValue dlt_user_log_write_utf8_string_attr(DltContextData *log, const char *text, const char *name)
    2642              : {
    2643            7 :     return dlt_user_log_write_string_utils_attr(log, text, UTF8_STRING, name, true);
    2644              : }
    2645              : 
    2646            8 : DltReturnValue dlt_user_log_write_sized_utf8_string(DltContextData *log, const char *text, uint16_t length)
    2647              : {
    2648            8 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, UTF8_STRING, NULL, false);
    2649              : }
    2650              : 
    2651            7 : DltReturnValue dlt_user_log_write_sized_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name)
    2652              : {
    2653            7 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, UTF8_STRING, name, true);
    2654              : }
    2655              : 
    2656            5 : DltReturnValue dlt_user_log_write_constant_utf8_string(DltContextData *log, const char *text)
    2657              : {
    2658              :     /* Send parameter only in verbose mode */
    2659            5 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_utf8_string(log, text) : DLT_RETURN_OK;
    2660              : }
    2661              : 
    2662            4 : DltReturnValue dlt_user_log_write_constant_utf8_string_attr(DltContextData *log, const char *text, const char *name)
    2663              : {
    2664              :     /* Send parameter only in verbose mode */
    2665            4 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_utf8_string_attr(log, text, name) : DLT_RETURN_OK;
    2666              : }
    2667              : 
    2668            5 : DltReturnValue dlt_user_log_write_sized_constant_utf8_string(DltContextData *log, const char *text, uint16_t length)
    2669              : {
    2670              :     /* Send parameter only in verbose mode */
    2671            5 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_utf8_string(log, text, length) : DLT_RETURN_OK;
    2672              : }
    2673              : 
    2674            4 : DltReturnValue dlt_user_log_write_sized_constant_utf8_string_attr(DltContextData *log, const char *text, uint16_t length, const char *name)
    2675              : {
    2676              :     /* Send parameter only in verbose mode */
    2677            4 :     return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_utf8_string_attr(log, text, length, name) : DLT_RETURN_OK;
    2678              : }
    2679              : 
    2680        11729 : static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, size_t length, const enum StringType type, const char *name, bool with_var_info)
    2681              : {
    2682        11729 :     if ((log == NULL) || (text == NULL))
    2683              :         return DLT_RETURN_WRONG_PARAMETER;
    2684              : 
    2685        11720 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    2686            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    2687            0 :         return DLT_RETURN_ERROR;
    2688              :     }
    2689              : 
    2690        11720 :     const uint16_t name_size = (name != NULL) ? strlen(name)+1 : 0;
    2691              : 
    2692        11720 :     size_t arg_size = (size_t) (length + 1);
    2693              : 
    2694        11720 :     size_t new_log_size = log->size + arg_size + sizeof(uint16_t);
    2695              : 
    2696        11720 :     uint32_t type_info = 0;
    2697              : 
    2698        11720 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2699        11720 :         new_log_size += sizeof(uint32_t);
    2700        11720 :         if (with_var_info) {
    2701           21 :             new_log_size += sizeof(uint16_t);  // length of "name" attribute
    2702           21 :             new_log_size += name_size;  // the "name" attribute itself
    2703              : 
    2704           21 :             type_info |= DLT_TYPE_INFO_VARI;
    2705              :         }
    2706              :     }
    2707              : 
    2708              :     size_t str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1;
    2709              :     size_t max_payload_str_msg;
    2710              :     DltReturnValue ret = DLT_RETURN_OK;
    2711              : 
    2712              :     /* Check log size condition */
    2713        11720 :     if (new_log_size > dlt_user.log_buf_len) {
    2714              :         ret = DLT_RETURN_USER_BUFFER_FULL;
    2715              : 
    2716              :         /* Re-calculate arg_size */
    2717           21 :         arg_size = (size_t) (dlt_user.log_buf_len - log->size - sizeof(uint16_t));
    2718              : 
    2719           21 :         size_t min_payload_str_truncate_msg = log->size + str_truncate_message_length + sizeof(uint16_t);
    2720              : 
    2721              :         if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2722           21 :             min_payload_str_truncate_msg += sizeof(uint32_t);
    2723           21 :             arg_size -= (size_t) sizeof(uint32_t);
    2724           21 :             if (with_var_info) {
    2725            0 :                 min_payload_str_truncate_msg += sizeof(uint16_t) + name_size;
    2726            0 :                 arg_size -= sizeof(uint16_t) + name_size;
    2727              :             }
    2728              :         }
    2729              : 
    2730              :         /* Return when dlt_user.log_buf_len does not have enough space for min_payload_str_truncate_msg */
    2731           21 :         if (min_payload_str_truncate_msg > dlt_user.log_buf_len) {
    2732            1 :             dlt_vlog(LOG_WARNING, "%s not enough minimum space to store data\n", __FUNCTION__);
    2733            1 :             return ret;
    2734              :         }
    2735              : 
    2736              :         /* Calculate the maximum size of string will be copied after truncate */
    2737           20 :         max_payload_str_msg = dlt_user.log_buf_len - min_payload_str_truncate_msg;
    2738              : 
    2739           20 :         if (type == UTF8_STRING) {
    2740              :             /**
    2741              :              * Adjust the lengh to truncate one utf8 character corectly
    2742              :              * refer: https://en.wikipedia.org/wiki/UTF-8
    2743              :              * one utf8 character will have maximum 4 bytes then maximum bytes will be truncate additional is 3
    2744              :              */
    2745           12 :             const char *tmp = (text + max_payload_str_msg - 3);
    2746              :             uint16_t reduce_size = 0;
    2747              : 
    2748           12 :             if (tmp[2] & 0x80) {
    2749              :                 /* Is the last byte of truncated text is the first byte in multi-byte sequence (utf8 2 bytes) */
    2750            9 :                 if (tmp[2] & 0x40)
    2751              :                     reduce_size = 1;
    2752              :                 /* Is the next to last byte of truncated text is the first byte in multi-byte sequence (utf8 3 bytes) */
    2753            6 :                 else if ((tmp[1] & 0xe0) == 0xe0)
    2754              :                     reduce_size = 2;
    2755              :                 /* utf8 4 bytes */
    2756            3 :                 else if ((tmp[0] & 0xf0) == 0xf0)
    2757              :                     reduce_size = 3;
    2758              :             }
    2759              : 
    2760           12 :             max_payload_str_msg -= reduce_size;
    2761           12 :             arg_size -= (size_t) reduce_size;
    2762              :         }
    2763              :     }
    2764              : 
    2765              :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2766        11719 :         switch (type) {
    2767        11694 :         case ASCII_STRING:
    2768        11694 :             type_info |= DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
    2769        11694 :             break;
    2770           25 :         case UTF8_STRING:
    2771           25 :             type_info |= DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
    2772           25 :             break;
    2773              :         default:
    2774              :             /* Do nothing */
    2775              :             break;
    2776              :         }
    2777              : 
    2778        11719 :         memcpy(log->buffer + log->size, &type_info, sizeof(uint32_t));
    2779        11719 :         log->size += sizeof(uint32_t);
    2780              :     }
    2781              : 
    2782        11719 :     memcpy(log->buffer + log->size, &arg_size, sizeof(uint16_t));
    2783        11719 :     log->size += sizeof(uint16_t);
    2784              : 
    2785        11719 :     if (is_verbose_mode(dlt_user.verbose_mode, log)) {
    2786        11719 :         if (with_var_info) {
    2787              :             // Write length of "name" attribute.
    2788              :             // We assume that the protocol allows zero-sized strings here (which this code will create
    2789              :             // when the input pointer is NULL).
    2790           21 :             memcpy(log->buffer + log->size, &name_size, sizeof(uint16_t));
    2791           21 :             log->size += sizeof(uint16_t);
    2792              : 
    2793              :             // Write name string itself.
    2794              :             // Must not use NULL as source pointer for memcpy. This check assures that.
    2795           21 :             if (name_size != 0) {
    2796           15 :                 memcpy(log->buffer + log->size, name, name_size);
    2797           15 :                 log->size += name_size;
    2798              :             }
    2799              :         }
    2800              :     }
    2801              : 
    2802        11719 :     switch (ret) {
    2803        11699 :     case DLT_RETURN_OK:
    2804              :     {
    2805              :         /* Whole string will be copied */
    2806        11699 :         memcpy(log->buffer + log->size, text, length);
    2807              :         /* The input string might not be null-terminated, so we're doing that by ourselves */
    2808        11699 :         log->buffer[log->size + length] = '\0';
    2809        11699 :         log->size += arg_size;
    2810        11699 :         break;
    2811              :     }
    2812           20 :     case DLT_RETURN_USER_BUFFER_FULL:
    2813              :     {
    2814              :         /* Only copy partial string */
    2815           20 :         memcpy(log->buffer + log->size, text, max_payload_str_msg);
    2816           20 :         log->size += max_payload_str_msg;
    2817              : 
    2818              :         /* Append string truncate the input string */
    2819           20 :         memcpy(log->buffer + log->size, STR_TRUNCATED_MESSAGE, str_truncate_message_length);
    2820           20 :         log->size += str_truncate_message_length;
    2821           20 :         break;
    2822              :     }
    2823              :     default:
    2824              :     {
    2825              :         /* Do nothing */
    2826              :         break;
    2827              :     }
    2828              :     }
    2829              : 
    2830        11719 :     log->args_num++;
    2831              : 
    2832        11719 :     return ret;
    2833              : }
    2834              : 
    2835        11721 : static DltReturnValue dlt_user_log_write_string_utils_attr(DltContextData *log, const char *text, const enum StringType type, const char *name, bool with_var_info)
    2836              : {
    2837        11721 :     if ((log == NULL) || (text == NULL))
    2838              :         return DLT_RETURN_WRONG_PARAMETER;
    2839              : 
    2840        11706 :     size_t length = strlen(text);
    2841        11706 :     return dlt_user_log_write_sized_string_utils_attr(log, text, length, type, name, with_var_info);
    2842              : }
    2843              : 
    2844            0 : DltReturnValue dlt_register_injection_callback_with_id(DltContext *handle, uint32_t service_id,
    2845              :                                                        dlt_injection_callback_id dlt_injection_cbk, void *priv)
    2846              : {
    2847              :     DltContextData log;
    2848              :     uint32_t i, j, k;
    2849              :     int found = 0;
    2850              : 
    2851              :     DltUserInjectionCallback *old;
    2852              : 
    2853            0 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    2854              :         return DLT_RETURN_ERROR;
    2855              : 
    2856            0 :     if (service_id < DLT_USER_INJECTION_MIN)
    2857              :         return DLT_RETURN_WRONG_PARAMETER;
    2858              : 
    2859              :     /* This function doesn't make sense storing to local file is choosen;
    2860              :      * so terminate this function */
    2861            0 :     if (dlt_user.dlt_is_file)
    2862              :         return DLT_RETURN_OK;
    2863              : 
    2864            0 :     DLT_SEM_LOCK();
    2865              : 
    2866            0 :     if (dlt_user.dlt_ll_ts == NULL) {
    2867            0 :         DLT_SEM_FREE();
    2868            0 :         return DLT_RETURN_OK;
    2869              :     }
    2870              : 
    2871              :     /* Insert callback in corresponding table */
    2872            0 :     i = (uint32_t) handle->log_level_pos;
    2873              : 
    2874              :     /* Insert each service_id only once */
    2875            0 :     for (k = 0; k < dlt_user.dlt_ll_ts[i].nrcallbacks; k++)
    2876            0 :         if ((dlt_user.dlt_ll_ts[i].injection_table) &&
    2877            0 :             (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id)) {
    2878              :             found = 1;
    2879              :             break;
    2880              :         }
    2881              : 
    2882            0 :     if (found) {
    2883              :         j = k;
    2884              :     }
    2885              :     else {
    2886              :         j = dlt_user.dlt_ll_ts[i].nrcallbacks;
    2887              : 
    2888              :         /* Allocate or expand injection table */
    2889            0 :         if (dlt_user.dlt_ll_ts[i].injection_table == NULL) {
    2890            0 :             dlt_user.dlt_ll_ts[i].injection_table =
    2891            0 :                 (DltUserInjectionCallback *)malloc(sizeof(DltUserInjectionCallback));
    2892              : 
    2893            0 :             if (dlt_user.dlt_ll_ts[i].injection_table == NULL) {
    2894            0 :                 DLT_SEM_FREE();
    2895            0 :                 return DLT_RETURN_ERROR;
    2896              :             }
    2897              :         }
    2898              :         else {
    2899              :             old = dlt_user.dlt_ll_ts[i].injection_table;
    2900            0 :             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback *)malloc(
    2901            0 :                 sizeof(DltUserInjectionCallback) * (j + 1));
    2902              : 
    2903            0 :             if (dlt_user.dlt_ll_ts[i].injection_table == NULL) {
    2904            0 :                 dlt_user.dlt_ll_ts[i].injection_table = old;
    2905            0 :                 DLT_SEM_FREE();
    2906            0 :                 return DLT_RETURN_ERROR;
    2907              :             }
    2908              : 
    2909            0 :             memcpy(dlt_user.dlt_ll_ts[i].injection_table, old, sizeof(DltUserInjectionCallback) * j);
    2910            0 :             free(old);
    2911              :         }
    2912              : 
    2913            0 :         dlt_user.dlt_ll_ts[i].nrcallbacks++;
    2914              :     }
    2915              : 
    2916              :     /* Store service_id and corresponding function pointer for callback function */
    2917            0 :     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
    2918              : 
    2919            0 :     if (priv == NULL) {
    2920            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = (dlt_injection_callback)(void*)dlt_injection_cbk;
    2921            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback_with_id = NULL;
    2922            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].data = NULL;
    2923              :     }
    2924              :     else {
    2925            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = NULL;
    2926            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback_with_id = dlt_injection_cbk;
    2927            0 :         dlt_user.dlt_ll_ts[i].injection_table[j].data = priv;
    2928              :     }
    2929              : 
    2930            0 :     DLT_SEM_FREE();
    2931              : 
    2932              :     return DLT_RETURN_OK;
    2933              : }
    2934              : 
    2935            0 : DltReturnValue dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
    2936              :                                                int (*dlt_injection_callback)(uint32_t service_id,
    2937              :                                                                              void *data,
    2938              :                                                                              uint32_t length))
    2939              : {
    2940            0 :     return dlt_register_injection_callback_with_id(handle,
    2941              :                                                    service_id,
    2942              :                                                    (dlt_injection_callback_id)(void*)dlt_injection_callback,
    2943              :                                                    NULL);
    2944              : }
    2945              : 
    2946            1 : DltReturnValue dlt_register_log_level_changed_callback(DltContext *handle,
    2947              :                                                        void (*dlt_log_level_changed_callback)(
    2948              :                                                            char context_id[DLT_ID_SIZE],
    2949              :                                                            uint8_t log_level,
    2950              :                                                            uint8_t trace_status))
    2951              : {
    2952              :     DltContextData log;
    2953              :     uint32_t i;
    2954              : 
    2955            1 :     if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    2956              :         return DLT_RETURN_ERROR;
    2957              : 
    2958              :     /* This function doesn't make sense storing to local file is choosen;
    2959              :      * so terminate this function */
    2960            1 :     if (dlt_user.dlt_is_file)
    2961              :         return DLT_RETURN_OK;
    2962              : 
    2963            1 :     DLT_SEM_LOCK();
    2964              : 
    2965            1 :     if (dlt_user.dlt_ll_ts == NULL) {
    2966            0 :         DLT_SEM_FREE();
    2967            0 :         return DLT_RETURN_OK;
    2968              :     }
    2969              : 
    2970              :     /* Insert callback in corresponding table */
    2971            1 :     i = (uint32_t) handle->log_level_pos;
    2972              : 
    2973              :     /* Store new callback function */
    2974            1 :     dlt_user.dlt_ll_ts[i].log_level_changed_callback = dlt_log_level_changed_callback;
    2975              : 
    2976            1 :     DLT_SEM_FREE();
    2977              : 
    2978              :     return DLT_RETURN_OK;
    2979              : }
    2980              : 
    2981              : /**
    2982              :  * NW Trace related
    2983              :  */
    2984              : 
    2985              : #ifdef DLT_NETWORK_TRACE_ENABLE
    2986            0 : int check_buffer(void)
    2987              : {
    2988              :     int total_size, used_size;
    2989            0 :     dlt_user_check_buffer(&total_size, &used_size);
    2990              : 
    2991            0 :     return (total_size - used_size < total_size / 2) ? -1 : 1;
    2992              : }
    2993              : 
    2994              : /**
    2995              :  * Send the start of a segment chain.
    2996              :  * Returns DLT_RETURN_ERROR on failure
    2997              :  */
    2998            0 : DltReturnValue dlt_user_trace_network_segmented_start(uint32_t *id,
    2999              :                                                       DltContext *handle,
    3000              :                                                       DltNetworkTraceType nw_trace_type,
    3001              :                                                       uint16_t header_len,
    3002              :                                                       void *header,
    3003              :                                                       uint16_t payload_len)
    3004              : {
    3005            0 :     DltContextData log = { 0 };
    3006              :     struct timeval tv;
    3007              :     int ret = DLT_RETURN_ERROR;
    3008              : 
    3009              :     /* check null pointer */
    3010            0 :     if (id == NULL)
    3011              :         return DLT_RETURN_WRONG_PARAMETER;
    3012              : 
    3013            0 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3014            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3015            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3016              :     }
    3017              : 
    3018            0 :     if (dlt_user.dlt_ll_ts == NULL)
    3019              :         return DLT_RETURN_ERROR;
    3020              : 
    3021            0 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3022              :         /* initialize values */
    3023            0 :         if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3024              :             return DLT_RETURN_ERROR;
    3025              : 
    3026            0 :         if (log.buffer == NULL) {
    3027            0 :             log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len);
    3028              : 
    3029            0 :             if (log.buffer == NULL) {
    3030            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3031            0 :                 return DLT_RETURN_ERROR;
    3032              :             }
    3033              :         }
    3034              : 
    3035            0 :         log.args_num = 0;
    3036            0 :         log.trace_status = nw_trace_type;
    3037            0 :         log.size = 0;
    3038              : 
    3039            0 :         gettimeofday(&tv, NULL);
    3040            0 :         *id = (uint32_t) tv.tv_usec;
    3041              : 
    3042              :         /* Write identifier */
    3043            0 :         if (dlt_user_log_write_string(&log, DLT_TRACE_NW_START) < 0) {
    3044              :             dlt_user_free_buffer(&(log.buffer));
    3045            0 :             return DLT_RETURN_ERROR;
    3046              :         }
    3047              : 
    3048              :         /* Write stream handle */
    3049            0 :         if (dlt_user_log_write_uint32(&log, *id) < 0) {
    3050              :             dlt_user_free_buffer(&(log.buffer));
    3051            0 :             return DLT_RETURN_ERROR;
    3052              :         }
    3053              : 
    3054              :         /* Write header */
    3055            0 :         if (dlt_user_log_write_raw(&log, header, header_len) < 0) {
    3056              :             dlt_user_free_buffer(&(log.buffer));
    3057            0 :             return DLT_RETURN_ERROR;
    3058              :         }
    3059              : 
    3060              :         /* Write size of payload */
    3061            0 :         if (dlt_user_log_write_uint32(&log, payload_len) < 0) {
    3062              :             dlt_user_free_buffer(&(log.buffer));
    3063            0 :             return DLT_RETURN_ERROR;
    3064              :         }
    3065              : 
    3066              :         /* Write expected segment count */
    3067            0 :         uint16_t segment_count = (uint16_t) (payload_len / DLT_MAX_TRACE_SEGMENT_SIZE + 1);
    3068              : 
    3069              :         /* If segments align perfectly with segment size, avoid sending empty segment */
    3070            0 :         if ((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
    3071              :             segment_count--;
    3072              : 
    3073            0 :         if (dlt_user_log_write_uint16(&log, segment_count) < 0) {
    3074              :             dlt_user_free_buffer(&(log.buffer));
    3075            0 :             return DLT_RETURN_ERROR;
    3076              :         }
    3077              : 
    3078              :         /* Write length of one segment */
    3079            0 :         if (dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0) {
    3080              :             dlt_user_free_buffer(&(log.buffer));
    3081            0 :             return DLT_RETURN_ERROR;
    3082              :         }
    3083              : 
    3084              :         /* Send log */
    3085            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3086              : 
    3087              :         dlt_user_free_buffer(&(log.buffer));
    3088              : 
    3089            0 :         return ret;
    3090              :     }
    3091              : 
    3092              :     return DLT_RETURN_OK;
    3093              : }
    3094              : 
    3095            0 : DltReturnValue dlt_user_trace_network_segmented_segment(uint32_t id,
    3096              :                                                         DltContext *handle,
    3097              :                                                         DltNetworkTraceType nw_trace_type,
    3098              :                                                         int sequence,
    3099              :                                                         uint16_t payload_len,
    3100              :                                                         void *payload)
    3101              : {
    3102              :     int ret = DLT_RETURN_ERROR;
    3103              :     struct timespec ts;
    3104              : 
    3105            0 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3106            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3107            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3108              :     }
    3109              : 
    3110            0 :     while (check_buffer() < 0) {
    3111              :         /* Wait 50ms */
    3112            0 :         ts.tv_sec = 0;
    3113            0 :         ts.tv_nsec = 1000000 * 50;
    3114            0 :         nanosleep(&ts, NULL);
    3115            0 :         dlt_user_log_resend_buffer();
    3116              :     }
    3117              : 
    3118            0 :     if (dlt_user.dlt_ll_ts == NULL)
    3119              :         return DLT_RETURN_ERROR;
    3120              : 
    3121            0 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3122            0 :         DltContextData log = { 0 };
    3123              : 
    3124            0 :         if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3125              :             return DLT_RETURN_ERROR;
    3126              : 
    3127              :         /* initialize values */
    3128            0 :         if (log.buffer == NULL) {
    3129            0 :             log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len);
    3130              : 
    3131            0 :             if (log.buffer == NULL) {
    3132            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3133            0 :                 return DLT_RETURN_ERROR;
    3134              :             }
    3135              :         }
    3136              : 
    3137            0 :         log.args_num = 0;
    3138            0 :         log.trace_status = nw_trace_type;
    3139            0 :         log.size = 0;
    3140              : 
    3141              :         /* Write identifier */
    3142            0 :         if (dlt_user_log_write_string(&log, DLT_TRACE_NW_SEGMENT) < DLT_RETURN_OK) {
    3143              :             dlt_user_free_buffer(&(log.buffer));
    3144            0 :             return DLT_RETURN_ERROR;
    3145              :         }
    3146              : 
    3147              :         /* Write stream handle */
    3148            0 :         if (dlt_user_log_write_uint32(&log, id) < DLT_RETURN_OK) {
    3149              :             dlt_user_free_buffer(&(log.buffer));
    3150            0 :             return DLT_RETURN_ERROR;
    3151              :         }
    3152              : 
    3153              :         /* Write segment sequence number */
    3154            0 :         if (dlt_user_log_write_uint16(&log, (uint16_t) sequence) < DLT_RETURN_OK) {
    3155              :             dlt_user_free_buffer(&(log.buffer));
    3156            0 :             return DLT_RETURN_ERROR;
    3157              :         }
    3158              : 
    3159              :         /* Write data */
    3160            0 :         if (dlt_user_log_write_raw(&log, payload, payload_len) < DLT_RETURN_OK) {
    3161              :             dlt_user_free_buffer(&(log.buffer));
    3162            0 :             return DLT_RETURN_ERROR;
    3163              :         }
    3164              : 
    3165            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3166              :         /* Send log */
    3167              : 
    3168              :         dlt_user_free_buffer(&(log.buffer));
    3169              : 
    3170            0 :         return ret;
    3171              :     }
    3172              : 
    3173              :     /* Allow other threads to log between chunks */
    3174            0 :     sched_yield();
    3175            0 :     return DLT_RETURN_OK;
    3176              : }
    3177              : 
    3178            0 : DltReturnValue dlt_user_trace_network_segmented_end(uint32_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
    3179              : {
    3180            0 :     DltContextData log = { 0 };
    3181              :     int ret = DLT_RETURN_ERROR;
    3182              : 
    3183            0 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3184            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3185            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3186              :     }
    3187              : 
    3188            0 :     if (dlt_user.dlt_ll_ts == NULL)
    3189              :         return DLT_RETURN_ERROR;
    3190              : 
    3191            0 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3192              :         /* initialize values */
    3193            0 :         if (dlt_user_log_init(handle, &log) < DLT_RETURN_OK)
    3194              :             return DLT_RETURN_ERROR;
    3195              : 
    3196              :         /* initialize values */
    3197            0 :         if (log.buffer == NULL) {
    3198            0 :             log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len);
    3199              : 
    3200            0 :             if (log.buffer == NULL) {
    3201            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3202            0 :                 return DLT_RETURN_ERROR;
    3203              :             }
    3204              :         }
    3205              : 
    3206            0 :         log.args_num = 0;
    3207            0 :         log.trace_status = nw_trace_type;
    3208            0 :         log.size = 0;
    3209              : 
    3210              :         /* Write identifier */
    3211            0 :         if (dlt_user_log_write_string(&log, DLT_TRACE_NW_END) < DLT_RETURN_OK) {
    3212              :             dlt_user_free_buffer(&(log.buffer));
    3213            0 :             return DLT_RETURN_ERROR;
    3214              :         }
    3215              : 
    3216              :         /* Write stream handle */
    3217            0 :         if (dlt_user_log_write_uint32(&log, id) < DLT_RETURN_OK) {
    3218              :             dlt_user_free_buffer(&(log.buffer));
    3219            0 :             return DLT_RETURN_ERROR;
    3220              :         }
    3221              : 
    3222            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3223              :         /* Send log */
    3224              : 
    3225              :         dlt_user_free_buffer(&(log.buffer));
    3226              : 
    3227            0 :         return ret;
    3228              : 
    3229              :     }
    3230              : 
    3231              :     return DLT_RETURN_OK;
    3232              : }
    3233              : 
    3234        21266 : void dlt_user_trace_network_segmented_thread(void *unused)
    3235              : {
    3236              :     /* Unused on purpose. */
    3237              :     (void)unused;
    3238              : #ifdef DLT_USE_PTHREAD_SETNAME_NP
    3239        21266 :     if (pthread_setname_np(dlt_user.dlt_segmented_nwt_handle, "dlt_segmented"))
    3240            0 :         dlt_log(LOG_WARNING, "Failed to rename segmented thread!\n");
    3241              : #elif linux
    3242              :     if (prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0) < 0)
    3243              :         dlt_log(LOG_WARNING, "Failed to rename segmented thread!\n");
    3244              : #endif
    3245        42532 :     pthread_cleanup_push(dlt_user_cleanup_handler, NULL);
    3246              : 
    3247              :     s_segmented_data *data;
    3248              : 
    3249              :     while (1) {
    3250              :         /* Wait until message queue is initialized */
    3251        21266 :         dlt_lock_mutex(&mq_mutex);
    3252              : 
    3253        21303 :         while (dlt_user.dlt_segmented_queue_read_handle < 0)
    3254              :         {
    3255        21303 :             pthread_cond_wait(&mq_init_condition, &mq_mutex);
    3256              :         }
    3257              : 
    3258            0 :         dlt_unlock_mutex(&mq_mutex);
    3259              : 
    3260            0 :         ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
    3261              :                                   sizeof(s_segmented_data *), NULL);
    3262              : 
    3263            0 :         if (read < 0) {
    3264            0 :             if (errno != EINTR) {
    3265              :                 struct timespec req;
    3266              :                 long sec = (DLT_USER_MQ_ERROR_RETRY_INTERVAL / 1000000);
    3267            0 :                 dlt_vlog(LOG_WARNING, "NWTSegmented: Error while reading queue: %s\n", strerror(errno));
    3268            0 :                 req.tv_sec = sec;
    3269            0 :                 req.tv_nsec = (DLT_USER_MQ_ERROR_RETRY_INTERVAL - sec * 1000000) * 1000;
    3270            0 :                 nanosleep(&req, NULL);
    3271              :             }
    3272              : 
    3273            0 :             continue;
    3274              :         }
    3275              : 
    3276            0 :         if (read != sizeof(s_segmented_data *)) {
    3277              :             /* This case will not happen. */
    3278              :             /* When this thread is interrupted by signal, mq_receive() will not return */
    3279              :             /* partial read length and will return -1. And also no data is removed from mq. */
    3280            0 :             dlt_vlog(LOG_WARNING, "NWTSegmented: Could not read data fully from queue: %zd\n", read);
    3281            0 :             continue;
    3282              :         }
    3283              : 
    3284            0 :         dlt_user_trace_network_segmented_thread_segmenter(data);
    3285              : 
    3286              :         /* Send the end message */
    3287            0 :         DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
    3288              : 
    3289            0 :         if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR))
    3290            0 :             dlt_log(LOG_WARNING, "NWTSegmented: Could not send end segment.\n");
    3291              : 
    3292              :         /* Free resources */
    3293            0 :         free(data->header);
    3294            0 :         free(data->payload);
    3295            0 :         free(data);
    3296              :     }
    3297              : 
    3298              :     pthread_cleanup_pop(1);
    3299              : }
    3300              : 
    3301            0 : void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
    3302              : {
    3303              :     /* Segment the data and send the chunks */
    3304              :     void *ptr = NULL;
    3305              :     uint32_t offset = 0;
    3306              :     uint16_t sequence = 0;
    3307              : 
    3308              :     do {
    3309              :         uint16_t len = 0;
    3310              : 
    3311            0 :         if (offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
    3312            0 :             len = (uint16_t) (data->payload_len - offset);
    3313              :         else
    3314              :             len = DLT_MAX_TRACE_SEGMENT_SIZE;
    3315              : 
    3316              :         /* If payload size aligns perfectly with segment size, avoid sending empty segment */
    3317            0 :         if (len == 0)
    3318              :             break;
    3319              : 
    3320            0 :         ptr = data->payload + offset;
    3321            0 :         DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id,
    3322              :                                                                       data->handle,
    3323              :                                                                       data->nw_trace_type,
    3324            0 :                                                                       sequence++,
    3325              :                                                                       len,
    3326              :                                                                       ptr);
    3327              : 
    3328            0 :         if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) {
    3329            0 :             dlt_log(LOG_ERR, "NWTSegmented: Could not send segment. Aborting.\n");
    3330            0 :             break;             /* loop */
    3331              :         }
    3332              : 
    3333            0 :         offset += len;
    3334            0 :     } while (ptr < data->payload + data->payload_len);
    3335            0 : }
    3336              : 
    3337              : 
    3338            7 : DltReturnValue dlt_user_trace_network_segmented(DltContext *handle,
    3339              :                                                 DltNetworkTraceType nw_trace_type,
    3340              :                                                 uint16_t header_len,
    3341              :                                                 void *header,
    3342              :                                                 uint16_t payload_len,
    3343              :                                                 void *payload)
    3344              : {
    3345              :     /* forbid dlt usage in child after fork */
    3346            7 :     if (g_dlt_is_child)
    3347              :         return DLT_RETURN_ERROR;
    3348              : 
    3349              :     /* Send as normal trace if possible */
    3350            7 :     if (header_len + payload_len + sizeof(uint16_t) < dlt_user.log_buf_len)
    3351            7 :         return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
    3352              : 
    3353              :     /* Allocate Memory */
    3354            0 :     s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
    3355              : 
    3356            0 :     if (thread_data == NULL)
    3357              :         return DLT_RETURN_ERROR;
    3358              : 
    3359            0 :     thread_data->header = malloc(header_len);
    3360              : 
    3361            0 :     if (thread_data->header == NULL) {
    3362            0 :         free(thread_data);
    3363            0 :         return DLT_RETURN_ERROR;
    3364              :     }
    3365              : 
    3366            0 :     thread_data->payload = malloc(payload_len);
    3367              : 
    3368            0 :     if (thread_data->payload == NULL) {
    3369            0 :         free(thread_data->header);
    3370            0 :         free(thread_data);
    3371            0 :         return DLT_RETURN_ERROR;
    3372              :     }
    3373              : 
    3374              :     /* Copy data */
    3375            0 :     thread_data->handle = handle;
    3376            0 :     thread_data->nw_trace_type = nw_trace_type;
    3377            0 :     thread_data->header_len = header_len;
    3378              :     memcpy(thread_data->header, header, header_len);
    3379            0 :     thread_data->payload_len = payload_len;
    3380              :     memcpy(thread_data->payload, payload, payload_len);
    3381              : 
    3382              :     /* Send start message */
    3383            0 :     DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id),
    3384              :                                                                 thread_data->handle,
    3385              :                                                                 thread_data->nw_trace_type,
    3386              :                                                                 (uint16_t) thread_data->header_len,
    3387              :                                                                 thread_data->header,
    3388              :                                                                 (uint16_t) thread_data->payload_len);
    3389              : 
    3390            0 :     if ((err == DLT_RETURN_BUFFER_FULL) || (err == DLT_RETURN_ERROR)) {
    3391            0 :         dlt_log(LOG_ERR, "NWTSegmented: Could not send start segment. Aborting.\n");
    3392            0 :         free(thread_data->header);
    3393            0 :         free(thread_data->payload);
    3394            0 :         free(thread_data);
    3395            0 :         return DLT_RETURN_ERROR;
    3396              :     }
    3397              : 
    3398              :     /* Open queue if it is not open */
    3399            0 :     if (dlt_init_message_queue() < 0) {
    3400            0 :         dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
    3401            0 :         free(thread_data->header);
    3402            0 :         free(thread_data->payload);
    3403            0 :         free(thread_data);
    3404              : 
    3405            0 :         return DLT_RETURN_ERROR;
    3406              :     }
    3407              : 
    3408              :     /* Add to queue */
    3409            0 :     if (mq_send(dlt_user.dlt_segmented_queue_write_handle,
    3410              :                 (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0) {
    3411            0 :         if (errno == EAGAIN)
    3412            0 :             dlt_log(LOG_WARNING, "NWTSegmented: Queue full. Message discarded.\n");
    3413              : 
    3414            0 :         free(thread_data->header);
    3415            0 :         free(thread_data->payload);
    3416            0 :         free(thread_data);
    3417            0 :         dlt_vnlog(LOG_WARNING, 256, "NWTSegmented: Could not write into queue: %s \n", strerror(errno));
    3418            0 :         return DLT_RETURN_ERROR;
    3419              :     }
    3420              : 
    3421              :     /*thread_data will be freed by the receiver function */
    3422              :     /*coverity[leaked_storage] */
    3423              :     return DLT_RETURN_OK;
    3424              : }
    3425              : 
    3426           14 : DltReturnValue dlt_user_trace_network(DltContext *handle,
    3427              :                                       DltNetworkTraceType nw_trace_type,
    3428              :                                       uint16_t header_len,
    3429              :                                       void *header,
    3430              :                                       uint16_t payload_len,
    3431              :                                       void *payload)
    3432              : {
    3433           14 :     return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
    3434              : }
    3435              : 
    3436           21 : DltReturnValue dlt_user_trace_network_truncated(DltContext *handle,
    3437              :                                                 DltNetworkTraceType nw_trace_type,
    3438              :                                                 uint16_t header_len,
    3439              :                                                 void *header,
    3440              :                                                 uint16_t payload_len,
    3441              :                                                 void *payload,
    3442              :                                                 int allow_truncate)
    3443              : {
    3444              :     int ret = DLT_RETURN_ERROR;
    3445           21 :     DltContextData log = { 0 };
    3446              : 
    3447           21 :     if ((payload == NULL) && (payload_len > 0))
    3448              :         return DLT_RETURN_WRONG_PARAMETER;
    3449              : 
    3450           15 :     if ((nw_trace_type < DLT_NW_TRACE_IPC) || (nw_trace_type >= DLT_NW_TRACE_MAX)) {
    3451            0 :         dlt_vlog(LOG_ERR, "Network trace type %u is outside valid range", nw_trace_type);
    3452            0 :         return DLT_RETURN_WRONG_PARAMETER;
    3453              :     }
    3454              : 
    3455           15 :     if (dlt_user.dlt_ll_ts == NULL)
    3456              :         return DLT_RETURN_ERROR;
    3457              : 
    3458           15 :     if (handle->trace_status_ptr && (*(handle->trace_status_ptr) == DLT_TRACE_STATUS_ON)) {
    3459            0 :         if ((dlt_user_log_init(handle, &log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL))
    3460              :             return DLT_RETURN_ERROR;
    3461              : 
    3462              :         /* initialize values */
    3463            0 :         if (log.buffer == NULL) {
    3464            0 :             log.buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len);
    3465              : 
    3466            0 :             if (log.buffer == NULL) {
    3467            0 :                 dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n");
    3468            0 :                 return DLT_RETURN_ERROR;
    3469              :             }
    3470              :         }
    3471              : 
    3472            0 :         log.args_num = 0;
    3473            0 :         log.trace_status = nw_trace_type;
    3474            0 :         log.size = 0;
    3475              : 
    3476            0 :         if (header == NULL)
    3477              :             header_len = 0;
    3478              : 
    3479              :         /* If truncation is allowed, check if we must do it */
    3480            0 :         if ((allow_truncate > 0) && ((header_len + payload_len + sizeof(uint16_t)) > dlt_user.log_buf_len)) {
    3481              :             /* Identify as truncated */
    3482            0 :             if (dlt_user_log_write_string(&log, DLT_TRACE_NW_TRUNCATED) < DLT_RETURN_OK) {
    3483              :                 dlt_user_free_buffer(&(log.buffer));
    3484            0 :                 return DLT_RETURN_ERROR;
    3485              :             }
    3486              : 
    3487              :             /* Write header and its length */
    3488            0 :             if (dlt_user_log_write_raw(&log, header, header_len) < DLT_RETURN_OK) {
    3489              :                 dlt_user_free_buffer(&(log.buffer));
    3490            0 :                 return DLT_RETURN_ERROR;
    3491              :             }
    3492              : 
    3493              :             /* Write original size of payload */
    3494            0 :             if (dlt_user_log_write_uint32(&log, payload_len) < DLT_RETURN_OK) {
    3495              :                 dlt_user_free_buffer(&(log.buffer));
    3496            0 :                 return DLT_RETURN_ERROR;
    3497              :             }
    3498              : 
    3499              :             /**
    3500              :              *  Calculate maximum available space in sending buffer after headers.
    3501              :              */
    3502              : 
    3503            0 :             uint16_t truncated_payload_len = (uint16_t) (dlt_user.log_buf_len - log.size - sizeof(uint16_t) - sizeof(uint32_t));
    3504              : 
    3505              :             /* Write truncated payload */
    3506            0 :             if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < DLT_RETURN_OK) {
    3507              :                 dlt_user_free_buffer(&(log.buffer));
    3508            0 :                 return DLT_RETURN_ERROR;
    3509              :             }
    3510              :         }
    3511              :         else { /* Truncation not allowed or data short enough */
    3512              : 
    3513              :             /* Write header and its length */
    3514            0 :             if (dlt_user_log_write_raw(&log, header, header_len) < DLT_RETURN_OK) {
    3515              :                 dlt_user_free_buffer(&(log.buffer));
    3516            0 :                 return DLT_RETURN_ERROR;
    3517              :             }
    3518              : 
    3519            0 :             if (payload == NULL)
    3520              :                 payload_len = 0;
    3521              : 
    3522              :             /* Write payload and its length */
    3523            0 :             if (dlt_user_log_write_raw(&log, payload, payload_len) < DLT_RETURN_OK) {
    3524              :                 dlt_user_free_buffer(&(log.buffer));
    3525            0 :                 return DLT_RETURN_ERROR;
    3526              :             }
    3527              :         }
    3528              : 
    3529            0 :         ret = dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE, NULL);
    3530              : 
    3531              :         dlt_user_free_buffer(&(log.buffer));
    3532              : 
    3533              :         /* Send log */
    3534            0 :         return ret;
    3535              :     }
    3536              : 
    3537              :     return DLT_RETURN_OK;
    3538              : }
    3539              : #else  /* DLT_NETWORK_TRACE_ENABLE not set */
    3540              : DltReturnValue dlt_user_trace_network_segmented(DltContext *handle,
    3541              :                                                 DltNetworkTraceType nw_trace_type,
    3542              :                                                 uint16_t header_len,
    3543              :                                                 void *header,
    3544              :                                                 uint16_t payload_len,
    3545              :                                                 void *payload)
    3546              : {
    3547              :     /**
    3548              :      *  vsomeip uses the DLT_TRACE_NETWORK_SEGMENTED macro that calls this function.
    3549              :      *  It's not possible to rewrite this macro directly to a no-op,
    3550              :      *  because the macro is used on vsomeip side and there our defines are not set.
    3551              :      *  Add an empty function to the dlt-lib to avoid a broken build.
    3552              :      */
    3553              :     (void)handle;
    3554              :     (void)nw_trace_type;
    3555              :     (void)header_len;
    3556              :     (void)header;
    3557              :     (void)payload_len;
    3558              :     (void)payload;
    3559              :     return DLT_RETURN_LOGGING_DISABLED;
    3560              : }
    3561              : 
    3562              : DltReturnValue dlt_user_trace_network_truncated(DltContext *handle,
    3563              :                                                 DltNetworkTraceType nw_trace_type,
    3564              :                                                 uint16_t header_len,
    3565              :                                                 void *header,
    3566              :                                                 uint16_t payload_len,
    3567              :                                                 void *payload,
    3568              :                                                 int allow_truncate)
    3569              : {
    3570              :     /**
    3571              :      *  vsomeip uses the DLT_TRACE_NETWORK_TRUNCATED macro that calls this function.
    3572              :      *  It's not possible to rewrite this macro directly to a no-op,
    3573              :      *  because the macro is used on vsomeip side and there our defines are not set.
    3574              :      *  Add an empty function to the dlt-lib to avoid a broken build.
    3575              :      */
    3576              :     (void)handle;
    3577              :     (void)nw_trace_type;
    3578              :     (void)header_len;
    3579              :     (void)header;
    3580              :     (void)payload_len;
    3581              :     (void)payload;
    3582              :     (void)allow_truncate;
    3583              :     return DLT_RETURN_LOGGING_DISABLED;
    3584              : }
    3585              : 
    3586              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    3587              : 
    3588           18 : DltReturnValue dlt_log_string(DltContext *handle, DltLogLevelType loglevel, const char *text)
    3589              : {
    3590           36 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    3591              :         return DLT_RETURN_ERROR;
    3592              : 
    3593           18 :     if ((handle == NULL) || (text == NULL))
    3594              :         return DLT_RETURN_WRONG_PARAMETER;
    3595              : 
    3596              :     DltReturnValue ret = DLT_RETURN_OK;
    3597              :     DltContextData log;
    3598              : 
    3599           15 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    3600           11 :         ret = dlt_user_log_write_string(&log, text);
    3601              : 
    3602           11 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    3603              :             ret = DLT_RETURN_ERROR;
    3604              :     }
    3605              : 
    3606              :     return ret;
    3607              : }
    3608              : 
    3609           25 : DltReturnValue dlt_log_string_int(DltContext *handle, DltLogLevelType loglevel, const char *text, int data)
    3610              : {
    3611           50 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    3612              :         return DLT_RETURN_ERROR;
    3613              : 
    3614           25 :     if ((handle == NULL) || (text == NULL))
    3615              :         return DLT_RETURN_WRONG_PARAMETER;
    3616              : 
    3617              :     DltReturnValue ret = DLT_RETURN_OK;
    3618              :     DltContextData log;
    3619              : 
    3620           22 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    3621           16 :         ret = dlt_user_log_write_string(&log, text);
    3622           16 :         dlt_user_log_write_int(&log, data);
    3623              : 
    3624           16 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    3625              :             ret = DLT_RETURN_ERROR;
    3626              :     }
    3627              : 
    3628              :     return ret;
    3629              : }
    3630              : 
    3631           25 : DltReturnValue dlt_log_string_uint(DltContext *handle, DltLogLevelType loglevel, const char *text, unsigned int data)
    3632              : {
    3633           50 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    3634              :         return DLT_RETURN_ERROR;
    3635              : 
    3636           25 :     if ((handle == NULL) || (text == NULL))
    3637              :         return DLT_RETURN_WRONG_PARAMETER;
    3638              : 
    3639              :     DltReturnValue ret = DLT_RETURN_OK;
    3640              :     DltContextData log;
    3641              : 
    3642           22 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    3643           16 :         ret = dlt_user_log_write_string(&log, text);
    3644           16 :         dlt_user_log_write_uint(&log, data);
    3645              : 
    3646           16 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    3647              :             ret = DLT_RETURN_ERROR;
    3648              :     }
    3649              : 
    3650              :     return ret;
    3651              : }
    3652              : 
    3653           22 : DltReturnValue dlt_log_int(DltContext *handle, DltLogLevelType loglevel, int data)
    3654              : {
    3655           44 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    3656              :         return DLT_RETURN_ERROR;
    3657              : 
    3658           22 :     if (handle == NULL)
    3659              :         return DLT_RETURN_ERROR;
    3660              : 
    3661              :     DltContextData log;
    3662              : 
    3663           21 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    3664           15 :         dlt_user_log_write_int(&log, data);
    3665              : 
    3666           15 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    3667              :             return DLT_RETURN_ERROR;
    3668              :     }
    3669              : 
    3670              :     return DLT_RETURN_OK;
    3671              : }
    3672              : 
    3673           22 : DltReturnValue dlt_log_uint(DltContext *handle, DltLogLevelType loglevel, unsigned int data)
    3674              : {
    3675           44 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    3676              :         return DLT_RETURN_ERROR;
    3677              : 
    3678           22 :     if (handle == NULL)
    3679              :         return DLT_RETURN_WRONG_PARAMETER;
    3680              : 
    3681              :     DltContextData log;
    3682              : 
    3683           21 :     if (dlt_user_log_write_start(handle, &log, loglevel) == DLT_RETURN_TRUE) {
    3684           15 :         dlt_user_log_write_uint(&log, data);
    3685              : 
    3686           15 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    3687              :             return DLT_RETURN_ERROR;
    3688              :     }
    3689              : 
    3690              :     return DLT_RETURN_OK;
    3691              : }
    3692              : 
    3693           11 : DltReturnValue dlt_log_raw(DltContext *handle, DltLogLevelType loglevel, void *data, uint16_t length)
    3694              : {
    3695           22 :     if (!is_verbose_mode(dlt_user.verbose_mode, NULL))
    3696              :         return DLT_RETURN_ERROR;
    3697              : 
    3698           11 :     if (handle == NULL)
    3699              :         return DLT_RETURN_WRONG_PARAMETER;
    3700              : 
    3701              :     DltContextData log;
    3702              :     DltReturnValue ret = DLT_RETURN_OK;
    3703              : 
    3704            9 :     if (dlt_user_log_write_start(handle, &log, loglevel) > 0) {
    3705            7 :         if ((ret = dlt_user_log_write_raw(&log, data, length)) < DLT_RETURN_OK) {
    3706              :             dlt_user_free_buffer(&(log.buffer));
    3707            2 :             return ret;
    3708              :         }
    3709              : 
    3710            5 :         if (dlt_user_log_write_finish(&log) < DLT_RETURN_OK)
    3711              :             return DLT_RETURN_ERROR;
    3712              :     }
    3713              : 
    3714              :     return DLT_RETURN_OK;
    3715              : }
    3716              : 
    3717            1 : DltReturnValue dlt_log_marker()
    3718              : {
    3719            1 :     if (!DLT_USER_INITIALIZED) {
    3720            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3721            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3722            0 :             return DLT_RETURN_ERROR;
    3723              :         }
    3724              :     }
    3725              : 
    3726            1 :     return dlt_user_log_send_marker();
    3727              : }
    3728              : 
    3729           10 : DltReturnValue dlt_verbose_mode(void)
    3730              : {
    3731           10 :     if (!DLT_USER_INITIALIZED) {
    3732            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3733            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3734            0 :             return DLT_RETURN_ERROR;
    3735              :         }
    3736              :     }
    3737              : 
    3738              :     /* Switch to verbose mode */
    3739           10 :     dlt_user.verbose_mode = 1;
    3740              : 
    3741           10 :     return DLT_RETURN_OK;
    3742              : }
    3743              : 
    3744           10 : DltReturnValue dlt_nonverbose_mode(void)
    3745              : {
    3746           10 :     if (!DLT_USER_INITIALIZED) {
    3747            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3748            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3749            0 :             return DLT_RETURN_ERROR;
    3750              :         }
    3751              :     }
    3752              : 
    3753              :     /* Switch to non-verbose mode */
    3754           10 :     dlt_user.verbose_mode = 0;
    3755              : 
    3756           10 :     return DLT_RETURN_OK;
    3757              : }
    3758              : 
    3759            2 : DltReturnValue dlt_use_extended_header_for_non_verbose(int8_t use_extended_header_for_non_verbose)
    3760              : {
    3761            2 :     if (!DLT_USER_INITIALIZED) {
    3762            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3763            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3764            0 :             return DLT_RETURN_ERROR;
    3765              :         }
    3766              :     }
    3767              : 
    3768              :     /* Set use_extended_header_for_non_verbose */
    3769            2 :     dlt_user.use_extended_header_for_non_verbose = use_extended_header_for_non_verbose;
    3770              : 
    3771            2 :     return DLT_RETURN_OK;
    3772              : }
    3773              : 
    3774            0 : DltReturnValue dlt_with_session_id(int8_t with_session_id)
    3775              : {
    3776            0 :     if (!DLT_USER_INITIALIZED) {
    3777            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3778            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3779            0 :             return DLT_RETURN_ERROR;
    3780              :         }
    3781              :     }
    3782              : 
    3783              :     /* Set use_extended_header_for_non_verbose */
    3784            0 :     dlt_user.with_session_id = with_session_id;
    3785              : 
    3786            0 :     return DLT_RETURN_OK;
    3787              : }
    3788              : 
    3789            0 : DltReturnValue dlt_with_timestamp(int8_t with_timestamp)
    3790              : {
    3791            0 :     if (!DLT_USER_INITIALIZED) {
    3792            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3793            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3794            0 :             return DLT_RETURN_ERROR;
    3795              :         }
    3796              :     }
    3797              : 
    3798              :     /* Set with_timestamp */
    3799            0 :     dlt_user.with_timestamp = with_timestamp;
    3800              : 
    3801            0 :     return DLT_RETURN_OK;
    3802              : }
    3803              : 
    3804            0 : DltReturnValue dlt_with_ecu_id(int8_t with_ecu_id)
    3805              : {
    3806            0 :     if (!DLT_USER_INITIALIZED) {
    3807            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3808            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3809            0 :             return DLT_RETURN_ERROR;
    3810              :         }
    3811              :     }
    3812              : 
    3813              :     /* Set with_timestamp */
    3814            0 :     dlt_user.with_ecu_id = with_ecu_id;
    3815              : 
    3816            0 :     return DLT_RETURN_OK;
    3817              : }
    3818              : 
    3819            0 : DltReturnValue dlt_enable_local_print(void)
    3820              : {
    3821            0 :     if (!DLT_USER_INITIALIZED) {
    3822            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3823            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3824            0 :             return DLT_RETURN_ERROR;
    3825              :         }
    3826              :     }
    3827              : 
    3828            0 :     dlt_user.enable_local_print = 1;
    3829              : 
    3830            0 :     return DLT_RETURN_OK;
    3831              : }
    3832              : 
    3833            0 : DltReturnValue dlt_disable_local_print(void)
    3834              : {
    3835            0 :     if (!DLT_USER_INITIALIZED) {
    3836            0 :         if (dlt_init() < DLT_RETURN_OK) {
    3837            0 :             dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3838            0 :             return DLT_RETURN_ERROR;
    3839              :         }
    3840              :     }
    3841              : 
    3842            0 :     dlt_user.enable_local_print = 0;
    3843              : 
    3844            0 :     return DLT_RETURN_OK;
    3845              : }
    3846              : 
    3847              : /* Cleanup on thread cancellation, thread may hold lock release it here */
    3848        42531 : static void dlt_user_cleanup_handler(void *arg)
    3849              : {
    3850              :     DLT_UNUSED(arg); /* Satisfy compiler */
    3851              : 
    3852              : #ifdef DLT_NETWORK_TRACE_ENABLE
    3853              :     /* unlock the message queue */
    3854        42531 :     dlt_unlock_mutex(&mq_mutex);
    3855              : #endif
    3856              : 
    3857              :     /* unlock DLT (dlt_mutex) */
    3858        42532 :     DLT_SEM_FREE();
    3859        42532 : }
    3860              : 
    3861        21266 : void dlt_user_housekeeperthread_function(void *ptr)
    3862              : {
    3863              :     struct timespec ts;
    3864              :     bool in_loop = true;
    3865              :     int signal_status = 0;
    3866              :     atomic_bool* dlt_housekeeper_running = (atomic_bool*)ptr;
    3867              : 
    3868              : #ifdef __ANDROID_API__
    3869              :     sigset_t set;
    3870              :     sigset_t pset;
    3871              :     /*
    3872              :      * bionic is not supporting pthread_cancel so
    3873              :      * use SIGUSR1 to kill thread properly.
    3874              :      */
    3875              :     sigemptyset(&set);
    3876              :     sigaddset(&set, SIGUSR1);
    3877              :     if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
    3878              :         dlt_vlog(LOG_ERR, "Failed to block signal with error [%s]\n",
    3879              :                 strerror(errno));
    3880              :         in_loop = false;
    3881              :     }
    3882              : #endif
    3883              : 
    3884              : #ifdef DLT_USE_PTHREAD_SETNAME_NP
    3885        21266 :     if (pthread_setname_np(dlt_housekeeperthread_handle, "dlt_housekeeper"))
    3886            0 :         dlt_log(LOG_WARNING, "Failed to rename housekeeper thread!\n");
    3887              : #elif linux
    3888              :     if (prctl(PR_SET_NAME, "dlt_housekeeper", 0, 0, 0) < 0)
    3889              :         dlt_log(LOG_WARNING, "Failed to rename housekeeper thread!\n");
    3890              : #endif
    3891              : 
    3892        42532 :     pthread_cleanup_push(dlt_user_cleanup_handler, NULL);
    3893              : 
    3894              : 
    3895        21266 :     pthread_mutex_lock(&dlt_housekeeper_running_mutex);
    3896              : 
    3897              :     // signal dlt thread to be running
    3898        21266 :     *dlt_housekeeper_running = true;
    3899        21266 :     signal_status = pthread_cond_signal(&dlt_housekeeper_running_cond);
    3900        21266 :     if (signal_status != 0) {
    3901            0 :         dlt_log(LOG_CRIT, "Housekeeper thread failed to signal running state\n");
    3902              :     }
    3903              : 
    3904        21266 :     pthread_mutex_unlock(&dlt_housekeeper_running_mutex);
    3905              : 
    3906              :     while (in_loop) {
    3907              :         /* Check for new messages from DLT daemon */
    3908        21282 :         if (!dlt_user.disable_injection_msg)
    3909        21282 :             if (dlt_user_log_check_user_message() < DLT_RETURN_OK)
    3910              :                 /* Critical error */
    3911            0 :                 dlt_log(LOG_CRIT, "Housekeeper thread encountered error condition\n");
    3912              : 
    3913              :         /* Reattach to daemon if neccesary */
    3914           21 :         dlt_user_log_reattach_to_daemon();
    3915              : 
    3916              :         /* flush buffer to DLT daemon if possible */
    3917           21 :         if (dlt_user.dlt_log_handle != DLT_FD_INIT)
    3918           10 :             dlt_user_log_resend_buffer();
    3919              : 
    3920              : #ifdef __ANDROID_API__
    3921              :         if (sigpending(&pset)) {
    3922              :             dlt_vlog(LOG_ERR, "sigpending failed with error [%s]!\n", strerror(errno));
    3923              :             break;
    3924              :         }
    3925              : 
    3926              :         if (sigismember(&pset, SIGUSR1)) {
    3927              :             dlt_log(LOG_NOTICE, "Received SIGUSR1! Stop thread\n");
    3928              :             break;
    3929              :         }
    3930              : #endif
    3931              : 
    3932              :         /* delay */
    3933           21 :         ts.tv_sec = 0;
    3934           21 :         ts.tv_nsec = DLT_USER_RECEIVE_NDELAY;
    3935           21 :         nanosleep(&ts, NULL);
    3936              :     }
    3937              : 
    3938              :     pthread_cleanup_pop(1);
    3939              : }
    3940              : 
    3941              : /* Private functions of user library */
    3942              : 
    3943         6411 : DltReturnValue dlt_user_log_init(DltContext *handle, DltContextData *log)
    3944              : {
    3945              :     int ret = DLT_RETURN_OK;
    3946              : 
    3947         6411 :     if ((handle == NULL) || (log == NULL))
    3948              :         return DLT_RETURN_WRONG_PARAMETER;
    3949              : 
    3950         6411 :     if (!DLT_USER_INITIALIZED) {
    3951            0 :         ret = dlt_init();
    3952              : 
    3953            0 :         if (ret < DLT_RETURN_OK) {
    3954            0 :             if (ret != DLT_RETURN_LOGGING_DISABLED)
    3955            0 :                 dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__);
    3956              : 
    3957            0 :             return ret;
    3958              :         }
    3959              :     }
    3960              : 
    3961         6411 :     log->handle = handle;
    3962         6411 :     log->buffer = NULL;
    3963         6411 :     return ret;
    3964              : }
    3965              : 
    3966         6008 : DltReturnValue dlt_user_log_send_log(DltContextData *log, const int mtype, int *const sent_size)
    3967              : {
    3968              :     DltMessage msg;
    3969              :     DltUserHeader userheader;
    3970              :     int32_t len;
    3971              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    3972              :     uint32_t time_stamp;
    3973              : #else
    3974              :     // shut up warning
    3975              :     (void)sent_size;
    3976              : #endif
    3977              : 
    3978              :     DltReturnValue ret = DLT_RETURN_OK;
    3979              : 
    3980         6008 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    3981            0 :         dlt_vlog(LOG_WARNING, "%s dlt_user_init_state=%i (expected INIT_DONE), dlt_user_freeing=%i\n", __FUNCTION__, dlt_user_init_state, dlt_user_freeing);
    3982            0 :         return DLT_RETURN_ERROR;
    3983              :     }
    3984              : 
    3985         6008 :     if ((log == NULL) ||
    3986         6008 :         (log->handle == NULL) ||
    3987         5999 :         (log->handle->contextID[0] == '\0') ||
    3988         5999 :         (mtype < DLT_TYPE_LOG) || (mtype > DLT_TYPE_CONTROL)
    3989              :         )
    3990              :         return DLT_RETURN_WRONG_PARAMETER;
    3991              : 
    3992              :     /* also for Trace messages */
    3993         5999 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG) < DLT_RETURN_OK)
    3994              :         return DLT_RETURN_ERROR;
    3995              : 
    3996         5999 :     if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR)
    3997              :         return DLT_RETURN_ERROR;
    3998              : 
    3999         5999 :     msg.storageheader = (DltStorageHeader *)msg.headerbuffer;
    4000              : 
    4001         5999 :     if (dlt_set_storageheader(msg.storageheader, dlt_user.ecuID) == DLT_RETURN_ERROR)
    4002              :         return DLT_RETURN_ERROR;
    4003              : 
    4004         5999 :     msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader));
    4005         5999 :     msg.standardheader->htyp = DLT_HTYP_PROTOCOL_VERSION1;
    4006              : 
    4007              :     /* send ecu id */
    4008         5999 :     if (dlt_user.with_ecu_id)
    4009         5999 :         msg.standardheader->htyp |= DLT_HTYP_WEID;
    4010              : 
    4011              :     /* send timestamp */
    4012         5999 :     if (dlt_user.with_timestamp)
    4013         5999 :         msg.standardheader->htyp |= DLT_HTYP_WTMS;
    4014              : 
    4015              :     /* send session id */
    4016         5999 :     if (dlt_user.with_session_id) {
    4017         5999 :         msg.standardheader->htyp |= DLT_HTYP_WSID;
    4018         5999 :         if (__builtin_expect(!!(dlt_user.local_pid == -1), false)) {
    4019           19 :             dlt_user.local_pid = getpid();
    4020              :         }
    4021         5999 :         msg.headerextra.seid = (uint32_t) dlt_user.local_pid;
    4022              :     }
    4023              : 
    4024         5999 :     if (is_verbose_mode(dlt_user.verbose_mode, log))
    4025              :         /* In verbose mode, send extended header */
    4026         5996 :         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH);
    4027              :     else
    4028              :         /* In non-verbose, send extended header if desired */
    4029            3 :         if (dlt_user.use_extended_header_for_non_verbose)
    4030            2 :             msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH);
    4031              : 
    4032              : #if (BYTE_ORDER == BIG_ENDIAN)
    4033              :     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
    4034              : #endif
    4035              : 
    4036         5999 :     msg.standardheader->mcnt = log->handle->mcnt++;
    4037              : 
    4038              :     /* Set header extra parameters */
    4039         5999 :     dlt_set_id(msg.headerextra.ecu, dlt_user.ecuID);
    4040              : 
    4041              :     /*msg.headerextra.seid = 0; */
    4042         5999 :     if (log->use_timestamp == DLT_AUTO_TIMESTAMP) {
    4043         5998 :         msg.headerextra.tmsp = dlt_uptime();
    4044              :     }
    4045              :     else {
    4046            1 :         msg.headerextra.tmsp = log->user_timestamp;
    4047              :     }
    4048              : 
    4049              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4050              :     time_stamp = msg.headerextra.tmsp;
    4051              : #endif
    4052              : 
    4053         5999 :     if (dlt_message_set_extraparameters(&msg, 0) == DLT_RETURN_ERROR)
    4054              :         return DLT_RETURN_ERROR;
    4055              : 
    4056              :     /* Fill out extended header, if extended header should be provided */
    4057         5999 :     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp)) {
    4058              :         /* with extended header */
    4059         5998 :         msg.extendedheader =
    4060         5998 :             (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    4061         5998 :                                   DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
    4062              : 
    4063         5998 :         switch (mtype) {
    4064         5998 :         case DLT_TYPE_LOG:
    4065              :         {
    4066         5998 :             msg.extendedheader->msin = (uint8_t) (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT |
    4067         5998 :                 ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    4068         5998 :             break;
    4069              :         }
    4070            0 :         case DLT_TYPE_NW_TRACE:
    4071              :         {
    4072            0 :             msg.extendedheader->msin = (uint8_t) (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT |
    4073            0 :                 ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    4074            0 :             break;
    4075              :         }
    4076              :         default:
    4077              :         {
    4078              :             /* This case should not occur */
    4079              :             return DLT_RETURN_ERROR;
    4080              :             break;
    4081              :         }
    4082              :         }
    4083              : 
    4084              :         /* If in verbose mode, set flag in header for verbose mode */
    4085         5998 :         if (is_verbose_mode(dlt_user.verbose_mode, log))
    4086         5996 :             msg.extendedheader->msin |= DLT_MSIN_VERB;
    4087              : 
    4088         5998 :         msg.extendedheader->noar = (uint8_t) log->args_num;              /* number of arguments */
    4089         5998 :         dlt_set_id(msg.extendedheader->apid, dlt_user.appID);       /* application id */
    4090         5998 :         dlt_set_id(msg.extendedheader->ctid, log->handle->contextID);   /* context id */
    4091              : 
    4092         5998 :         msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) +
    4093         5998 :             DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
    4094              :     }
    4095              :     else {
    4096              :         /* without extended header */
    4097            1 :         msg.headersize = (uint32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(
    4098              :             msg.standardheader->htyp));
    4099              :     }
    4100              : 
    4101         5999 :     len = (int32_t) (msg.headersize - sizeof(DltStorageHeader) + log->size);
    4102              : 
    4103         5999 :     if (len > UINT16_MAX) {
    4104            0 :         dlt_log(LOG_WARNING, "Huge message discarded!\n");
    4105            0 :         return DLT_RETURN_ERROR;
    4106              :     }
    4107              : 
    4108         5999 :     msg.standardheader->len = DLT_HTOBE_16(len);
    4109              : 
    4110              :     /* print to std out, if enabled */
    4111         5999 :     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
    4112              :         (dlt_user.local_print_mode != DLT_PM_AUTOMATIC)) {
    4113         5999 :         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
    4114            0 :             if (dlt_user_print_msg(&msg, log) == DLT_RETURN_ERROR)
    4115              :                 return DLT_RETURN_ERROR;
    4116              :     }
    4117              : 
    4118         5999 :     if (dlt_user.dlt_is_file) {
    4119            0 :         if (dlt_user_file_reach_max) {
    4120              :             return DLT_RETURN_FILESZERR;
    4121              :         }
    4122              :         else {
    4123              :             /* Get file size */
    4124              :             struct stat st;
    4125            0 :             if(fstat(dlt_user.dlt_log_handle, &st) != 0) {
    4126            0 :                 dlt_vlog(LOG_WARNING,
    4127            0 :                      "%s: Cannot get file information (errno=%d)\n", __func__, errno);
    4128            0 :                 return DLT_RETURN_ERROR;
    4129              :             }
    4130              : 
    4131            0 :             dlt_vlog(LOG_DEBUG, "%s: Current file size=[%ld]\n", __func__,
    4132              :                      st.st_size);
    4133              :             /* Check filesize */
    4134              :             /* Return error if the file size has reached to maximum */
    4135            0 :             unsigned int msg_size = st.st_size + (unsigned int) msg.headersize +
    4136            0 :                                     (unsigned int) log->size;
    4137            0 :             if (msg_size > dlt_user.filesize_max) {
    4138            0 :                 dlt_user_file_reach_max = true;
    4139            0 :                 dlt_vlog(LOG_ERR,
    4140              :                          "%s: File size (%ld bytes) reached to defined maximum size (%d bytes)\n",
    4141              :                          __func__, st.st_size, dlt_user.filesize_max);
    4142            0 :                 return DLT_RETURN_FILESZERR;
    4143              :             }
    4144              :             else {
    4145              :                 /* log to file */
    4146            0 :                 ret = dlt_user_log_out2(dlt_user.dlt_log_handle,
    4147              :                                         msg.headerbuffer, msg.headersize,
    4148            0 :                                         log->buffer, log->size);
    4149            0 :                 return ret;
    4150              :             }
    4151              :         }
    4152              :     } else {
    4153         5999 :         if (dlt_user.overflow_counter) {
    4154            0 :             if (dlt_user_log_send_overflow() == DLT_RETURN_OK) {
    4155            0 :                 dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "%u messages discarded!\n", dlt_user.overflow_counter);
    4156            0 :                 dlt_user.overflow_counter = 0;
    4157              :             }
    4158              :         }
    4159              : 
    4160              :         /* try to resent old data first */
    4161              :         ret = DLT_RETURN_OK;
    4162              : 
    4163         5999 :         if ((dlt_user.dlt_log_handle != -1) && (dlt_user.appID[0] != '\0'))
    4164         5812 :             ret = dlt_user_log_resend_buffer();
    4165              : 
    4166         5999 :         if ((ret == DLT_RETURN_OK) && (dlt_user.appID[0] != '\0')) {
    4167              :             /* resend ok or nothing to resent */
    4168              : #ifdef DLT_SHM_ENABLE
    4169              : 
    4170              :             if (dlt_user.dlt_log_handle != -1)
    4171              :                 dlt_shm_push(&dlt_user.dlt_shm, msg.headerbuffer + sizeof(DltStorageHeader),
    4172              :                              msg.headersize - sizeof(DltStorageHeader),
    4173              :                              log->buffer, log->size, 0, 0);
    4174              : 
    4175              :             ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
    4176              :                                     &(userheader), sizeof(DltUserHeader),
    4177              :                                     0, 0,
    4178              :                                     0, 0);
    4179              : #else
    4180              : #   ifdef DLT_TEST_ENABLE
    4181              : 
    4182              :             if (dlt_user.corrupt_user_header) {
    4183              :                 userheader.pattern[0] = (char) 0xff;
    4184              :                 userheader.pattern[1] = (char) 0xff;
    4185              :                 userheader.pattern[2] = (char) 0xff;
    4186              :                 userheader.pattern[3] = (char) 0xff;
    4187              :             }
    4188              : 
    4189              :             if (dlt_user.corrupt_message_size)
    4190              :                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
    4191              : 
    4192              : #   endif
    4193              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4194              :             /* check trace load before output */
    4195              :             if (!sent_size)
    4196              :             {
    4197              :                 pthread_rwlock_wrlock(&trace_load_rw_lock);
    4198              :                 DltTraceLoadSettings* settings =
    4199              :                     dlt_find_runtime_trace_load_settings(
    4200              :                         trace_load_settings, trace_load_settings_count, dlt_user.appID, log->handle->contextID);
    4201              :                 const bool trace_load_in_limits = dlt_check_trace_load(
    4202              :                         settings,
    4203              :                         log->log_level, time_stamp,
    4204              :                         sizeof(DltUserHeader)
    4205              :                             + msg.headersize - sizeof(DltStorageHeader)
    4206              :                             + log->size,
    4207              :                         dlt_user_output_internal_msg,
    4208              :                         NULL);
    4209              :                 pthread_rwlock_unlock(&trace_load_rw_lock);
    4210              :                 if (!trace_load_in_limits){
    4211              :                     return DLT_RETURN_LOAD_EXCEEDED;
    4212              :                 }
    4213              :             }
    4214              :             else
    4215              :             {
    4216              :                 *sent_size = (sizeof(DltUserHeader) + msg.headersize - sizeof(DltStorageHeader) + log->size);
    4217              :             }
    4218              : #endif
    4219              : 
    4220         5998 :             ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
    4221              :                                     &(userheader), sizeof(DltUserHeader),
    4222              :                                     msg.headerbuffer + sizeof(DltStorageHeader),
    4223         5998 :                                     msg.headersize - sizeof(DltStorageHeader),
    4224         5998 :                                     log->buffer, log->size);
    4225              : #endif
    4226              :         }
    4227              : 
    4228              :         DltReturnValue process_error_ret = DLT_RETURN_OK;
    4229              :         /* store message in ringbuffer, if an error has occurred */
    4230              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4231              :         if (((ret!=DLT_RETURN_OK) || (dlt_user.appID[0] == '\0')) && !sent_size)
    4232              : #else
    4233         5998 :         if ((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0'))
    4234              : #endif
    4235          189 :             process_error_ret = dlt_user_log_out_error_handling(&(userheader),
    4236              :                                                   sizeof(DltUserHeader),
    4237              :                                                   msg.headerbuffer + sizeof(DltStorageHeader),
    4238          189 :                                                   msg.headersize - sizeof(DltStorageHeader),
    4239          189 :                                                   log->buffer,
    4240          189 :                                                   log->size);
    4241              : 
    4242          189 :         if (process_error_ret == DLT_RETURN_OK)
    4243         5999 :             return DLT_RETURN_OK;
    4244            0 :         if (process_error_ret == DLT_RETURN_BUFFER_FULL) {
    4245              :             /* Buffer full */
    4246            0 :             dlt_user.overflow_counter += 1;
    4247            0 :             return DLT_RETURN_BUFFER_FULL;
    4248              :         }
    4249              : 
    4250              :         /* handle return value of function dlt_user_log_out3() when process_error_ret < 0*/
    4251            0 :         switch (ret) {
    4252              :             case DLT_RETURN_PIPE_FULL:
    4253              :             {
    4254              :                 /* data could not be written */
    4255              :                 return DLT_RETURN_PIPE_FULL;
    4256              :             }
    4257            0 :             case DLT_RETURN_PIPE_ERROR:
    4258              :             {
    4259              :                 /* handle not open or pipe error */
    4260            0 :                 close(dlt_user.dlt_log_handle);
    4261            0 :                 dlt_user.dlt_log_handle = -1;
    4262              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    4263              :             dlt_user.connection_state = DLT_USER_RETRY_CONNECT;
    4264              : #endif
    4265              : 
    4266              :     #ifdef DLT_SHM_ENABLE
    4267              :             /* free shared memory */
    4268              :             dlt_shm_free_client(&dlt_user.dlt_shm);
    4269              :     #endif
    4270              : 
    4271            0 :             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
    4272            0 :                 dlt_user_print_msg(&msg, log);
    4273              : 
    4274            0 :             return DLT_RETURN_PIPE_ERROR;
    4275              :         }
    4276              :         case DLT_RETURN_ERROR:
    4277              :         {
    4278              :             /* other error condition */
    4279              :             return DLT_RETURN_ERROR;
    4280              :         }
    4281              :         case DLT_RETURN_OK:
    4282              :         {
    4283              :             return DLT_RETURN_OK;
    4284              :         }
    4285              :         default:
    4286              :         {
    4287              :             /* This case should never occur. */
    4288              :             return DLT_RETURN_ERROR;
    4289              :         }
    4290              :         }
    4291              :     }
    4292              : 
    4293              :     return DLT_RETURN_OK;
    4294              : }
    4295              : 
    4296          171 : DltReturnValue dlt_user_log_send_register_application(void)
    4297              : {
    4298              :     DltUserHeader userheader;
    4299              :     DltUserControlMsgRegisterApplication usercontext;
    4300              : 
    4301              :     DltReturnValue ret;
    4302              : 
    4303          171 :     if (dlt_user.appID[0] == '\0')
    4304              :         return DLT_RETURN_ERROR;
    4305              : 
    4306              :     /* set userheader */
    4307          171 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION) < DLT_RETURN_OK)
    4308              :         return DLT_RETURN_ERROR;
    4309              : 
    4310              :     /* set usercontext */
    4311          171 :     dlt_set_id(usercontext.apid, dlt_user.appID);       /* application id */
    4312          171 :     usercontext.pid = getpid();
    4313              : 
    4314          171 :     if (dlt_user.application_description != NULL)
    4315          171 :         usercontext.description_length = (uint32_t) strlen(dlt_user.application_description);
    4316              :     else
    4317            0 :         usercontext.description_length = 0;
    4318              : 
    4319          171 :     if (dlt_user.dlt_is_file)
    4320              :         return DLT_RETURN_OK;
    4321              : 
    4322          171 :     ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
    4323              :                             &(userheader), sizeof(DltUserHeader),
    4324              :                             &(usercontext), sizeof(DltUserControlMsgRegisterApplication),
    4325          171 :                             dlt_user.application_description, usercontext.description_length);
    4326              : 
    4327              :     /* store message in ringbuffer, if an error has occured */
    4328          171 :     if (ret < DLT_RETURN_OK)
    4329          164 :         return dlt_user_log_out_error_handling(&(userheader),
    4330              :                                                sizeof(DltUserHeader),
    4331              :                                                &(usercontext),
    4332              :                                                sizeof(DltUserControlMsgRegisterApplication),
    4333          164 :                                                dlt_user.application_description,
    4334          164 :                                                usercontext.description_length);
    4335              : 
    4336              :     return DLT_RETURN_OK;
    4337              : }
    4338              : 
    4339          181 : DltReturnValue dlt_user_log_send_unregister_application(void)
    4340              : {
    4341              :     DltUserHeader userheader;
    4342              :     DltUserControlMsgUnregisterApplication usercontext;
    4343              :     DltReturnValue ret = DLT_RETURN_OK;
    4344              : 
    4345          181 :     if (dlt_user.appID[0] == '\0')
    4346              :         return DLT_RETURN_ERROR;
    4347              : 
    4348              :     /* set userheader */
    4349          172 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION) < DLT_RETURN_OK)
    4350              :         return DLT_RETURN_ERROR;
    4351              : 
    4352              :     /* set usercontext */
    4353          172 :     dlt_set_id(usercontext.apid, dlt_user.appID);       /* application id */
    4354          172 :     usercontext.pid = getpid();
    4355              : 
    4356          172 :     if (dlt_user.dlt_is_file)
    4357              :         return DLT_RETURN_OK;
    4358              : 
    4359          172 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle,
    4360              :                             &(userheader), sizeof(DltUserHeader),
    4361              :                             &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
    4362              : 
    4363              :     /* store message in ringbuffer, if an error has occured */
    4364          172 :     if (ret < DLT_RETURN_OK)
    4365          166 :         return dlt_user_log_out_error_handling(&(userheader),
    4366              :                                                sizeof(DltUserHeader),
    4367              :                                                &(usercontext),
    4368              :                                                sizeof(DltUserControlMsgUnregisterApplication),
    4369              :                                                NULL,
    4370              :                                                0);
    4371              : 
    4372              :     return DLT_RETURN_OK;
    4373              : }
    4374              : 
    4375          205 : DltReturnValue dlt_user_log_send_register_context(DltContextData *log)
    4376              : {
    4377              :     DltUserHeader userheader;
    4378              :     DltUserControlMsgRegisterContext usercontext;
    4379              :     DltReturnValue ret = DLT_RETURN_ERROR;
    4380              : 
    4381          205 :     if (log == NULL)
    4382              :         return DLT_RETURN_WRONG_PARAMETER;
    4383              : 
    4384          205 :     if (log->handle == NULL)
    4385              :         return DLT_RETURN_ERROR;
    4386              : 
    4387          205 :     if (log->handle->contextID[0] == '\0')
    4388              :         return DLT_RETURN_ERROR;
    4389              : 
    4390              :     /* set userheader */
    4391          205 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT) < DLT_RETURN_OK)
    4392              :         return DLT_RETURN_ERROR;
    4393              : 
    4394              :     /* set usercontext */
    4395          205 :     dlt_set_id(usercontext.apid, dlt_user.appID);       /* application id */
    4396          205 :     dlt_set_id(usercontext.ctid, log->handle->contextID);       /* context id */
    4397          205 :     usercontext.log_level_pos = log->handle->log_level_pos;
    4398          205 :     usercontext.pid = getpid();
    4399              : 
    4400          205 :     usercontext.log_level = (int8_t) log->log_level;
    4401          205 :     usercontext.trace_status = (int8_t) log->trace_status;
    4402              : 
    4403          205 :     if (log->context_description != NULL)
    4404          205 :         usercontext.description_length = (uint32_t) strlen(log->context_description);
    4405              :     else
    4406            0 :         usercontext.description_length = 0;
    4407              : 
    4408          205 :     if (dlt_user.dlt_is_file)
    4409              :         return DLT_RETURN_OK;
    4410              : 
    4411          205 :     if (dlt_user.appID[0] != '\0')
    4412              :         ret =
    4413          205 :             dlt_user_log_out3(dlt_user.dlt_log_handle,
    4414              :                               &(userheader),
    4415              :                               sizeof(DltUserHeader),
    4416              :                               &(usercontext),
    4417              :                               sizeof(DltUserControlMsgRegisterContext),
    4418              :                               log->context_description,
    4419          205 :                               usercontext.description_length);
    4420              : 
    4421              :     /* store message in ringbuffer, if an error has occured */
    4422          205 :     if ((ret != DLT_RETURN_OK) || (dlt_user.appID[0] == '\0'))
    4423          167 :         return dlt_user_log_out_error_handling(&(userheader),
    4424              :                                                sizeof(DltUserHeader),
    4425              :                                                &(usercontext),
    4426              :                                                sizeof(DltUserControlMsgRegisterContext),
    4427          167 :                                                log->context_description,
    4428          167 :                                                usercontext.description_length);
    4429              : 
    4430              :     return DLT_RETURN_OK;
    4431              : 
    4432              : }
    4433              : 
    4434          204 : DltReturnValue dlt_user_log_send_unregister_context(DltContextData *log)
    4435              : {
    4436              :     DltUserHeader userheader;
    4437              :     DltUserControlMsgUnregisterContext usercontext;
    4438              :     DltReturnValue ret;
    4439              : 
    4440          204 :     if (log == NULL)
    4441              :         return DLT_RETURN_WRONG_PARAMETER;
    4442              : 
    4443          204 :     if (log->handle == NULL)
    4444              :         return DLT_RETURN_WRONG_PARAMETER;
    4445              : 
    4446          204 :     if (log->handle->contextID[0] == '\0')
    4447              :         return DLT_RETURN_ERROR;
    4448              : 
    4449              :     /* set userheader */
    4450          204 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT) < DLT_RETURN_OK)
    4451              :         return DLT_RETURN_ERROR;
    4452              : 
    4453              :     /* set usercontext */
    4454          204 :     dlt_set_id(usercontext.apid, dlt_user.appID);       /* application id */
    4455          204 :     dlt_set_id(usercontext.ctid, log->handle->contextID);       /* context id */
    4456          204 :     usercontext.pid = getpid();
    4457              : 
    4458          204 :     if (dlt_user.dlt_is_file)
    4459              :         return DLT_RETURN_OK;
    4460              : 
    4461          204 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle,
    4462              :                             &(userheader),
    4463              :                             sizeof(DltUserHeader),
    4464              :                             &(usercontext),
    4465              :                             sizeof(DltUserControlMsgUnregisterContext));
    4466              : 
    4467              :     /* store message in ringbuffer, if an error has occured */
    4468          204 :     if (ret < DLT_RETURN_OK)
    4469          167 :         return dlt_user_log_out_error_handling(&(userheader),
    4470              :                                                sizeof(DltUserHeader),
    4471              :                                                &(usercontext),
    4472              :                                                sizeof(DltUserControlMsgUnregisterContext),
    4473              :                                                NULL,
    4474              :                                                0);
    4475              : 
    4476              :     return DLT_RETURN_OK;
    4477              : }
    4478              : 
    4479            0 : DltReturnValue dlt_send_app_ll_ts_limit(const char *apid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
    4480              : {
    4481              :     DltUserHeader userheader;
    4482              :     DltUserControlMsgAppLogLevelTraceStatus usercontext;
    4483              :     DltReturnValue ret;
    4484              : 
    4485            0 :     if ((loglevel < DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel >= DLT_LOG_MAX)) {
    4486            0 :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    4487            0 :         return DLT_RETURN_ERROR;
    4488              :     }
    4489              : 
    4490            0 :     if ((tracestatus < DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus >= DLT_TRACE_STATUS_MAX)) {
    4491            0 :         dlt_vlog(LOG_ERR, "Tracestatus %d is outside valid range", tracestatus);
    4492            0 :         return DLT_RETURN_ERROR;
    4493              :     }
    4494              : 
    4495            0 :     if ((apid == NULL) || (apid[0] == '\0'))
    4496              :         return DLT_RETURN_ERROR;
    4497              : 
    4498              :     /* set userheader */
    4499            0 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS) < DLT_RETURN_OK)
    4500              :         return DLT_RETURN_ERROR;
    4501              : 
    4502              :     /* set usercontext */
    4503            0 :     dlt_set_id(usercontext.apid, apid);       /* application id */
    4504            0 :     usercontext.log_level = loglevel;
    4505            0 :     usercontext.trace_status = tracestatus;
    4506              : 
    4507            0 :     if (dlt_user.dlt_is_file)
    4508              :         return DLT_RETURN_OK;
    4509              : 
    4510            0 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle,
    4511              :                             &(userheader), sizeof(DltUserHeader),
    4512              :                             &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
    4513              : 
    4514              :     /* store message in ringbuffer, if an error has occured */
    4515            0 :     if (ret < DLT_RETURN_OK)
    4516            0 :         return dlt_user_log_out_error_handling(&(userheader),
    4517              :                                                sizeof(DltUserHeader),
    4518              :                                                &(usercontext),
    4519              :                                                sizeof(DltUserControlMsgAppLogLevelTraceStatus),
    4520              :                                                NULL,
    4521              :                                                0);
    4522              : 
    4523              :     return DLT_RETURN_OK;
    4524              : }
    4525              : 
    4526            4 : DltReturnValue dlt_user_log_send_log_mode(DltUserLogMode mode)
    4527              : {
    4528              :     DltUserHeader userheader;
    4529              :     DltUserControlMsgLogMode logmode;
    4530              :     DltReturnValue ret;
    4531              : 
    4532            4 :     if ((mode < DLT_USER_MODE_UNDEFINED) || (mode >= DLT_USER_MODE_MAX)) {
    4533            0 :         dlt_vlog(LOG_ERR, "User log mode %d is outside valid range", mode);
    4534            0 :         return DLT_RETURN_WRONG_PARAMETER;
    4535              :     }
    4536              : 
    4537              :     /* set userheader */
    4538            4 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE) < DLT_RETURN_OK)
    4539              :         return DLT_RETURN_ERROR;
    4540              : 
    4541              :     /* set data */
    4542            4 :     logmode.log_mode = (unsigned char)mode;
    4543              : 
    4544            4 :     if (dlt_user.dlt_is_file)
    4545              :         return DLT_RETURN_OK;
    4546              : 
    4547            4 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle,
    4548              :                             &(userheader), sizeof(DltUserHeader),
    4549              :                             &(logmode), sizeof(DltUserControlMsgLogMode));
    4550              : 
    4551              :     /* store message in ringbuffer, if an error has occured */
    4552            4 :     if (ret < DLT_RETURN_OK)
    4553            4 :         return dlt_user_log_out_error_handling(&(userheader),
    4554              :                                                sizeof(DltUserHeader),
    4555              :                                                &(logmode),
    4556              :                                                sizeof(DltUserControlMsgLogMode),
    4557              :                                                NULL,
    4558              :                                                0);
    4559              : 
    4560              :     return DLT_RETURN_OK;
    4561              : }
    4562              : 
    4563            1 : DltReturnValue dlt_user_log_send_marker()
    4564              : {
    4565              :     DltUserHeader userheader;
    4566              :     DltReturnValue ret;
    4567              : 
    4568              :     /* set userheader */
    4569            1 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_MARKER) < DLT_RETURN_OK)
    4570              :         return DLT_RETURN_ERROR;
    4571              : 
    4572            1 :     if (dlt_user.dlt_is_file)
    4573              :         return DLT_RETURN_OK;
    4574              : 
    4575              :     /* log to FIFO */
    4576            1 :     ret = dlt_user_log_out2(dlt_user.dlt_log_handle,
    4577              :                             &(userheader), sizeof(DltUserHeader), 0, 0);
    4578              : 
    4579              :     /* store message in ringbuffer, if an error has occured */
    4580            1 :     if (ret < DLT_RETURN_OK)
    4581            1 :         return dlt_user_log_out_error_handling(&(userheader),
    4582              :                                                sizeof(DltUserHeader),
    4583              :                                                NULL,
    4584              :                                                0,
    4585              :                                                NULL,
    4586              :                                                0);
    4587              : 
    4588              :     return DLT_RETURN_OK;
    4589              : }
    4590              : 
    4591            0 : DltReturnValue dlt_user_print_msg(DltMessage *msg, DltContextData *log)
    4592              : {
    4593              :     uint8_t *databuffer_tmp;
    4594              :     uint32_t datasize_tmp;
    4595              :     uint32_t databuffersize_tmp;
    4596              :     static char text[DLT_USER_TEXT_LENGTH];
    4597              : 
    4598            0 :     if ((msg == NULL) || (log == NULL))
    4599              :         return DLT_RETURN_WRONG_PARAMETER;
    4600              : 
    4601              :     /* Save variables before print */
    4602            0 :     databuffer_tmp = msg->databuffer;
    4603            0 :     datasize_tmp = msg->datasize;
    4604            0 :     databuffersize_tmp = msg->databuffersize;
    4605              : 
    4606              :     /* Act like a receiver, convert header back to host format */
    4607            0 :     msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
    4608            0 :     dlt_message_get_extraparameters(msg, 0);
    4609              : 
    4610            0 :     msg->databuffer = log->buffer;
    4611            0 :     msg->datasize = (uint32_t) log->size;
    4612            0 :     msg->databuffersize = (uint32_t) log->size;
    4613              : 
    4614              :     /* Print message as ASCII */
    4615            0 :     if (dlt_message_print_ascii(msg, text, DLT_USER_TEXT_LENGTH, 0) == DLT_RETURN_ERROR)
    4616              :         return DLT_RETURN_ERROR;
    4617              : 
    4618              :     /* Restore variables and set len to BE*/
    4619            0 :     msg->databuffer = databuffer_tmp;
    4620            0 :     msg->databuffersize = databuffersize_tmp;
    4621            0 :     msg->datasize = datasize_tmp;
    4622              : 
    4623            0 :     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
    4624              : 
    4625            0 :     return DLT_RETURN_OK;
    4626              : }
    4627              : 
    4628        21282 : DltReturnValue dlt_user_log_check_user_message(void)
    4629              : {
    4630              :     int offset = 0;
    4631              :     int leave_while = 0;
    4632              :     int ret = 0;
    4633              : 
    4634              :     uint32_t i;
    4635              :     int fd;
    4636              :     struct pollfd nfd[1];
    4637              : 
    4638              :     DltUserHeader *userheader;
    4639              :     DltReceiver *receiver = &(dlt_user.receiver);
    4640              : 
    4641              :     DltUserControlMsgLogLevel *usercontextll;
    4642              :     DltUserControlMsgInjection *usercontextinj;
    4643              :     DltUserControlMsgLogState *userlogstate;
    4644              :     unsigned char *userbuffer;
    4645              : 
    4646              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4647              :     DltUserControlMsgTraceSettingMsg *trace_load_settings_user_messages;
    4648              :     uint32_t trace_load_settings_user_messages_count = 0;
    4649              :     uint32_t trace_load_settings_user_message_bytes_required = 0;
    4650              :     unsigned long trace_load_settings_alloc_size = 0;
    4651              : #endif
    4652              : 
    4653              :     /* For delayed calling of injection callback, to avoid deadlock */
    4654              :     DltUserInjectionCallback delayed_injection_callback;
    4655              :     DltUserLogLevelChangedCallback delayed_log_level_changed_callback;
    4656              :     unsigned char *delayed_inject_buffer = 0;
    4657              :     uint32_t delayed_inject_data_length = 0;
    4658              : 
    4659              :     /* Ensure that callback is null before searching for it */
    4660              :     delayed_injection_callback.injection_callback = 0;
    4661              :     delayed_injection_callback.injection_callback_with_id = 0;
    4662              :     delayed_injection_callback.service_id = 0;
    4663        21282 :     delayed_log_level_changed_callback.log_level_changed_callback = 0;
    4664              :     delayed_injection_callback.data = 0;
    4665              : 
    4666              : #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC
    4667              :     fd = dlt_user.dlt_log_handle;
    4668              : #else /* DLT_LIB_USE_FIFO_IPC */
    4669        21282 :     fd = dlt_user.dlt_user_handle;
    4670              : #endif
    4671        21282 :     nfd[0].events = POLLIN;
    4672        21282 :     nfd[0].fd = fd;
    4673              : 
    4674        21282 :     if (fd >= 0) {
    4675              :         ret = poll(nfd, 1, DLT_USER_RECEIVE_MDELAY);
    4676           21 :         if (ret) {
    4677            9 :             if (nfd[0].revents & (POLLHUP | POLLNVAL | POLLERR)) {
    4678            0 :                 dlt_user.dlt_log_handle = DLT_FD_INIT;
    4679            0 :                 return DLT_RETURN_ERROR;
    4680              :             }
    4681              : 
    4682            9 :             if (dlt_receiver_receive(receiver) <= 0)
    4683              :                 /* No new message available */
    4684              :                 return DLT_RETURN_OK;
    4685              : 
    4686              :             /* look through buffer as long as data is in there */
    4687              :             while (1) {
    4688           21 :                 if (receiver->bytesRcvd < (int32_t) sizeof(DltUserHeader))
    4689              :                     break;
    4690              : 
    4691              :                 /* resync if necessary */
    4692              :                 offset = 0;
    4693              : 
    4694              :                 do {
    4695           12 :                     userheader = (DltUserHeader *)(receiver->buf + offset);
    4696              : 
    4697              :                     /* Check for user header pattern */
    4698           12 :                     if (dlt_user_check_userheader(userheader))
    4699              :                         break;
    4700              : 
    4701            0 :                     offset++;
    4702              : 
    4703            0 :                 } while (((int32_t) (sizeof(DltUserHeader)) + offset) <= receiver->bytesRcvd);
    4704              : 
    4705              :                 /* Check for user header pattern */
    4706           24 :                 if ((dlt_user_check_userheader(userheader) < 0) ||
    4707           12 :                     (dlt_user_check_userheader(userheader) == 0))
    4708              :                     break;
    4709              : 
    4710              :                 /* Set new start offset */
    4711           12 :                 if (offset > 0) {
    4712            0 :                     receiver->buf += offset;
    4713            0 :                     receiver->bytesRcvd -= offset;
    4714              :                 }
    4715              : 
    4716           12 :                 switch (userheader->message) {
    4717            5 :                 case DLT_USER_MESSAGE_LOG_LEVEL:
    4718              :                 {
    4719            5 :                     if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel))) {
    4720              :                         leave_while = 1;
    4721              :                         break;
    4722              :                     }
    4723              : 
    4724            5 :                     usercontextll = (DltUserControlMsgLogLevel *)(receiver->buf + sizeof(DltUserHeader));
    4725              : 
    4726              :                     /* Update log level and trace status */
    4727              :                     if (usercontextll != NULL) {
    4728            5 :                         DLT_SEM_LOCK();
    4729              : 
    4730            5 :                         if ((usercontextll->log_level_pos >= 0) &&
    4731            5 :                             (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries)) {
    4732            5 :                             if (dlt_user.dlt_ll_ts) {
    4733            5 :                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = (int8_t) usercontextll->log_level;
    4734            5 :                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status =
    4735            5 :                                     (int8_t) usercontextll->trace_status;
    4736              : 
    4737            5 :                                 if (dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
    4738            0 :                                     *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) =
    4739              :                                         (int8_t) usercontextll->log_level;
    4740              : 
    4741            5 :                                 if (dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
    4742            0 :                                     *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) =
    4743            0 :                                         (int8_t) usercontextll->trace_status;
    4744              : 
    4745            5 :                                 delayed_log_level_changed_callback.log_level_changed_callback =
    4746            5 :                                     dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_changed_callback;
    4747              :                                 memcpy(delayed_log_level_changed_callback.contextID,
    4748              :                                        dlt_user.dlt_ll_ts[usercontextll->log_level_pos].contextID, DLT_ID_SIZE);
    4749            5 :                                 delayed_log_level_changed_callback.log_level = (int8_t) usercontextll->log_level;
    4750            5 :                                 delayed_log_level_changed_callback.trace_status = (int8_t) usercontextll->trace_status;
    4751              :                             }
    4752              :                         }
    4753              : 
    4754            5 :                         DLT_SEM_FREE();
    4755              :                     }
    4756              : 
    4757              :                     /* call callback outside of semaphore */
    4758            5 :                     if (delayed_log_level_changed_callback.log_level_changed_callback != 0)
    4759            0 :                         delayed_log_level_changed_callback.log_level_changed_callback(
    4760              :                             delayed_log_level_changed_callback.contextID,
    4761            0 :                             (uint8_t) delayed_log_level_changed_callback.log_level,
    4762            0 :                             (uint8_t) delayed_log_level_changed_callback.trace_status);
    4763              : 
    4764              :                     /* keep not read data in buffer */
    4765            5 :                     if (dlt_receiver_remove(receiver,
    4766              :                                             sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogLevel)) ==
    4767              :                         DLT_RETURN_ERROR)
    4768              :                         return DLT_RETURN_ERROR;
    4769              :                 }
    4770              :                 break;
    4771            0 :                 case DLT_USER_MESSAGE_INJECTION:
    4772              :                 {
    4773              :                     /* At least, user header, user context, and service id and data_length of injected message is available */
    4774            0 :                     if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection))) {
    4775              :                         leave_while = 1;
    4776              :                         break;
    4777              :                     }
    4778              : 
    4779            0 :                     usercontextinj = (DltUserControlMsgInjection *)(receiver->buf + sizeof(DltUserHeader));
    4780            0 :                     userbuffer =
    4781              :                         (unsigned char *)(receiver->buf + sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection));
    4782              : 
    4783              :                     if (userbuffer != NULL) {
    4784              : 
    4785            0 :                         if (receiver->bytesRcvd <
    4786            0 :                             (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgInjection) +
    4787            0 :                                       usercontextinj->data_length_inject)) {
    4788              :                             leave_while = 1;
    4789              :                             break;
    4790              :                         }
    4791              : 
    4792            0 :                         DLT_SEM_LOCK();
    4793              : 
    4794            0 :                         if ((usercontextinj->data_length_inject > 0) && (dlt_user.dlt_ll_ts))
    4795              :                             /* Check if injection callback is registered for this context */
    4796            0 :                             for (i = 0; i < dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks; i++)
    4797            0 :                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
    4798            0 :                                     (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id ==
    4799            0 :                                      usercontextinj->service_id)) {
    4800              :                                     /* Prepare delayed injection callback call */
    4801            0 :                                     if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].
    4802              :                                         injection_callback != NULL) {
    4803              :                                         delayed_injection_callback.injection_callback =
    4804              :                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].
    4805              :                                             injection_callback;
    4806              :                                     }
    4807            0 :                                     else if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].
    4808              :                                              injection_callback_with_id != NULL)
    4809              :                                     {
    4810              :                                         delayed_injection_callback.injection_callback_with_id =
    4811              :                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].
    4812              :                                             injection_callback_with_id;
    4813              :                                         delayed_injection_callback.data =
    4814            0 :                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].data;
    4815              :                                     }
    4816              : 
    4817              :                                     delayed_injection_callback.service_id = usercontextinj->service_id;
    4818              :                                     delayed_inject_data_length = usercontextinj->data_length_inject;
    4819            0 :                                     delayed_inject_buffer = malloc(delayed_inject_data_length);
    4820              : 
    4821            0 :                                     if (delayed_inject_buffer != NULL) {
    4822              :                                         memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
    4823              :                                     }
    4824              :                                     else {
    4825            0 :                                         DLT_SEM_FREE();
    4826            0 :                                         dlt_log(LOG_WARNING, "malloc failed!\n");
    4827            0 :                                         return DLT_RETURN_ERROR;
    4828              :                                     }
    4829              : 
    4830              :                                     break;
    4831              :                                 }
    4832              : 
    4833            0 :                         DLT_SEM_FREE();
    4834              : 
    4835              :                         /* Delayed injection callback call */
    4836            0 :                         if ((delayed_inject_buffer != NULL) &&
    4837              :                             (delayed_injection_callback.injection_callback != NULL)) {
    4838            0 :                             delayed_injection_callback.injection_callback(delayed_injection_callback.service_id,
    4839              :                                                                           delayed_inject_buffer,
    4840              :                                                                           delayed_inject_data_length);
    4841            0 :                             delayed_injection_callback.injection_callback = NULL;
    4842              :                         }
    4843            0 :                         else if ((delayed_inject_buffer != NULL) &&
    4844              :                                  (delayed_injection_callback.injection_callback_with_id != NULL))
    4845              :                         {
    4846            0 :                             delayed_injection_callback.injection_callback_with_id(delayed_injection_callback.service_id,
    4847              :                                                                                   delayed_inject_buffer,
    4848              :                                                                                   delayed_inject_data_length,
    4849              :                                                                                   delayed_injection_callback.data);
    4850              :                             delayed_injection_callback.injection_callback_with_id = NULL;
    4851              :                         }
    4852              : 
    4853            0 :                         free(delayed_inject_buffer);
    4854              :                         delayed_inject_buffer = NULL;
    4855              : 
    4856              :                         /* keep not read data in buffer */
    4857            0 :                         if (dlt_receiver_remove(receiver,
    4858              :                                                 (int) (sizeof(DltUserHeader) +
    4859            0 :                                                  sizeof(DltUserControlMsgInjection) +
    4860            0 :                                                  usercontextinj->data_length_inject)) != DLT_RETURN_OK)
    4861              :                             return DLT_RETURN_ERROR;
    4862              :                     }
    4863              :                 }
    4864              :                 break;
    4865            7 :                 case DLT_USER_MESSAGE_LOG_STATE:
    4866              :                 {
    4867              :                     /* At least, user header, user context, and service id and data_length of injected message is available */
    4868            7 :                     if (receiver->bytesRcvd < (int32_t) (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogState))) {
    4869              :                         leave_while = 1;
    4870              :                         break;
    4871              :                     }
    4872              : 
    4873            7 :                     userlogstate = (DltUserControlMsgLogState *)(receiver->buf + sizeof(DltUserHeader));
    4874            7 :                     dlt_user.log_state = userlogstate->log_state;
    4875              : 
    4876              :                     /* keep not read data in buffer */
    4877            7 :                     if (dlt_receiver_remove(receiver,
    4878              :                                             (sizeof(DltUserHeader) + sizeof(DltUserControlMsgLogState))) ==
    4879              :                         DLT_RETURN_ERROR)
    4880              :                         return DLT_RETURN_ERROR;
    4881              :                 }
    4882              :                 break;
    4883              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4884              :                 case DLT_USER_MESSAGE_TRACE_LOAD:
    4885              :                 {
    4886              :                     /*
    4887              :                      * at least user header and message length is available
    4888              :                      */
    4889              :                     trace_load_settings_user_message_bytes_required =
    4890              :                         (int32_t) (sizeof(DltUserHeader) + sizeof(uint32_t ));
    4891              :                     if (receiver->bytesRcvd < (int32_t)trace_load_settings_user_message_bytes_required) {
    4892              :                         // Not enough data to read the message length
    4893              :                         leave_while = 1;
    4894              :                         break;
    4895              :                     }
    4896              : 
    4897              :                     // Read trace settings count from buffer.
    4898              :                     trace_load_settings_user_messages_count = (uint32_t)(*(receiver->buf + sizeof(DltUserHeader)));
    4899              :                     trace_load_settings_user_message_bytes_required +=
    4900              :                         trace_load_settings_user_messages_count * sizeof(DltUserControlMsgTraceSettingMsg);
    4901              :                     if (receiver->bytesRcvd < (int32_t)trace_load_settings_user_message_bytes_required) {
    4902              :                         // Not enough data to read trace settings
    4903              :                         leave_while = 1;
    4904              :                         break;
    4905              :                     }
    4906              : 
    4907              :                     trace_load_settings_user_messages =
    4908              :                         (DltUserControlMsgTraceSettingMsg *)(receiver->buf + sizeof(DltUserHeader) + sizeof(uint32_t));
    4909              : 
    4910              :                     pthread_rwlock_wrlock(&trace_load_rw_lock);
    4911              : 
    4912              :                     // Remove the default created at startup
    4913              :                     if (trace_load_settings != NULL) {
    4914              :                         free(trace_load_settings);
    4915              :                     }
    4916              : 
    4917              :                     char msg[255];
    4918              :                     trace_load_settings_alloc_size = sizeof(DltTraceLoadSettings) * trace_load_settings_user_messages_count;
    4919              :                     trace_load_settings = malloc(trace_load_settings_alloc_size);
    4920              :                     if (trace_load_settings == NULL) {
    4921              :                         pthread_rwlock_unlock(&trace_load_rw_lock);
    4922              :                         dlt_log(LOG_ERR, "Failed to allocate memory for trace load settings\n");
    4923              :                         return DLT_RETURN_ERROR;
    4924              :                     }
    4925              :                     memset(trace_load_settings, 0, trace_load_settings_alloc_size);
    4926              :                     for (i = 0; i < trace_load_settings_user_messages_count; i++) {
    4927              :                         strncpy(trace_load_settings[i].apid, dlt_user.appID, DLT_ID_SIZE);
    4928              :                         strncpy(trace_load_settings[i].ctid, trace_load_settings_user_messages[i].ctid, DLT_ID_SIZE);
    4929              :                         trace_load_settings[i].soft_limit = trace_load_settings_user_messages[i].soft_limit;
    4930              :                         trace_load_settings[i].hard_limit = trace_load_settings_user_messages[i].hard_limit;
    4931              :                     }
    4932              :                     trace_load_settings_count = trace_load_settings_user_messages_count;
    4933              :                     pthread_rwlock_unlock(&trace_load_rw_lock);
    4934              : 
    4935              :                     // must be sent with unlocked trace_load_rw_lock
    4936              :                     for (i = 0; i < trace_load_settings_user_messages_count; i++) {
    4937              :                         if (trace_load_settings[i].ctid[0] == '\0') {
    4938              :                             snprintf(
    4939              :                                 msg, sizeof(msg),
    4940              :                                 "Received trace load settings: apid=%.4s, soft_limit=%u, hard_limit=%u\n",
    4941              :                                 trace_load_settings[i].apid,
    4942              :                                 trace_load_settings[i].soft_limit,
    4943              :                                 trace_load_settings[i].hard_limit);
    4944              :                         } else {
    4945              :                             snprintf(
    4946              :                                 msg, sizeof(msg),
    4947              :                                 "Received trace load settings: apid=%.4s, ctid=%.4s, soft_limit=%u, hard_limit=%u\n",
    4948              :                                 trace_load_settings[i].apid,
    4949              :                                 trace_load_settings[i].ctid,
    4950              :                                 trace_load_settings[i].soft_limit,
    4951              :                                 trace_load_settings[i].hard_limit);
    4952              :                         }
    4953              :                         dlt_user_output_internal_msg(DLT_LOG_INFO, msg, NULL);
    4954              :                     }
    4955              : 
    4956              :                     /* keep not read data in buffer */
    4957              :                     if (dlt_receiver_remove(receiver, trace_load_settings_user_message_bytes_required)
    4958              :                         == DLT_RETURN_ERROR) {
    4959              :                         return DLT_RETURN_ERROR;
    4960              :                     }
    4961              :                 }
    4962              : #endif
    4963            0 :                 default:
    4964              :                 {
    4965            0 :                     dlt_log(LOG_WARNING, "Invalid user message type received!\n");
    4966              :                     /* Ignore result */
    4967            0 :                     if (dlt_receiver_remove(receiver, sizeof(DltUserHeader)) == -1)
    4968            0 :                         dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
    4969              :                     /* In next invocation of while loop, a resync will be triggered if additional data was received */
    4970              :                 }
    4971              :                 break;
    4972              :                 } /* switch() */
    4973              : 
    4974           12 :                 if (leave_while == 1) {
    4975              :                     leave_while = 0;
    4976              :                     break;
    4977              :                 }
    4978              :             } /* while buffer*/
    4979              : 
    4980            9 :             if (dlt_receiver_move_to_begin(receiver) == DLT_RETURN_ERROR)
    4981              :                 return DLT_RETURN_ERROR;
    4982              :         } /* while receive */
    4983              : 
    4984              :     } /* if */
    4985              : 
    4986              :     return DLT_RETURN_OK;
    4987              : }
    4988              : 
    4989         5835 : DltReturnValue dlt_user_log_resend_buffer(void)
    4990              : {
    4991              :     int num, count;
    4992              :     int size;
    4993              :     DltReturnValue ret;
    4994              : 
    4995         5835 :     DLT_SEM_LOCK();
    4996              : 
    4997         5835 :     if (dlt_user.appID[0] == '\0') {
    4998            3 :         DLT_SEM_FREE();
    4999            3 :         return 0;
    5000              :     }
    5001              : 
    5002              :     /* Send content of ringbuffer */
    5003         5832 :     count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
    5004         5832 :     DLT_SEM_FREE();
    5005              : 
    5006         5832 :     for (num = 0; num < count; num++) {
    5007              : 
    5008            1 :         DLT_SEM_LOCK();
    5009            1 :         size = dlt_buffer_copy(&(dlt_user.startup_buffer), dlt_user.resend_buffer, dlt_user.log_buf_len);
    5010              : 
    5011            1 :         if (size > 0) {
    5012            1 :             DltUserHeader *userheader = (DltUserHeader *)(dlt_user.resend_buffer);
    5013              : 
    5014              :             /* Add application id to the messages of needed*/
    5015            1 :             if (dlt_user_check_userheader(userheader)) {
    5016            1 :                 switch (userheader->message) {
    5017            0 :                 case DLT_USER_MESSAGE_REGISTER_CONTEXT:
    5018              :                 {
    5019              :                     DltUserControlMsgRegisterContext *usercontext =
    5020            0 :                         (DltUserControlMsgRegisterContext *)(dlt_user.resend_buffer + sizeof(DltUserHeader));
    5021              : 
    5022            0 :                     if ((usercontext != 0) && (usercontext->apid[0] == '\0'))
    5023            0 :                         dlt_set_id(usercontext->apid, dlt_user.appID);
    5024              : 
    5025              :                     break;
    5026              :                 }
    5027            1 :                 case DLT_USER_MESSAGE_LOG:
    5028              :                 {
    5029              :                     DltExtendedHeader *extendedHeader =
    5030            1 :                         (DltExtendedHeader *)(dlt_user.resend_buffer + sizeof(DltUserHeader) +
    5031              :                                               sizeof(DltStandardHeader) +
    5032              :                                               sizeof(DltStandardHeaderExtra));
    5033              : 
    5034            1 :                     if (((extendedHeader) != 0) && (extendedHeader->apid[0] == '\0')) /* if application id is empty, add it */
    5035            0 :                         dlt_set_id(extendedHeader->apid, dlt_user.appID);
    5036              : 
    5037              :                     break;
    5038              :                 }
    5039              :                 default:
    5040              :                 {
    5041              :                     break;
    5042              :                 }
    5043              :                 }
    5044              :             }
    5045              : 
    5046              : #ifdef DLT_SHM_ENABLE
    5047              :             dlt_shm_push(&dlt_user.dlt_shm,
    5048              :                          dlt_user.resend_buffer + sizeof(DltUserHeader),
    5049              :                          size - sizeof(DltUserHeader),
    5050              :                          0,
    5051              :                          0,
    5052              :                          0,
    5053              :                          0);
    5054              : 
    5055              :             ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer, sizeof(DltUserHeader), 0, 0, 0, 0);
    5056              : #else
    5057            1 :             ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer, (size_t) size, 0, 0, 0, 0);
    5058              : #endif
    5059              : 
    5060              :             /* in case of error, keep message in ringbuffer */
    5061            1 :             if (ret == DLT_RETURN_OK) {
    5062            0 :                 dlt_buffer_remove(&(dlt_user.startup_buffer));
    5063              :             }
    5064              :             else {
    5065            1 :                 if (ret == DLT_RETURN_PIPE_ERROR) {
    5066              :                     /* handle not open or pipe error */
    5067            1 :                     close(dlt_user.dlt_log_handle);
    5068            1 :                     dlt_user.dlt_log_handle = -1;
    5069              :                 }
    5070              : 
    5071              :                 /* keep message in ringbuffer */
    5072            1 :                 DLT_SEM_FREE();
    5073            1 :                 return ret;
    5074              :             }
    5075              :         }
    5076              : 
    5077            0 :         DLT_SEM_FREE();
    5078              :     }
    5079              : 
    5080              :     return DLT_RETURN_OK;
    5081              : }
    5082              : 
    5083          121 : void dlt_user_log_reattach_to_daemon(void)
    5084              : {
    5085              :     uint32_t num;
    5086              :     DltContext handle;
    5087              :     DltContextData log_new;
    5088              : 
    5089          121 :     if (!DLT_USER_INITIALIZED_NOT_FREEING) {
    5090          111 :         return;
    5091              :     }
    5092              : 
    5093              : 
    5094          121 :     if (dlt_user.dlt_log_handle < 0) {
    5095          111 :         dlt_user.dlt_log_handle = DLT_FD_INIT;
    5096              : 
    5097              : #ifdef DLT_LIB_USE_UNIX_SOCKET_IPC
    5098              :         /* try to open connection to dlt daemon */
    5099              :         dlt_initialize_socket_connection();
    5100              : 
    5101              :         if (dlt_user.connection_state != DLT_USER_CONNECTED)
    5102              :             /* return if not connected */
    5103              :             return;
    5104              : 
    5105              : #elif defined DLT_LIB_USE_VSOCK_IPC
    5106              :         dlt_initialize_vsock_connection();
    5107              : 
    5108              :         if (dlt_user.connection_state != DLT_USER_CONNECTED)
    5109              :             return;
    5110              : 
    5111              : #else /* DLT_LIB_USE_FIFO_IPC */
    5112              :         /* try to open pipe to dlt daemon */
    5113              :         int fd = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK);
    5114              : 
    5115          111 :         if (fd < 0)
    5116              :             return;
    5117              : 
    5118            0 :         dlt_user.dlt_log_handle = fd;
    5119              : #endif
    5120              : 
    5121            0 :         if (dlt_user_log_init(&handle, &log_new) < DLT_RETURN_OK)
    5122              :             return;
    5123              : 
    5124              : #ifdef DLT_SHM_ENABLE
    5125              : 
    5126              :         /* init shared memory */
    5127              :         if (dlt_shm_init_client(&dlt_user.dlt_shm, dltShmName) < DLT_RETURN_OK)
    5128              :             dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled,"
    5129              :                       " Shared memory %s cannot be created!\n", dltShmName);
    5130              : 
    5131              : #endif
    5132              : 
    5133            0 :         dlt_log(LOG_NOTICE, "Logging (re-)enabled!\n");
    5134              : 
    5135              :         /* Re-register application */
    5136            0 :         if (dlt_user_log_send_register_application() < DLT_RETURN_ERROR)
    5137              :             return;
    5138              : 
    5139            0 :         DLT_SEM_LOCK();
    5140              : 
    5141              :         /* Re-register all stored contexts */
    5142            0 :         for (num = 0; num < dlt_user.dlt_ll_ts_num_entries; num++)
    5143              :             /* Re-register stored context */
    5144            0 :             if ((dlt_user.appID[0] != '\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0] != '\0')) {
    5145              :                 /*dlt_set_id(log_new.appID, dlt_user.appID); */
    5146            0 :                 dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
    5147            0 :                 handle.log_level_pos = (int32_t) num;
    5148            0 :                 log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
    5149              : 
    5150              :                 /* Release the mutex for sending context registration: */
    5151              :                 /* function  dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock */
    5152            0 :                 DLT_SEM_FREE();
    5153              : 
    5154            0 :                 log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
    5155            0 :                 log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
    5156              : 
    5157            0 :                 if (dlt_user_log_send_register_context(&log_new) < DLT_RETURN_ERROR)
    5158              :                     return;
    5159              : 
    5160              :                 /* Lock again the mutex */
    5161              :                 /* it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section. */
    5162            0 :                 DLT_SEM_LOCK();
    5163              :             }
    5164            0 :         DLT_SEM_FREE();
    5165              :     }
    5166              : }
    5167              : 
    5168            0 : DltReturnValue dlt_user_log_send_overflow(void)
    5169              : {
    5170              :     DltUserHeader userheader;
    5171              :     DltUserControlMsgBufferOverflow userpayload;
    5172              : 
    5173              :     /* set userheader */
    5174            0 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW) < DLT_RETURN_OK)
    5175              :         return DLT_RETURN_ERROR;
    5176              : 
    5177            0 :     if (dlt_user.dlt_is_file)
    5178              :         return DLT_RETURN_OK;
    5179              : 
    5180              :     /* set user message parameters */
    5181            0 :     userpayload.overflow_counter = dlt_user.overflow_counter;
    5182            0 :     dlt_set_id(userpayload.apid, dlt_user.appID);
    5183              : 
    5184            0 :     return dlt_user_log_out2(dlt_user.dlt_log_handle,
    5185              :                              &(userheader), sizeof(DltUserHeader),
    5186              :                              &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
    5187              : }
    5188              : 
    5189            0 : DltReturnValue dlt_user_check_buffer(int *total_size, int *used_size)
    5190              : {
    5191            0 :     if ((total_size == NULL) || (used_size == NULL))
    5192              :         return DLT_RETURN_WRONG_PARAMETER;
    5193              : 
    5194            0 :     DLT_SEM_LOCK();
    5195              : 
    5196              : #ifdef DLT_SHM_ENABLE
    5197              :     *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
    5198              :     *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
    5199              : #else
    5200            0 :     *total_size = (int) dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
    5201            0 :     *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
    5202              : #endif
    5203              : 
    5204            0 :     DLT_SEM_FREE();
    5205              :     return DLT_RETURN_OK; /* ok */
    5206              : }
    5207              : 
    5208              : #ifdef DLT_TEST_ENABLE
    5209              : void dlt_user_test_corrupt_user_header(int enable)
    5210              : {
    5211              :     dlt_user.corrupt_user_header = enable;
    5212              : }
    5213              : void dlt_user_test_corrupt_message_size(int enable, int16_t size)
    5214              : {
    5215              :     dlt_user.corrupt_message_size = enable;
    5216              :     dlt_user.corrupt_message_size_size = size;
    5217              : }
    5218              : #endif
    5219              : 
    5220              : 
    5221        21266 : int dlt_start_threads()
    5222              : {
    5223              :     struct timespec time_to_wait, single_wait;
    5224              :     struct timespec now;
    5225              :     int signal_status = 1;
    5226        21266 :     atomic_bool dlt_housekeeper_running = false;
    5227              : 
    5228              :     /*
    5229              :     * Configure the condition varibale to use CLOCK_MONOTONIC.
    5230              :     * This makes sure we're protected against changes in the system clock
    5231              :      */
    5232              :     pthread_condattr_t attr;
    5233        21266 :     pthread_condattr_init(&attr);
    5234        21266 :     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    5235        21266 :     pthread_cond_init(&dlt_housekeeper_running_cond, &attr);
    5236              : 
    5237        21266 :     if (pthread_create(&(dlt_housekeeperthread_handle),
    5238              :                        0,
    5239              :                        (void *)&dlt_user_housekeeperthread_function,
    5240              :                        &dlt_housekeeper_running) != 0) {
    5241            0 :         dlt_log(LOG_CRIT, "Can't create housekeeper thread!\n");
    5242            0 :         return -1;
    5243              :     }
    5244              : 
    5245        21266 :     clock_gettime(CLOCK_MONOTONIC, &now);
    5246              :     /* wait at most 10s */
    5247        21266 :     time_to_wait.tv_sec = now.tv_sec + 10;
    5248              :     time_to_wait.tv_nsec = now.tv_nsec;
    5249              : 
    5250              :     /*
    5251              :     * wait until the house keeper is up and running
    5252              :     * Even though the condition variable and the while are
    5253              :     * using the same time out the while loop is not a no op.
    5254              :     * This is due to the fact that the pthread_cond_timedwait
    5255              :     * can be woken before time is up and dlt_housekeeper_running is not true yet.
    5256              :     * (spurious wakeup)
    5257              :     * To protect against this, a while loop with a timeout is added
    5258              :     * */
    5259              : 
    5260              :     // pthread_cond_timedwait has to be called on a locked mutex
    5261        21266 :     pthread_mutex_lock(&dlt_housekeeper_running_mutex);
    5262              : 
    5263        21266 :     while (!dlt_housekeeper_running
    5264        21266 :            && now.tv_sec <= time_to_wait.tv_sec) {
    5265              : 
    5266              :         /*
    5267              :         * wait 500ms at a time
    5268              :         * this makes sure we don't block too long
    5269              :         * even if we missed the signal
    5270              :          */
    5271        21239 :         clock_gettime(CLOCK_MONOTONIC, &now);
    5272        21239 :         if (now.tv_nsec >= 500000000) {
    5273        10678 :             single_wait.tv_sec = now.tv_sec + 1;
    5274        10678 :             single_wait.tv_nsec = now.tv_nsec - 500000000;
    5275              :         } else {
    5276        10561 :             single_wait.tv_sec = now.tv_sec;
    5277        10561 :             single_wait.tv_nsec = now.tv_nsec + 500000000;
    5278              :         }
    5279              : 
    5280        21239 :         signal_status = pthread_cond_timedwait(
    5281              :             &dlt_housekeeper_running_cond,
    5282              :             &dlt_housekeeper_running_mutex,
    5283              :             &single_wait);
    5284              : 
    5285              :         /* otherwise it might be a spurious wakeup, try again until the time is over */
    5286        21239 :         if (signal_status == 0) {
    5287              :             break;
    5288              :         }
    5289              :      }
    5290              : 
    5291        21266 :     pthread_mutex_unlock(&dlt_housekeeper_running_mutex);
    5292              : 
    5293        21266 :      if (signal_status != 0 && !dlt_housekeeper_running) {
    5294            0 :          dlt_log(LOG_CRIT, "Failed to wait for house keeper thread!\n");
    5295            0 :          dlt_stop_threads();
    5296            0 :          return -1;
    5297              :      }
    5298              : 
    5299              : #ifdef DLT_NETWORK_TRACE_ENABLE
    5300              :     /* Start the segmented thread */
    5301        21266 :     if (pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
    5302              :                        (void *)dlt_user_trace_network_segmented_thread, NULL)) {
    5303            0 :         dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
    5304            0 :         return -1;
    5305              :     }
    5306              : #endif
    5307              :     return 0;
    5308              : }
    5309              : 
    5310        21266 : void dlt_stop_threads()
    5311              : {
    5312              :     int dlt_housekeeperthread_result = 0;
    5313              :     int joined = 0;
    5314              : 
    5315        21266 :     if (dlt_housekeeperthread_handle) {
    5316              :         /* do not ignore return value */
    5317              : #ifndef __ANDROID_API__
    5318        21266 :         dlt_housekeeperthread_result = pthread_cancel(dlt_housekeeperthread_handle);
    5319              : #else
    5320              : 
    5321              : #ifdef DLT_NETWORK_TRACE_ENABLE
    5322              :         dlt_lock_mutex(&mq_mutex);
    5323              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    5324              :         dlt_housekeeperthread_result = pthread_kill(dlt_housekeeperthread_handle, SIGUSR1);
    5325              :         dlt_user_cleanup_handler(NULL);
    5326              : #endif
    5327              : 
    5328              : 
    5329        21266 :         if (dlt_housekeeperthread_result != 0)
    5330            0 :             dlt_vlog(LOG_ERR,
    5331              :                      "ERROR %s(dlt_housekeeperthread_handle): %s\n",
    5332              : #ifndef __ANDROID_API__
    5333              :                      "pthread_cancel",
    5334              : #else
    5335              :                      "pthread_kill",
    5336              : #endif
    5337              :                      strerror(dlt_housekeeperthread_result));
    5338              :     }
    5339              : 
    5340              : #ifdef DLT_NETWORK_TRACE_ENABLE
    5341              :     int dlt_segmented_nwt_result = 0;
    5342              : 
    5343        21266 :     if (dlt_user.dlt_segmented_nwt_handle) {
    5344        21266 :         dlt_lock_mutex(&mq_mutex);
    5345        21266 :         pthread_cond_signal(&mq_init_condition);
    5346        21266 :         dlt_unlock_mutex(&mq_mutex);
    5347              : 
    5348        21266 :         dlt_segmented_nwt_result = pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
    5349              : 
    5350        21266 :         if (dlt_segmented_nwt_result != 0)
    5351            0 :             dlt_vlog(LOG_ERR,
    5352              :                      "ERROR pthread_cancel(dlt_user.dlt_segmented_nwt_handle): %s\n",
    5353              :                      strerror(dlt_segmented_nwt_result));
    5354              :     }
    5355              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    5356              :     /* make sure that the threads really finished working */
    5357        21266 :     if ((dlt_housekeeperthread_result == 0) && dlt_housekeeperthread_handle) {
    5358        21266 :         joined = pthread_join(dlt_housekeeperthread_handle, NULL);
    5359              : 
    5360        21266 :         if (joined != 0)
    5361            0 :             dlt_vlog(LOG_ERR,
    5362              :                      "ERROR pthread_join(dlt_housekeeperthread_handle, NULL): %s\n",
    5363              :                      strerror(joined));
    5364              : 
    5365        21266 :         dlt_housekeeperthread_handle = 0; /* set to invalid */
    5366              :     }
    5367              : 
    5368              : #ifdef DLT_NETWORK_TRACE_ENABLE
    5369        21266 :     if ((dlt_segmented_nwt_result == 0) && dlt_user.dlt_segmented_nwt_handle) {
    5370        21266 :         joined = pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL);
    5371              : 
    5372        21266 :         if (joined != 0)
    5373            0 :             dlt_vlog(LOG_ERR,
    5374              :                      "ERROR pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL): %s\n",
    5375              :                      strerror(joined));
    5376              : 
    5377        21266 :         dlt_user.dlt_segmented_nwt_handle = 0; /* set to invalid */
    5378              :     }
    5379              : #endif /* DLT_NETWORK_TRACE_ENABLE */
    5380        21266 : }
    5381              : 
    5382            0 : static void dlt_fork_child_fork_handler()
    5383              : {
    5384            0 :     g_dlt_is_child = 1;
    5385            0 :     dlt_user_init_state = INIT_UNITIALIZED;
    5386            0 :     dlt_user.dlt_log_handle = -1;
    5387            0 :     dlt_user.local_pid = -1;
    5388              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    5389              :     pthread_rwlock_unlock(&trace_load_rw_lock);
    5390              : #endif
    5391            0 : }
    5392              : 
    5393              : 
    5394              : #if defined(DLT_TRACE_LOAD_CTRL_ENABLE)
    5395              : static DltReturnValue dlt_user_output_internal_msg(
    5396              :     const DltLogLevelType loglevel, const char *const text, void* const params)
    5397              : {
    5398              :     (void)params; // parameter is not needed
    5399              :     static DltContext handle;
    5400              :     DltContextData log;
    5401              :     int ret;
    5402              :     int sent_size = 0;
    5403              : 
    5404              :     if (!handle.contextID[0])
    5405              :     {
    5406              :         // Register Special Context ID for output DLT library internal message
    5407              :         ret = dlt_register_context(&handle, DLT_TRACE_LOAD_CONTEXT_ID, "DLT user library internal context");
    5408              :         if (ret < DLT_RETURN_OK)
    5409              :         {
    5410              :             return ret;
    5411              :         }
    5412              :     }
    5413              : 
    5414              :     if (dlt_user.verbose_mode == 0)
    5415              :     {
    5416              :         return DLT_RETURN_ERROR;
    5417              :     }
    5418              : 
    5419              :     if (loglevel < DLT_USER_LOG_LEVEL_NOT_SET || loglevel >= DLT_LOG_MAX)
    5420              :     {
    5421              :         dlt_vlog(LOG_ERR, "Loglevel %d is outside valid range", loglevel);
    5422              :         return DLT_RETURN_WRONG_PARAMETER;
    5423              :     }
    5424              : 
    5425              :     if (text == NULL)
    5426              :     {
    5427              :         return DLT_RETURN_WRONG_PARAMETER;
    5428              :     }
    5429              : 
    5430              :     ret = dlt_user_log_write_start(&handle, &log, loglevel);
    5431              : 
    5432              :     // Ok means below threshold
    5433              :     // see src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp::sloggerinfo_callback for reference
    5434              :     if (ret == DLT_RETURN_OK)
    5435              :     {
    5436              :         return ret;
    5437              :     }
    5438              : 
    5439              :     if (ret != DLT_RETURN_TRUE)
    5440              :     {
    5441              :         dlt_vlog(LOG_ERR, "Loglevel %d is disabled", loglevel);
    5442              :     }
    5443              : 
    5444              : 
    5445              :     if (log.buffer == NULL)
    5446              :     {
    5447              :         return DLT_RETURN_LOGGING_DISABLED;
    5448              :     }
    5449              : 
    5450              :     ret = dlt_user_log_write_string(&log, text);
    5451              :     if (ret < DLT_RETURN_OK)
    5452              :     {
    5453              :         return ret;
    5454              :     }
    5455              : 
    5456              :     ret = dlt_user_log_send_log(&log, DLT_TYPE_LOG, &sent_size);
    5457              : 
    5458              :     /* Return number of bytes if message was successfully sent */
    5459              :     return (ret == DLT_RETURN_OK) ? sent_size : ret;
    5460              : }
    5461              : #endif
    5462              : 
    5463          858 : DltReturnValue dlt_user_log_out_error_handling(void *ptr1, size_t len1, void *ptr2, size_t len2, void *ptr3,
    5464              :                                                size_t len3)
    5465              : {
    5466              :     DltReturnValue ret = DLT_RETURN_ERROR;
    5467          858 :     size_t msg_size = len1 + len2 + len3;
    5468              : 
    5469          858 :     DLT_SEM_LOCK();
    5470          858 :     ret = dlt_buffer_check_size(&(dlt_user.startup_buffer), (int)msg_size);
    5471          858 :     DLT_SEM_FREE();
    5472              : 
    5473          858 :     DLT_SEM_LOCK();
    5474              : 
    5475          858 :     if (dlt_buffer_push3(&(dlt_user.startup_buffer),
    5476              :                          ptr1, (unsigned int)len1,
    5477              :                          ptr2, (unsigned int)len2,
    5478              :                          ptr3, (unsigned int)len3) == DLT_RETURN_ERROR) {
    5479            0 :         if (dlt_user.overflow_counter == 0)
    5480            0 :             dlt_log(LOG_WARNING, "Buffer full! Messages will be discarded.\n");
    5481              : 
    5482              :         ret = DLT_RETURN_BUFFER_FULL;
    5483              :     }
    5484              : 
    5485          858 :     DLT_SEM_FREE();
    5486              : 
    5487          858 :     return ret;
    5488              : }
        

Generated by: LCOV version 2.0-1