LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 57.5 % 1810 1041
Test Date: 2025-12-01 16:57:19 Functions: 80.9 % 141 114

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

Generated by: LCOV version 2.0-1