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