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

Generated by: LCOV version 2.0-1