LCOV - code coverage report
Current view: top level - lib - dlt_user.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 58.1 % 1746 1014
Test Date: 2025-03-25 20:53:42 Functions: 80.4 % 138 111

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

Generated by: LCOV version 2.0-1