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