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