LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 54.0 % 2646 1430
Test Date: 2026-06-22 19:44:37 Functions: 75.3 % 170 128

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

Generated by: LCOV version 2.0-1