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