LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 57.5 % 1827 1050
Test Date: 2025-12-12 09:13:23 Functions: 80.9 % 141 114

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

Generated by: LCOV version 2.0-1