LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 57.4 % 1799 1032
Test Date: 2025-10-30 14:45:29 Functions: 80.6 % 139 112

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

Generated by: LCOV version 2.0-1