LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Hit Total Coverage
Test: dlt_final_coverage.info Lines: 1014 1757 57.7 %
Date: 2024-11-20 10:17:27 Functions: 111 138 80.4 %

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

Generated by: LCOV version 1.14