c99a646b66f1ffb0749648aabf2487f1081e6696
[profile/ivi/dlt-daemon.git] / src / lib / dlt_user.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012-2014  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed with
13  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  *
16  * \author
17  * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
18  * Markus Klein <Markus.Klein@esk.fraunhofer.de>
19  * Mikko Rapeli <mikko.rapeli@bmw.de>
20  *
21  * \file dlt_user.c
22  * For further information see http://www.genivi.org/.
23  * @licence end@
24  */
25
26 #include <stdlib.h> /* for getenv(), free(), atexit() */
27 #include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
28 #include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
29
30 #if !defined (__WIN32__)
31 #include <syslog.h> /* for LOG_... */
32 #include <semaphore.h>
33 #include <pthread.h>    /* POSIX Threads */
34 #endif
35
36 #include <sys/time.h>
37 #include <math.h>
38
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <errno.h>
42
43 #include <sys/uio.h> /* writev() */
44
45 #include <limits.h>
46 #ifdef linux
47 #include <sys/prctl.h>
48 #endif
49
50 #include "dlt_user.h"
51 #include "dlt_user_shared.h"
52 #include "dlt_user_shared_cfg.h"
53 #include "dlt_user_cfg.h"
54
55 static DltUser dlt_user;
56 static int dlt_user_initialised = 0;
57 static int dlt_user_freeing = 0;
58
59 static char str[DLT_USER_BUFFER_LENGTH];
60
61 static sem_t dlt_mutex;
62 static pthread_t dlt_receiverthread_handle;
63 static pthread_attr_t dlt_receiverthread_attr;
64
65 /* Segmented Network Trace */
66 #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
67 #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
68 #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
69
70 /* Mutex to wait on while message queue is not initialized */
71 pthread_mutex_t mq_mutex;
72 pthread_cond_t  mq_init_condition;
73
74 /* Structure to pass data to segmented thread */
75 typedef struct {
76         DltContext                      *handle;
77         uint16_t                        id;
78         DltNetworkTraceType     nw_trace_type;
79         uint16_t                        header_len;
80         void                            *header;
81         uint16_t                        payload_len;
82         void                            *payload;
83 } s_segmented_data;
84
85 /* Function prototypes for internally used functions */
86 static void dlt_user_receiverthread_function(void *ptr);
87 static void dlt_user_atexit_handler(void);
88 static int dlt_user_log_init(DltContext *handle, DltContextData *log);
89 static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
90 static int dlt_user_log_send_register_application(void);
91 static int dlt_user_log_send_unregister_application(void);
92 static int dlt_user_log_send_register_context(DltContextData *log);
93 static int dlt_user_log_send_unregister_context(DltContextData *log);
94 static int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
95 static int dlt_user_log_send_log_mode(DltUserLogMode mode);
96 static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
97 static int dlt_user_log_check_user_message(void);
98 static void dlt_user_log_reattach_to_daemon(void);
99 static int dlt_user_log_send_overflow(void);
100 static void dlt_user_trace_network_segmented_thread(void *unused);
101 static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
102 static int dlt_user_queue_resend(void);
103
104 int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
105
106         char str[200];
107         char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
108         char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
109
110         dlt_get_major_version( lib_major_version);
111         dlt_get_minor_version( lib_minor_version);
112
113         if( (strcmp(lib_major_version,user_major_version)!=0) || (strcmp(lib_minor_version,user_minor_version)!=0))
114         {
115                 sprintf(str,"DLT Library version check failed! Installed DLT library version is %s.%s - Application using DLT library version %s.%s\n",lib_major_version,lib_minor_version,user_major_version,user_minor_version);
116                 dlt_log(LOG_WARNING, str);
117                 return -1;
118         }
119         return 0;
120 }
121
122 int dlt_init(void)
123 {
124     char filename[DLT_USER_MAX_FILENAME_LENGTH];
125     int ret;
126
127     // process is exiting. Do not allocate new resources.
128     if (dlt_user_freeing != 0)
129     {
130         // return negative value, to stop the current log
131         return -1;
132     }
133
134     // WARNING: multithread unsafe !
135     // Another thread will check that dlt_user_initialised != 0, but the lib is not initialised !
136     dlt_user_initialised = 1;
137
138     /* Initialize common part of dlt_init()/dlt_init_file() */
139     if (dlt_init_common()==-1)
140     {
141         dlt_user_initialised = 0;
142         return -1;
143     }
144
145     /* check environment variables */
146     dlt_check_envvar();
147
148     dlt_user.dlt_is_file = 0;
149     dlt_user.overflow = 0;
150     dlt_user.overflow_counter = 0;
151 #ifdef DLT_SHM_ENABLE
152         memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
153 #endif
154
155     /* create and open DLT user FIFO */
156     sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
157      
158     /* Try to delete existing pipe, ignore result of unlink */
159     unlink(filename);
160     
161     ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
162     if (ret==-1)
163     {
164         sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
165         dlt_log(LOG_WARNING, str);
166         /* return 0; */ /* removed to prevent error, when FIFO already exists */
167     }
168
169     // S_IWGRP cannot be set by mkfifo (???), let's reassign right bits
170     ret=chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
171     if (ret==-1)
172     {
173         sprintf(str,"FIFO user %s cannot be chmoded!\n", DLT_USER_DIR);
174         dlt_log(LOG_ERR, str);
175         return -1;
176     }
177
178     dlt_user.dlt_user_handle = open(filename, O_RDWR | O_CLOEXEC);
179     if (dlt_user.dlt_user_handle == DLT_FD_INIT)
180     {
181         sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
182         dlt_log(LOG_WARNING, str);
183         unlink(filename);
184         return 0;
185     }
186
187     /* open DLT output FIFO */
188     dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK | O_CLOEXEC );
189     if (dlt_user.dlt_log_handle==-1)
190     {
191         sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
192         dlt_log(LOG_WARNING, str);
193         //return 0;
194     }
195         else
196         {
197 #ifdef DLT_SHM_ENABLE
198                 /* init shared memory */
199                 if (dlt_shm_init_client(&(dlt_user.dlt_shm),DLT_SHM_KEY) < 0)
200                 {
201                         sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
202                         dlt_log(LOG_WARNING, str);
203                         //return 0; 
204                 }   
205 #endif
206         }
207                 
208
209     if (dlt_receiver_init(&(dlt_user.receiver),dlt_user.dlt_user_handle, DLT_USER_RCVBUF_MAX_SIZE)==-1)
210         {
211         dlt_user_initialised = 0;
212         return -1;
213     }
214
215     /* Start receiver thread */
216     if (pthread_create(&(dlt_receiverthread_handle),
217                        0,
218                        (void *) &dlt_user_receiverthread_function,
219                        0)!=0)
220         {
221                 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
222                 {
223                         dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
224                 }
225
226                 dlt_log(LOG_CRIT, "Can't create receiver thread!\n");
227                 dlt_user_initialised = 0;
228         return -1;
229         }
230
231     if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
232         {
233                 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
234         }
235
236     /* These will be lazy initialized only when needed */
237     dlt_user.dlt_segmented_queue_read_handle = -1;
238     dlt_user.dlt_segmented_queue_write_handle = -1;
239
240     /* Wait mutext for segmented thread */
241     pthread_mutex_init(&mq_mutex, NULL);
242     pthread_cond_init(&mq_init_condition, NULL);
243
244     /* Start the segmented thread */
245         if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
246            (void *)dlt_user_trace_network_segmented_thread, NULL))
247         {
248         dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
249         return -1;
250         }
251
252         return 0;
253 }
254
255 int dlt_init_file(const char *name)
256 {
257     dlt_user_initialised = 1;
258
259     /* Initialize common part of dlt_init()/dlt_init_file() */
260     if (dlt_init_common()==-1)
261     {
262         dlt_user_initialised = 0;
263         return -1;
264     }
265
266     dlt_user.dlt_is_file = 1;
267
268     /* open DLT output file */
269     dlt_user.dlt_log_handle = open(name,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
270     if (dlt_user.dlt_log_handle == -1)
271     {
272         sprintf(str,"Log file %s cannot be opened!\n",name);
273         dlt_log(LOG_ERR, str);
274         return -1;
275     }
276
277     return 0;
278 }
279
280 int dlt_init_message_queue(void)
281 {
282         pthread_mutex_lock(&mq_mutex);
283         if(dlt_user.dlt_segmented_queue_read_handle >= 0 &&
284            dlt_user.dlt_segmented_queue_write_handle >= 0)
285         {
286                 // Already intialized
287                 pthread_mutex_unlock(&mq_mutex);
288                 return 0;
289         }
290
291     /* Generate per process name for queue */
292     char queue_name[NAME_MAX];
293     sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
294
295     /* Maximum queue size is 10, limit to size of pointers */
296     struct mq_attr mqatr;
297     mqatr.mq_flags              = 0;
298     mqatr.mq_maxmsg             = 10;
299     mqatr.mq_msgsize    = sizeof(s_segmented_data *);
300     mqatr.mq_curmsgs    = 0;
301
302     /**
303      * Create the message queue. It must be newly created
304      * if old one was left by a crashing process.
305      * */
306     dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
307                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
308     if(dlt_user.dlt_segmented_queue_read_handle < 0)
309     {
310         if(errno == EEXIST)
311         {
312                 dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
313                 if(mq_unlink(queue_name) < 0)
314                 {
315                 char str[256];
316                 snprintf(str,255,"Could not delete existing message queue!: %s \n",strerror(errno));
317                 dlt_log(LOG_CRIT, str);
318                 }
319                 else // Retry
320                 {
321                         dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
322                                         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
323                 }
324         }
325         if(dlt_user.dlt_segmented_queue_read_handle < 0)
326         {
327             char str[256];
328             snprintf(str,255,"Can't create message queue read handle!: %s \n",strerror(errno));
329             dlt_log(LOG_CRIT, str);
330                 pthread_mutex_unlock(&mq_mutex);
331                 return -1;
332         }
333     }
334
335     dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY|O_NONBLOCK);
336     if(dlt_user.dlt_segmented_queue_write_handle < 0)
337     {
338
339         char str[256];
340         snprintf(str,255,"Can't open message queue write handle!: %s \n",strerror(errno));
341         dlt_log(LOG_CRIT, str);
342         pthread_mutex_unlock(&mq_mutex);
343         return -1;
344     }
345
346     pthread_cond_signal(&mq_init_condition);
347     pthread_mutex_unlock(&mq_mutex);
348     return 0;
349 }
350
351 int dlt_init_common(void)
352 {
353     char *env_local_print;
354
355     /* Binary semaphore for threads */
356     if (sem_init(&dlt_mutex, 0, 1)==-1)
357     {
358         dlt_user_initialised = 0;
359         return -1;
360     }
361
362         /* set to unknown state of connected client */
363         dlt_user.log_state = -1;
364
365     dlt_user.dlt_log_handle=-1;
366     dlt_user.dlt_user_handle=DLT_FD_INIT;
367
368     dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
369     dlt_set_id(dlt_user.appID,"");
370
371     dlt_user.application_description = 0;
372
373     /* Verbose mode is enabled by default */
374     dlt_user.verbose_mode = 1;
375
376     /* Local print is disabled by default */
377     dlt_user.enable_local_print = 0;
378
379     dlt_user.local_print_mode = DLT_PM_UNSET;
380
381     env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
382     if (env_local_print)
383     {
384         if (strcmp(env_local_print,"AUTOMATIC")==0)
385         {
386             dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
387         }
388         else if (strcmp(env_local_print,"FORCE_ON")==0)
389         {
390             dlt_user.local_print_mode = DLT_PM_FORCE_ON;
391         }
392         else if (strcmp(env_local_print,"FORCE_OFF")==0)
393         {
394             dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
395         }
396     }
397
398     /* Initialize LogLevel/TraceStatus field */
399     DLT_SEM_LOCK();
400     dlt_user.dlt_ll_ts = 0;
401     dlt_user.dlt_ll_ts_max_num_entries = 0;
402     dlt_user.dlt_ll_ts_num_entries = 0;
403
404     if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer), DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)==-1)
405     {
406                 dlt_user_initialised = 0;
407         DLT_SEM_FREE();
408         return -1;
409     }
410     DLT_SEM_FREE();
411
412     signal(SIGPIPE,SIG_IGN);                  /* ignore pipe signals */
413
414     atexit(dlt_user_atexit_handler);
415
416 #ifdef DLT_TEST_ENABLE
417     dlt_user.corrupt_user_header = 0;
418     dlt_user.corrupt_message_size = 0;
419     dlt_user.corrupt_message_size_size = 0;
420 #endif
421
422     return 0;
423 }
424
425 void dlt_user_atexit_handler(void)
426 {
427     if (dlt_user_initialised==0)
428     {
429         dlt_log(LOG_WARNING, "dlt_user_atexit_handler dlt_user_initialised==0\n");
430         // close file
431         dlt_log_free();
432         return;
433     }
434
435         /* Try to resend potential log messages in the user buffer */
436         int count = dlt_user_atexit_blow_out_user_buffer();
437
438         if(count != 0){
439                 char tmp[256];
440                 sprintf(tmp,"Lost log messages in user buffer when exiting: %i\n",count);
441                 dlt_log(LOG_ERR, tmp);
442         }
443
444     /* Unregister app (this also unregisters all contexts in daemon) */
445     /* Ignore return value */
446     dlt_unregister_app();
447
448     /* Cleanup */
449     /* Ignore return value */
450     dlt_free();
451 }
452
453 int dlt_user_atexit_blow_out_user_buffer(void){
454
455         int count,ret;
456
457         uint32_t exitTime = dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
458
459         while(dlt_uptime() < exitTime ){
460
461                 ret = dlt_user_log_resend_buffer();
462
463                 if(ret == 0)
464                 {
465                                 return 0;
466                 }
467
468                 usleep(DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP);
469         }
470
471         DLT_SEM_LOCK();
472         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
473         DLT_SEM_FREE();
474
475         return count;
476 }
477
478 int dlt_free(void)
479 {
480     uint32_t i;
481         char filename[DLT_USER_MAX_FILENAME_LENGTH];
482
483     if( dlt_user_freeing != 0 )
484         // resources are already being freed. Do nothing and return.
485         return -1;
486
487     // library is freeing its resources. Avoid to allocate it in dlt_init()
488     dlt_user_freeing = 1;
489
490     if (dlt_user_initialised==0)
491     {
492         dlt_user_freeing = 0;
493         return -1;
494     }
495     dlt_user_initialised = 0;
496
497     if (dlt_receiverthread_handle)
498     {
499         /* Ignore return value */
500         pthread_cancel(dlt_receiverthread_handle);
501     }
502
503     if (dlt_user.dlt_segmented_nwt_handle)
504     {
505         pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
506     }
507
508     if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
509     {
510         sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
511
512         close(dlt_user.dlt_user_handle);
513         dlt_user.dlt_user_handle=DLT_FD_INIT;
514
515         unlink(filename);
516     }
517
518 #ifdef DLT_SHM_ENABLE
519         /* free shared memory */
520         dlt_shm_free_client(&dlt_user.dlt_shm);
521 #endif
522
523     if (dlt_user.dlt_log_handle!=-1)
524     {
525         /* close log file/output fifo to daemon */
526         close(dlt_user.dlt_log_handle);
527         dlt_user.dlt_log_handle = -1;
528     }
529
530         /* Ignore return value */
531     DLT_SEM_LOCK();
532     dlt_receiver_free(&(dlt_user.receiver));
533     DLT_SEM_FREE();
534
535         /* Ignore return value */
536     DLT_SEM_LOCK();
537     dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
538     DLT_SEM_FREE();
539
540     DLT_SEM_LOCK();
541     if (dlt_user.dlt_ll_ts)
542     {
543         for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
544         {
545             if (dlt_user.dlt_ll_ts[i].injection_table!=0)
546             {
547                 free(dlt_user.dlt_ll_ts[i].injection_table);
548                 dlt_user.dlt_ll_ts[i].injection_table = 0;
549             }
550             dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
551         }
552
553         free(dlt_user.dlt_ll_ts);
554         dlt_user.dlt_ll_ts = 0;
555         dlt_user.dlt_ll_ts_max_num_entries = 0;
556         dlt_user.dlt_ll_ts_num_entries = 0;
557     }
558     DLT_SEM_FREE();
559
560     char queue_name[NAME_MAX];
561     sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
562
563     /**
564      * Ignore errors from these, to not to spam user if dlt_free
565      * is accidentally called multiple times.
566      */
567     mq_close(dlt_user.dlt_segmented_queue_write_handle);
568     mq_close(dlt_user.dlt_segmented_queue_read_handle);
569     mq_unlink(queue_name);
570
571     // allow the user app to do dlt_init() again.
572     // The flag is unset only to keep almost the same behaviour as before, on EntryNav
573     // This should be removed for other projects (see documentation of dlt_free()
574     dlt_user_freeing = 0;
575
576     return 0;
577 }
578
579 int dlt_check_library_version(const char * user_major_version,const char * user_minor_version)
580 {
581         return dlt_user_check_library_version(user_major_version, user_minor_version);
582 }
583
584 int dlt_register_app(const char *appid, const char * description)
585 {
586     int ret;
587
588     if (dlt_user_initialised==0)
589     {
590         if (dlt_init()<0)
591         {
592             return -1;
593         }
594     }
595
596     if ((appid==0) || (appid[0]=='\0'))
597     {
598         return -1;
599     }
600
601     /* check if application already registered */
602     /* if yes do not register again */
603     if(appid[1]==0)
604     {
605        if(appid[0]==dlt_user.appID[0])
606              return 0;
607     }
608     else if(appid[2]==0)
609     {
610        if(appid[0]==dlt_user.appID[0] &&
611           appid[1]==dlt_user.appID[1])
612              return 0;
613     }
614     else if(appid[3]==0)
615     {
616        if(appid[0]==dlt_user.appID[0] &&
617           appid[1]==dlt_user.appID[1] &&
618           appid[2]==dlt_user.appID[2])
619              return 0;
620     }
621     else
622     {
623        if(appid[0]==dlt_user.appID[0] &&
624           appid[1]==dlt_user.appID[1] &&
625           appid[2]==dlt_user.appID[2] &&
626           appid[3]==dlt_user.appID[3])
627              return 0;
628     }
629
630     DLT_SEM_LOCK();
631
632     /* Store locally application id and application description */
633     dlt_set_id(dlt_user.appID, appid);
634
635     if (dlt_user.application_description!=0)
636     {
637         free(dlt_user.application_description);
638     }
639
640     dlt_user.application_description = 0;
641
642     if (description!=0)
643     {
644         size_t desc_len = strlen(description);
645         dlt_user.application_description= malloc(desc_len+1);
646         if (dlt_user.application_description){
647             strncpy(dlt_user.application_description, description, desc_len);
648
649             /* Terminate transmitted string with 0 */
650             dlt_user.application_description[desc_len]='\0';
651         }
652         else
653         {
654                 DLT_SEM_FREE();
655                 return -1;
656         }
657     }
658
659     DLT_SEM_FREE();
660
661     ret = dlt_user_log_send_register_application();
662
663     return ret;
664 }
665 int dlt_register_context(DltContext *handle, const char *contextid, const char * description)
666 {
667     if (dlt_user_initialised==0)
668     {
669         if (dlt_init()<0)
670         {
671             return -1;
672         }
673     }
674
675     DLT_SEM_LOCK();
676
677     if (dlt_user.appID[0]=='\0')
678     {
679         dlt_log(LOG_ERR, "no application registered!\n");
680
681         DLT_SEM_FREE();
682         return -1;
683     }
684
685     if ((contextid==0) || (contextid[0]=='\0'))
686     {
687         DLT_SEM_FREE();
688         return -1;
689     }
690
691     DLT_SEM_FREE();
692
693     return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
694 }
695
696 int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus)
697 {
698     DltContextData log;
699     uint32_t i;
700
701     if (dlt_user_initialised==0)
702     {
703         if (dlt_init()<0)
704         {
705             return -1;
706         }
707     }
708
709     DLT_SEM_LOCK();
710
711     if (dlt_user.appID[0]=='\0')
712     {
713         dlt_log(LOG_ERR, "no application registered!\n");
714
715         DLT_SEM_FREE();
716         return -1;
717     }
718
719     DLT_SEM_FREE();
720
721     if ((contextid==0) || (contextid[0]=='\0'))
722     {
723         return -1;
724     }
725
726     if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
727     {
728         return -1;
729     }
730
731     if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
732     {
733         return -1;
734     }
735
736     if (dlt_user_log_init(handle, &log)==-1)
737     {
738         return -1;
739     }
740
741     /* Reset message counter */
742     handle->mcnt = 0;
743
744     /* Store context id in log level/trace status field */
745
746     /* Check if already registered, else register context */
747     DLT_SEM_LOCK();
748
749     /* Check of double context registration removed */
750     /* Double registration is already checked by daemon */
751
752         /* Allocate or expand context array */
753         if (dlt_user.dlt_ll_ts == 0)
754         {
755                 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
756                 if (dlt_user.dlt_ll_ts==0)
757                 {
758                         DLT_SEM_FREE();
759                         return -1;
760                 }
761
762                 dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
763
764                 /* Initialize new entries */
765                 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
766                 {
767                         dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
768
769                         /* At startup, logging and tracing is locally enabled */
770                         /* the correct log level/status is set after received from daemon */
771                         dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
772                         dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
773
774                         dlt_user.dlt_ll_ts[i].log_level_ptr    = 0;
775                         dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
776
777                         dlt_user.dlt_ll_ts[i].context_description = 0;
778
779                         dlt_user.dlt_ll_ts[i].injection_table = 0;
780                         dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
781                 }
782         }
783         else
784         {
785                 if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
786                 {
787                         /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
788                         dlt_ll_ts_type *old_ll_ts;
789                         uint32_t old_max_entries;
790
791                         old_ll_ts = dlt_user.dlt_ll_ts;
792                         old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
793
794                         dlt_user.dlt_ll_ts_max_num_entries = ((dlt_user.dlt_ll_ts_num_entries/DLT_USER_CONTEXT_ALLOC_SIZE)+1)*DLT_USER_CONTEXT_ALLOC_SIZE;
795                         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
796                                                                  dlt_user.dlt_ll_ts_max_num_entries);
797                         if (dlt_user.dlt_ll_ts==0)
798                         {
799                                 dlt_user.dlt_ll_ts = old_ll_ts;
800                                 dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
801                                 DLT_SEM_FREE();
802                                 return -1;
803                         }
804
805                         memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
806                         free(old_ll_ts);
807
808                         /* Initialize new entries */
809                         for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
810                         {
811                                 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
812
813                                 /* At startup, logging and tracing is locally enabled */
814                                 /* the correct log level/status is set after received from daemon */
815                                 dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
816                                 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
817
818                                 dlt_user.dlt_ll_ts[i].log_level_ptr    = 0;
819                                 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
820
821                                 dlt_user.dlt_ll_ts[i].context_description = 0;
822
823                                 dlt_user.dlt_ll_ts[i].injection_table = 0;
824                                 dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
825                         }
826                 }
827         }
828
829         /* Store locally context id and context description */
830         dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
831
832         if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
833         {
834                 free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
835         }
836
837         dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
838
839         if (description!=0)
840         {
841                 size_t desc_len = strlen(description);
842                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
843                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
844                 {
845                         DLT_SEM_FREE();
846                         return -1;
847                 }
848
849                 strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
850
851                 /* Terminate transmitted string with 0 */
852                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
853         }
854
855         if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
856         {
857                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
858                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
859                 {
860                         DLT_SEM_FREE();
861                         return -1;
862                 }
863         }
864         if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
865         {
866                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
867                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
868                 {
869                         DLT_SEM_FREE();
870                         return -1;
871                 }
872         }
873
874         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
875         {
876                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
877         }
878
879         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
880         {
881                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
882         }
883
884         /* Prepare transfer struct */
885         //dlt_set_id(log->appID, dlt_user.appID);
886         dlt_set_id(handle->contextID, contextid);
887         handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
888
889         handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
890         handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
891
892         log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
893
894         *(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level;
895         *(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
896
897         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
898         {
899                 log.log_level = loglevel;
900         }
901         else
902         {
903                 log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
904         }
905
906         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
907         {
908                 log.trace_status = tracestatus;
909         }
910         else
911         {
912                 log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
913         }
914
915         dlt_user.dlt_ll_ts_num_entries++;
916
917         DLT_SEM_FREE();
918
919         return dlt_user_log_send_register_context(&log);
920 }
921
922 int dlt_unregister_app(void)
923 {
924     int ret;
925
926     if (dlt_user_initialised==0)
927     {
928         return -1;
929     }
930
931     /* Inform daemon to unregister application and all of its contexts */
932     ret = dlt_user_log_send_unregister_application();
933
934     DLT_SEM_LOCK();
935
936     /* Clear and free local stored application information */
937     dlt_set_id(dlt_user.appID, "");
938
939     if (dlt_user.application_description!=0)
940     {
941         free(dlt_user.application_description);
942     }
943
944     dlt_user.application_description = 0;
945
946     DLT_SEM_FREE();
947
948     return ret;
949 }
950
951 int dlt_unregister_context(DltContext *handle)
952 {
953     DltContextData log;
954     int ret;
955
956     if (dlt_user_initialised==0)
957     {
958         return -1;
959     }
960
961     if (dlt_user_log_init(handle, &log) == -1)
962     {
963                 return -1;
964     }
965
966     DLT_SEM_LOCK();
967
968     handle->log_level_ptr = 0;
969     handle->trace_status_ptr = 0;
970
971     if (dlt_user.dlt_ll_ts)
972     {
973         /* Clear and free local stored context information */
974         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
975
976         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
977         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
978
979         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
980         {
981             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
982         }
983
984         if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
985         {
986             free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
987             dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
988         }
989
990         if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
991         {
992             free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
993             dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
994         }
995
996         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
997
998         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
999         {
1000             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
1001             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
1002         }
1003
1004         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks     = 0;
1005     }
1006
1007     DLT_SEM_FREE();
1008
1009     /* Inform daemon to unregister context */
1010     ret = dlt_user_log_send_unregister_context(&log);
1011
1012     return ret;
1013 }
1014
1015 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
1016 {
1017     uint32_t i;
1018     int ret;
1019
1020     if (dlt_user_initialised==0)
1021     {
1022         if (dlt_init()<0)
1023         {
1024             return -1;
1025         }
1026     }
1027
1028     /* Removed because of DltLogLevelType and DltTraceStatusType
1029
1030     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1031     {
1032         return -1;
1033     }
1034
1035     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1036     {
1037         return -1;
1038     }
1039
1040     if (dlt_user.dlt_ll_ts==0)
1041     {
1042         return -1;
1043     }
1044
1045     */
1046
1047     DLT_SEM_LOCK();
1048     if (dlt_user.dlt_ll_ts==0)
1049     {
1050         DLT_SEM_FREE();
1051         return -1;
1052     }
1053
1054     /* Update local structures */
1055     for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
1056     {
1057         dlt_user.dlt_ll_ts[i].log_level = loglevel;
1058         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
1059         if(dlt_user.dlt_ll_ts[i].log_level_ptr)
1060                 *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
1061         if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
1062                 *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
1063     }
1064
1065     DLT_SEM_FREE();
1066
1067     /* Inform DLT server about update */
1068     ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
1069
1070     return ret;
1071 }
1072
1073 int dlt_get_log_state()
1074 {
1075         return dlt_user.log_state;
1076 }
1077
1078 int dlt_set_log_mode(DltUserLogMode mode)
1079 {
1080     if (dlt_user_initialised==0)
1081     {
1082         if (dlt_init()<0)
1083         {
1084             return -1;
1085         }
1086     }
1087
1088         return dlt_user_log_send_log_mode(mode);
1089 }
1090
1091 int dlt_forward_msg(void *msgdata,size_t size)
1092 {
1093     DltUserHeader userheader;
1094     DltReturnValue ret;
1095
1096     if ((msgdata==0) || (size==0))
1097     {
1098         return -1;
1099     }
1100
1101     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
1102     {
1103         /* Type of internal user message; same value for Trace messages */
1104         return -1;
1105     }
1106
1107     if (dlt_user.dlt_is_file)
1108     {
1109         /* log to file */
1110         ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
1111         return ((ret==DLT_RETURN_OK)?0:-1);
1112     }
1113     else
1114     {
1115         /* Reattach to daemon if neccesary */
1116         dlt_user_log_reattach_to_daemon();
1117
1118         if (dlt_user.overflow_counter)
1119         {
1120             if (dlt_user_log_send_overflow()==0)
1121             {
1122                                 sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
1123                                 dlt_log(LOG_ERR, str);
1124                 dlt_user.overflow_counter=0;            }
1125         }
1126
1127         /* log to FIFO */
1128         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
1129                                 &(userheader), sizeof(DltUserHeader),
1130                                 msgdata, size, 0, 0);
1131
1132         /* store message in ringbuffer, if an error has occured */
1133         if (ret!=DLT_RETURN_OK)
1134         {
1135             DLT_SEM_LOCK();
1136
1137             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
1138                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
1139                                  msgdata, size, 0, 0)==-1)
1140                         {
1141                 if(dlt_user.overflow_counter==0)
1142                 {
1143                         dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
1144                 }
1145                 ret = DLT_RETURN_BUFFER_FULL;
1146                         }
1147
1148             DLT_SEM_FREE();
1149
1150             if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
1151             {
1152                 ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
1153             }
1154         }
1155
1156         switch (ret)
1157         {
1158         case DLT_RETURN_BUFFER_FULL:
1159         {
1160                 /* Buffer full */
1161             dlt_user.overflow_counter += 1;
1162                 return -1;
1163         }
1164         case DLT_RETURN_PIPE_FULL:
1165         {
1166             /* data could not be written */
1167             return -1;
1168         }
1169         case DLT_RETURN_PIPE_ERROR:
1170         {
1171             /* handle not open or pipe error */
1172             close(dlt_user.dlt_log_handle);
1173             dlt_user.dlt_log_handle = -1;
1174
1175             return -1;
1176         }
1177         case DLT_RETURN_ERROR:
1178         {
1179             /* other error condition */
1180             return -1;
1181         }
1182         case DLT_RETURN_OK:
1183         {
1184                 return 0;
1185         }
1186                 default:
1187                 {
1188                         /* This case should not occur */
1189                         return -1;
1190                 }
1191         }
1192     }
1193
1194     return 0;
1195 }
1196
1197 /* ********************************************************************************************* */
1198
1199 inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
1200 {
1201     return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
1202 }
1203
1204 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
1205 {
1206         if(dlt_user_initialised==0)
1207         {
1208                 if (dlt_init()<0)
1209                 {
1210                         return -1;
1211                 }
1212         }
1213     if (log==0)
1214     {
1215         return -1;
1216     }
1217
1218     if (dlt_user_log_init(handle, log)==-1)
1219     {
1220                 return -1;
1221     }
1222
1223     if (dlt_user.dlt_ll_ts==0)
1224     {
1225         return -1;
1226     }
1227
1228     if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
1229     {
1230                 log->args_num = 0;
1231         log->log_level = loglevel;
1232
1233         /* In non-verbose mode, insert message id */
1234         if (dlt_user.verbose_mode==0)
1235         {
1236             if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1237             {
1238                 return -1;
1239             }
1240             /* Write message id */
1241             memcpy(log->buffer,&(messageid),sizeof(uint32_t));
1242             log->size = sizeof(uint32_t);
1243
1244             /* as the message id is part of each message in non-verbose mode,
1245                it doesn't increment the argument counter in extended header (if used) */
1246         }
1247         else log->size=0;
1248         return 1;
1249     }
1250
1251     return -1;
1252 }
1253
1254 int dlt_user_log_write_finish(DltContextData *log)
1255 {
1256     if (log==0)
1257     {
1258         return -1;
1259     }
1260
1261     return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
1262 }
1263
1264 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1265 {
1266     uint16_t arg_size;
1267     uint32_t type_info;
1268
1269     if (log==0)
1270     {
1271         return -1;
1272     }
1273
1274     if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1275     {
1276         return -1;
1277     }
1278
1279     if (dlt_user.verbose_mode)
1280     {
1281         if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1282         {
1283             return -1;
1284         }
1285
1286         /* Transmit type information */
1287         type_info = DLT_TYPE_INFO_RAWD;
1288
1289         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1290         log->size += sizeof(uint32_t);
1291
1292     }
1293
1294     /* First transmit length of raw data, then the raw data itself */
1295     arg_size = (uint16_t)length;
1296
1297     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1298     log->size += sizeof(uint16_t);
1299
1300     memcpy((log->buffer)+log->size,data,arg_size);
1301     log->size += arg_size;
1302
1303     log->args_num ++;
1304
1305     return 0;
1306 }
1307
1308 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1309 {
1310     uint32_t type_info;
1311
1312     if (log==0)
1313     {
1314         return -1;
1315     }
1316
1317     if (sizeof(float32_t)!=4)
1318     {
1319         return -1;
1320     }
1321
1322     if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1323     {
1324         return -1;
1325     }
1326
1327     if (dlt_user.verbose_mode)
1328     {
1329         if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1330         {
1331             return -1;
1332         }
1333
1334         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1335
1336         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1337         log->size += sizeof(uint32_t);
1338     }
1339
1340     memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1341     log->size += sizeof(float32_t);
1342
1343     log->args_num ++;
1344
1345     return 0;
1346 }
1347
1348 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1349 {
1350     uint32_t type_info;
1351
1352     if (log==0)
1353     {
1354         return -1;
1355     }
1356
1357     if (sizeof(float64_t)!=8)
1358     {
1359         return -1;
1360     }
1361
1362     if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1363     {
1364         return -1;
1365     }
1366
1367     if (dlt_user.verbose_mode)
1368     {
1369         if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1370         {
1371             return -1;
1372         }
1373
1374         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1375
1376         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1377         log->size += sizeof(uint32_t);
1378     }
1379
1380     memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1381     log->size += sizeof(float64_t);
1382
1383     log->args_num ++;
1384
1385     return 0;
1386 }
1387
1388 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1389 {
1390     if (log==0)
1391     {
1392         return -1;
1393     }
1394
1395     switch (sizeof(unsigned int))
1396     {
1397     case 1:
1398     {
1399         return dlt_user_log_write_uint8(log, (uint8_t)data);
1400         break;
1401     }
1402     case 2:
1403     {
1404         return dlt_user_log_write_uint16(log, (uint16_t)data);
1405         break;
1406     }
1407     case 4:
1408     {
1409         return dlt_user_log_write_uint32(log, (uint32_t)data);
1410         break;
1411     }
1412     case 8:
1413     {
1414         return dlt_user_log_write_uint64(log, (uint64_t)data);
1415                 break;
1416     }
1417     default:
1418     {
1419         return -1;
1420         break;
1421     }
1422     }
1423
1424     return 0;
1425 }
1426
1427 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1428 {
1429     uint32_t type_info;
1430
1431     if (log==0)
1432     {
1433         return -1;
1434     }
1435
1436     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1437     {
1438         return -1;
1439     }
1440
1441     if (dlt_user.verbose_mode)
1442     {
1443         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1444         {
1445             return -1;
1446         }
1447
1448         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1449
1450         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1451         log->size += sizeof(uint32_t);
1452     }
1453
1454     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1455     log->size += sizeof(uint8_t);
1456
1457     log->args_num ++;
1458
1459     return 0;
1460 }
1461
1462 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1463 {
1464     uint32_t type_info;
1465
1466     if (log==0)
1467     {
1468         return -1;
1469     }
1470
1471     if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1472     {
1473         return -1;
1474     }
1475
1476     if (dlt_user.verbose_mode)
1477     {
1478         if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1479         {
1480             return -1;
1481         }
1482
1483         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1484
1485         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1486         log->size += sizeof(uint32_t);
1487     }
1488
1489     memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1490     log->size += sizeof(uint16_t);
1491
1492     log->args_num ++;
1493
1494     return 0;
1495 }
1496
1497 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1498 {
1499     uint32_t type_info;
1500
1501     if (log==0)
1502     {
1503         return -1;
1504     }
1505
1506     if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1507     {
1508         return -1;
1509     }
1510
1511     if (dlt_user.verbose_mode)
1512     {
1513         if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1514         {
1515             return -1;
1516         }
1517
1518         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1519
1520         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1521         log->size += sizeof(uint32_t);
1522     }
1523
1524     memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1525     log->size += sizeof(uint32_t);
1526
1527     log->args_num ++;
1528
1529     return 0;
1530 }
1531
1532 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1533 {
1534     uint32_t type_info;
1535
1536     if (log==0)
1537     {
1538         return -1;
1539     }
1540
1541     if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1542     {
1543         return -1;
1544     }
1545
1546     if (dlt_user.verbose_mode)
1547     {
1548         if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1549         {
1550             return -1;
1551         }
1552
1553         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1554
1555         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1556         log->size +=sizeof(uint32_t);
1557     }
1558
1559     memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1560     log->size += sizeof(uint64_t);
1561
1562     log->args_num ++;
1563
1564     return 0;
1565 }
1566
1567 int dlt_user_log_write_int(DltContextData *log, int data)
1568 {
1569     if (log==0)
1570     {
1571         return -1;
1572     }
1573
1574     switch (sizeof(int))
1575     {
1576     case 1:
1577     {
1578         return dlt_user_log_write_int8(log, (int8_t)data);
1579         break;
1580     }
1581     case 2:
1582     {
1583         return dlt_user_log_write_int16(log, (int16_t)data);
1584         break;
1585     }
1586     case 4:
1587     {
1588         return dlt_user_log_write_int32(log, (int32_t)data);
1589         break;
1590     }
1591     case 8:
1592     {
1593         return dlt_user_log_write_int64(log, (int64_t)data);
1594                 break;
1595     }
1596     default:
1597     {
1598         return -1;
1599         break;
1600     }
1601     }
1602
1603     return 0;
1604 }
1605
1606 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1607 {
1608     uint32_t type_info;
1609
1610     if (log==0)
1611     {
1612         return -1;
1613     }
1614
1615     if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1616     {
1617         return -1;
1618     }
1619
1620     if (dlt_user.verbose_mode)
1621     {
1622         if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1623         {
1624             return -1;
1625         }
1626
1627         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1628
1629         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1630         log->size += sizeof(uint32_t);
1631     }
1632
1633     memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1634     log->size += sizeof(int8_t);
1635
1636     log->args_num ++;
1637
1638     return 0;
1639 }
1640
1641 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1642 {
1643     uint32_t type_info;
1644
1645     if (log==0)
1646     {
1647         return -1;
1648     }
1649
1650     if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1651     {
1652         return -1;
1653     }
1654
1655     if (dlt_user.verbose_mode)
1656     {
1657         if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1658                 {
1659             return -1;
1660                 }
1661
1662         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1663
1664         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1665         log->size += sizeof(uint32_t);
1666     }
1667
1668     memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1669     log->size += sizeof(int16_t);
1670
1671     log->args_num ++;
1672
1673     return 0;
1674 }
1675
1676 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1677 {
1678     uint32_t type_info;
1679
1680     if (log==0)
1681     {
1682         return -1;
1683     }
1684
1685     if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1686     {
1687         return -1;
1688     }
1689
1690     if (dlt_user.verbose_mode)
1691     {
1692         if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1693         {
1694             return -1;
1695         }
1696
1697         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1698
1699         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1700         log->size += sizeof(uint32_t);
1701     }
1702
1703     memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1704     log->size += sizeof(int32_t);
1705
1706     log->args_num ++;
1707
1708     return 0;
1709 }
1710
1711 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1712 {
1713     uint32_t type_info;
1714
1715     if (log==0)
1716     {
1717         return -1;
1718     }
1719
1720     if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1721     {
1722         return -1;
1723     }
1724
1725     if (dlt_user.verbose_mode)
1726     {
1727         if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1728         {
1729             return -1;
1730         }
1731
1732         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1733
1734         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1735         log->size += sizeof(uint32_t);
1736     }
1737
1738     memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1739     log->size += sizeof(int64_t);
1740
1741     log->args_num ++;
1742
1743     return 0;
1744 }
1745
1746 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1747 {
1748     uint32_t type_info;
1749
1750     if (log==0)
1751     {
1752         return -1;
1753     }
1754
1755     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1756     {
1757         return -1;
1758     }
1759
1760     if (dlt_user.verbose_mode)
1761     {
1762         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1763         {
1764             return -1;
1765         }
1766
1767         type_info = DLT_TYPE_INFO_BOOL;
1768
1769         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1770         log->size += sizeof(uint32_t);
1771     }
1772
1773     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1774     log->size += sizeof(uint8_t);
1775
1776     log->args_num ++;
1777
1778     return 0;
1779 }
1780
1781 int dlt_user_log_write_string(DltContextData *log, const char *text)
1782 {
1783     uint16_t arg_size;
1784     uint32_t type_info;
1785
1786     if ((log==0) || (text==0))
1787     {
1788         return -1;
1789     }
1790
1791     if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1792     {
1793         return -1;
1794     }
1795
1796     if (dlt_user.verbose_mode)
1797     {
1798         if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1799         {
1800             return -1;
1801         }
1802
1803         type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
1804
1805         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1806         log->size += sizeof(uint32_t);
1807     }
1808
1809     arg_size = strlen(text) + 1;
1810
1811     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1812     log->size += sizeof(uint16_t);
1813
1814     memcpy((log->buffer)+log->size,text,arg_size);
1815     log->size += arg_size;
1816
1817     log->args_num ++;
1818
1819     return 0;
1820 }
1821
1822 int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
1823 {
1824     uint16_t arg_size;
1825     uint32_t type_info;
1826
1827     if ((log==0) || (text==0))
1828     {
1829         return -1;
1830     }
1831
1832     arg_size = strlen(text)+1;
1833
1834     if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1835     {
1836         return -1;
1837     }
1838
1839     if (dlt_user.verbose_mode)
1840     {
1841         if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1842         {
1843             return -1;
1844         }
1845
1846         type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
1847
1848         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1849         log->size += sizeof(uint32_t);
1850     }
1851
1852     arg_size = strlen(text) + 1;
1853
1854     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1855     log->size += sizeof(uint16_t);
1856
1857     memcpy((log->buffer)+log->size,text,arg_size);
1858     log->size += arg_size;
1859
1860     log->args_num ++;
1861
1862     return 0;
1863 }
1864
1865 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1866                                     int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1867 {
1868     DltContextData log;
1869     uint32_t i,j,k;
1870     int found = 0;
1871
1872         DltUserInjectionCallback *old;
1873
1874     if (handle==0)
1875     {
1876         return -1;
1877     }
1878
1879     if (dlt_user_log_init(handle, &log)==-1)
1880     {
1881                 return -1;
1882     }
1883
1884     if (service_id<DLT_USER_INJECTION_MIN)
1885     {
1886         return -1;
1887     }
1888     /* This function doesn't make sense storing to local file is choosen;
1889        so terminate this function */
1890     if (dlt_user.dlt_is_file)
1891     {
1892         return 0;
1893     }
1894
1895     DLT_SEM_LOCK();
1896
1897     if (dlt_user.dlt_ll_ts==0)
1898     {
1899         DLT_SEM_FREE();
1900         return 0;
1901     }
1902
1903     /* Insert callback in corresponding table */
1904     i=handle->log_level_pos;
1905
1906     /* Insert each service_id only once */
1907     for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1908     {
1909         if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1910                 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1911         {
1912             found = 1;
1913             break;
1914         }
1915     }
1916
1917     if (found)
1918     {
1919         j = k;
1920     }
1921     else
1922     {
1923         j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1924
1925         /* Allocate or expand injection table */
1926         if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1927         {
1928             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1929             if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1930             {
1931                 DLT_SEM_FREE();
1932                 return -1;
1933             }
1934         }
1935         else
1936         {
1937             old = dlt_user.dlt_ll_ts[i].injection_table;
1938             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1939             if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1940             {
1941                 dlt_user.dlt_ll_ts[i].injection_table = old;
1942                 DLT_SEM_FREE();
1943                 return -1;
1944             }
1945             memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1946             free(old);
1947         }
1948
1949         dlt_user.dlt_ll_ts[i].nrcallbacks++;
1950     }
1951
1952     /* Store service_id and corresponding function pointer for callback function */
1953     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1954     dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1955
1956     DLT_SEM_FREE();
1957     return 0;
1958 }
1959
1960 /**
1961  * NW Trace related
1962  */
1963
1964
1965 int check_buffer()
1966 {
1967         int total_size, used_size;
1968         dlt_user_check_buffer(&total_size, &used_size);
1969
1970         if((total_size - used_size) < (total_size/2))
1971         {
1972                 return -1;
1973         }
1974         return 1;
1975 }
1976
1977 /**
1978  * Send the start of a segment chain.
1979  * Returns -1 on failure
1980  */
1981 int dlt_user_trace_network_segmented_start(uint16_t *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len)
1982 {
1983
1984     DltContextData log;
1985         struct timeval tv;
1986
1987     if (handle==NULL)
1988     {
1989         return -1;
1990     }
1991
1992     if (dlt_user_log_init(handle, &log)==-1)
1993     {
1994                 return -1;
1995     }
1996
1997
1998     if (dlt_user.dlt_ll_ts==0)
1999     {
2000         return -1;
2001     }
2002
2003     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2004     {
2005
2006         log.args_num = 0;
2007         log.trace_status = nw_trace_type;
2008         log.size = 0;
2009
2010         gettimeofday(&tv, NULL);
2011         *id = tv.tv_usec;
2012
2013         /* Write identifier */
2014         if(dlt_user_log_write_string(&log, "NWST") < 0)
2015         {
2016                 return -1;
2017         }
2018
2019         /* Write stream handle */
2020         if(dlt_user_log_write_uint16(&log, *id) < 0)
2021         {
2022                 return -1;
2023         }
2024
2025         /* Write header */
2026         if(dlt_user_log_write_raw(&log, header, header_len) < 0)
2027         {
2028                 return -1;
2029         }
2030
2031         /* Write size of payload */
2032         if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2033         {
2034                 return -1;
2035         }
2036
2037         /* Write expected segment count */
2038         uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
2039
2040         /* If segments align perfectly with segment size, avoid sending empty segment */
2041         if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
2042         {
2043                 segment_count--;
2044         }
2045
2046         if(dlt_user_log_write_uint16(&log, segment_count) < 0)
2047         {
2048                 return -1;
2049         }
2050
2051         /* Write length of one segment */
2052         if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
2053         {
2054                 return -1;
2055         }
2056
2057         /* Send log */
2058         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2059     }
2060     return 0;
2061 }
2062
2063 int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
2064 {
2065         while(check_buffer() < 0)
2066         {
2067                 usleep(1000*50); // Wait 50ms
2068                 dlt_user_log_resend_buffer();
2069         }
2070
2071     if (handle==NULL)
2072     {
2073         return -1;
2074     }
2075
2076     DltContextData log;
2077
2078     if (dlt_user_log_init(handle, &log)==-1)
2079     {
2080                 return -1;
2081     }
2082
2083     if (dlt_user.dlt_ll_ts==0)
2084     {
2085         return -1;
2086     }
2087
2088     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2089     {
2090
2091         log.args_num = 0;
2092         log.trace_status = nw_trace_type;
2093         log.size = 0;
2094
2095         /* Write identifier */
2096         if(dlt_user_log_write_string(&log, "NWCH") < 0)
2097         {
2098                 return -1;
2099         }
2100
2101         /* Write stream handle */
2102         if(dlt_user_log_write_uint16(&log, id) < 0)
2103         {
2104                 return -1;
2105         }
2106
2107         /* Write segment sequence number */
2108         if(dlt_user_log_write_uint16(&log, sequence) < 0)
2109         {
2110                 return -1;
2111         }
2112
2113         /* Write data */
2114         if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
2115         {
2116                 return -1;
2117         }
2118
2119         /* Send log */
2120         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2121     }
2122
2123     /* Allow other threads to log between chunks */
2124         pthread_yield();
2125     return 0;
2126 }
2127
2128 int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
2129 {
2130     DltContextData log;
2131
2132     if (handle==0)
2133     {
2134         return -1;
2135     }
2136
2137     if (dlt_user_log_init(handle, &log)==-1)
2138     {
2139                 return -1;
2140     }
2141
2142
2143
2144     if (dlt_user.dlt_ll_ts==0)
2145     {
2146         return -1;
2147     }
2148
2149     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2150     {
2151
2152         log.args_num = 0;
2153         log.trace_status = nw_trace_type;
2154         log.size = 0;
2155
2156         /* Write identifier */
2157         if(dlt_user_log_write_string(&log, "NWEN") < 0)
2158         {
2159                 return -1;
2160         }
2161
2162         /* Write stream handle */
2163         if(dlt_user_log_write_uint(&log, id) < 0)
2164         {
2165                 return -1;
2166         }
2167
2168         /* Send log */
2169         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2170     }
2171     return 0;
2172 }
2173
2174
2175 void dlt_user_trace_network_segmented_thread(void *unused)
2176 {
2177         /* Unused on purpose. */
2178         (void) unused;
2179 #ifdef linux
2180     prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0);
2181 #endif
2182
2183         s_segmented_data *data;
2184
2185         while(1)
2186         {
2187                 // Wait until message queue is initialized
2188                 pthread_mutex_lock(&mq_mutex);
2189                 if(dlt_user.dlt_segmented_queue_read_handle < 0)
2190                 {
2191                         pthread_cond_wait(&mq_init_condition, &mq_mutex);
2192                 }
2193                 pthread_mutex_unlock(&mq_mutex);
2194
2195                 ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
2196                                         sizeof(s_segmented_data * ), NULL);
2197
2198                 if(read != sizeof(s_segmented_data *))
2199                 {
2200
2201                         char str[255];
2202                         snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
2203                         dlt_log(LOG_CRIT, str);
2204                         continue;
2205                 }
2206
2207                 /* Indicator just to try to flush the buffer */
2208                 if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
2209                 {
2210                         // Sleep 100ms, to allow other process to read FIFO
2211                         usleep(100*1000);
2212                         if(dlt_user_log_resend_buffer() < 0)
2213                         {
2214                                 // Requeue if still not empty
2215                                 if ( dlt_user_queue_resend() < 0 )
2216                                 {
2217                                     //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
2218                                 }
2219                         }
2220                         free(data);
2221                         continue;
2222                 }
2223
2224                 dlt_user_trace_network_segmented_thread_segmenter(data);
2225
2226                 /* Send the end message */
2227                 DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
2228                 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2229                 {
2230                         dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
2231                 }
2232
2233                 /* Free resources */
2234                 free(data->header);
2235                 free(data->payload);
2236                 free(data);
2237         }
2238 }
2239
2240 void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
2241 {
2242         /* Segment the data and send the chunks */
2243         void *ptr                       = NULL;
2244         uint16_t offset         = 0;
2245         uint16_t sequence       = 0;
2246         do
2247         {
2248                 uint16_t len = 0;
2249                 if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
2250                 {
2251                         len = data->payload_len - offset;
2252                 }
2253                 else
2254                 {
2255                         len = DLT_MAX_TRACE_SEGMENT_SIZE;
2256                 }
2257                 /* If payload size aligns perfectly with segment size, avoid sending empty segment */
2258                 if(len == 0)
2259                 {
2260                         break;
2261                 }
2262
2263                 ptr = data->payload + offset;
2264                 DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
2265                 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2266                 {
2267                         dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
2268                         break; // loop
2269                 }
2270                 offset += len;
2271         }while(ptr < data->payload + data->payload_len);
2272 }
2273
2274
2275 int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2276 {
2277         /* Send as normal trace if possible */
2278         if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
2279                 return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
2280         }
2281
2282         /* Allocate Memory */
2283         s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
2284         if(thread_data == NULL)
2285         {
2286                 return -1;
2287         }
2288         thread_data->header = malloc(header_len);
2289         if(thread_data->header == NULL)
2290         {
2291                 free(thread_data);
2292                 return -1;
2293         }
2294         thread_data->payload = malloc(payload_len);
2295         if(thread_data->payload == NULL)
2296         {
2297                 free(thread_data->header);
2298                 free(thread_data);
2299                 return -1;
2300         }
2301
2302         /* Copy data */
2303         thread_data->handle = handle;
2304         thread_data->nw_trace_type = nw_trace_type;
2305         thread_data->header_len = header_len;
2306         memcpy(thread_data->header, header, header_len);
2307         thread_data->payload_len = payload_len;
2308         memcpy(thread_data->payload, payload, payload_len);
2309
2310         /* Send start message */
2311         DltReturnValue err =    dlt_user_trace_network_segmented_start(&(thread_data->id),
2312                                                         thread_data->handle, thread_data->nw_trace_type,
2313                                                         thread_data->header_len, thread_data->header,
2314                                                         thread_data->payload_len);
2315         if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2316         {
2317                 dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
2318                 free(thread_data->header);
2319                 free(thread_data->payload);
2320                 free(thread_data);
2321                 return -1;
2322         }
2323
2324         /* Open queue if it is not open */
2325         if(dlt_init_message_queue() < 0)
2326         {
2327                 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2328                 free(thread_data->header);
2329                 free(thread_data->payload);
2330                 free(thread_data);
2331
2332                 return -1;
2333         }
2334
2335         /* Add to queue */
2336         if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
2337                         (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
2338         {
2339                 if(errno == EAGAIN)
2340                 {
2341                         dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
2342                 }
2343                 free(thread_data->header);
2344                 free(thread_data->payload);
2345                 free(thread_data);              
2346         char str[256];
2347         snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
2348         dlt_log(LOG_CRIT, str);
2349                 return -1;
2350         }
2351
2352         //thread_data will be freed by the receiver function
2353         //coverity[leaked_storage]
2354         return 0;
2355 }
2356
2357 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2358 {
2359         return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
2360 }
2361
2362 int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate)
2363 {
2364     DltContextData log;
2365
2366     if (dlt_user_initialised==0)
2367     {
2368         if (dlt_init()<0)
2369         {
2370             return -1;
2371         }
2372     }
2373
2374     if (dlt_user_log_init(handle, &log)==-1)
2375     {
2376                 return -1;
2377     }
2378
2379     if (handle==0)
2380     {
2381         return -1;
2382     }
2383
2384     /* Commented out because of DltNetworkTraceType:
2385
2386     if ((nw_trace_type<=0) || (nw_trace_type>0x15))
2387     {
2388         return -1;
2389     }
2390
2391     */
2392
2393     if (dlt_user.dlt_ll_ts==0)
2394     {
2395         return -1;
2396     }
2397
2398     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2399     {
2400
2401         log.args_num = 0;
2402         log.trace_status = nw_trace_type;
2403         log.size = 0;
2404
2405         if (header==0)
2406         {
2407             header_len=0;
2408         }
2409
2410         /* If truncation is allowed, check if we must do it */
2411         if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
2412         {
2413                 /* Identify as truncated */
2414                 if(dlt_user_log_write_string(&log, "NWTR") < 0)
2415                 {
2416                         return -1;
2417                 }
2418
2419             /* Write header and its length */
2420             if (dlt_user_log_write_raw(&log, header, header_len) < 0)
2421             {
2422                 return -1;
2423             }
2424
2425                 /* Write original size of payload */
2426             if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2427             {
2428                 return -1;
2429             }
2430
2431                 /**
2432                  *  Calculate maximum avaialble space in sending buffer after headers.
2433                  */
2434
2435                 int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
2436                                 log.size - sizeof(uint16_t) - sizeof(uint32_t);
2437
2438             /* Write truncated payload */
2439             if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
2440             {
2441                         return -1;
2442             }
2443         }
2444         else /* Truncation not allowed or data short enough */
2445         {
2446             /* Write header and its length */
2447             if (dlt_user_log_write_raw(&log, header, header_len)==-1)
2448             {
2449                 return -1;
2450             }
2451
2452             if (payload==0)
2453             {
2454                 payload_len=0;
2455             }
2456
2457             /* Write payload and its length */
2458             if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
2459             {
2460                         return -1;
2461             }
2462         }
2463
2464         /* Send log */
2465         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2466     }
2467
2468     return 0;
2469 }
2470
2471 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
2472 {
2473     DltContextData log;
2474
2475     if (dlt_user.verbose_mode==0)
2476     {
2477         return -1;
2478     }
2479
2480     if ((handle==0) || (text==0))
2481     {
2482         return -1;
2483     }
2484
2485     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2486     {
2487         if (dlt_user_log_write_string(&log,text)==-1)
2488         {
2489                         return -1;
2490         }
2491         if (dlt_user_log_write_finish(&log)==-1)
2492         {
2493                 return -1;
2494         }
2495     }
2496
2497     return 0;
2498 }
2499
2500 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
2501 {
2502     DltContextData log;
2503
2504     if (dlt_user.verbose_mode==0)
2505     {
2506         return -1;
2507     }
2508
2509     if ((handle==0) || (text==0))
2510     {
2511         return -1;
2512     }
2513
2514     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2515     {
2516         if (dlt_user_log_write_string(&log,text)==-1)
2517         {
2518                         return -1;
2519         }
2520         if (dlt_user_log_write_int(&log,data)==-1)
2521         {
2522                         return -1;
2523         }
2524         if (dlt_user_log_write_finish(&log)==-1)
2525         {
2526                         return -1;
2527         }
2528     }
2529
2530     return 0;
2531 }
2532
2533 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
2534 {
2535     DltContextData log;
2536
2537     if (dlt_user.verbose_mode==0)
2538     {
2539         return -1;
2540     }
2541
2542     if ((handle==0) || (text==0))
2543     {
2544         return -1;
2545     }
2546
2547     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2548     {
2549         if (dlt_user_log_write_string(&log,text)==-1)
2550         {
2551                         return -1;
2552         }
2553         if (dlt_user_log_write_uint(&log,data)==-1)
2554         {
2555                         return -1;
2556         }
2557         if (dlt_user_log_write_finish(&log)==-1)
2558         {
2559                         return -1;
2560         }
2561     }
2562
2563     return 0;
2564 }
2565
2566 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
2567 {
2568     DltContextData log;
2569
2570     if (dlt_user.verbose_mode==0)
2571     {
2572         return -1;
2573     }
2574
2575     if (handle==0)
2576     {
2577         return -1;
2578     }
2579
2580     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2581     {
2582         if (dlt_user_log_write_int(&log,data)==-1)
2583         {
2584                         return -1;
2585         }
2586         if (dlt_user_log_write_finish(&log)==-1)
2587         {
2588                         return -1;
2589         }
2590     }
2591
2592     return 0;
2593 }
2594
2595 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
2596 {
2597     DltContextData log;
2598
2599     if (dlt_user.verbose_mode==0)
2600     {
2601         return -1;
2602     }
2603
2604     if (handle==0)
2605     {
2606         return -1;
2607     }
2608
2609     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2610     {
2611         if (dlt_user_log_write_uint(&log,data)==-1)
2612         {
2613                         return -1;
2614         }
2615         if (dlt_user_log_write_finish(&log)==-1)
2616         {
2617                         return -1;
2618         }
2619     }
2620
2621     return 0;
2622 }
2623
2624 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
2625 {
2626     DltContextData log;
2627
2628     if (dlt_user.verbose_mode==0)
2629     {
2630         return -1;
2631     }
2632
2633     if (handle==0)
2634     {
2635         return -1;
2636     }
2637
2638     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2639     {
2640         if (dlt_user_log_write_raw(&log,data,length)==-1)
2641         {
2642                         return -1;
2643         }
2644         if (dlt_user_log_write_finish(&log)==-1)
2645         {
2646                         return -1;
2647         }
2648     }
2649
2650     return 0;
2651 }
2652
2653 int dlt_verbose_mode(void)
2654 {
2655     if (dlt_user_initialised==0)
2656     {
2657         if (dlt_init()<0)
2658         {
2659             return -1;
2660         }
2661     }
2662
2663     /* Switch to verbose mode */
2664     dlt_user.verbose_mode = 1;
2665
2666     return 0;
2667 }
2668
2669 int dlt_nonverbose_mode(void)
2670 {
2671     if (dlt_user_initialised==0)
2672     {
2673         if (dlt_init()<0)
2674         {
2675             return -1;
2676         }
2677     }
2678
2679     /* Switch to non-verbose mode */
2680     dlt_user.verbose_mode = 0;
2681
2682     return 0;
2683 }
2684
2685 int dlt_enable_local_print(void)
2686 {
2687     if (dlt_user_initialised==0)
2688     {
2689         if (dlt_init()<0)
2690         {
2691             return -1;
2692         }
2693     }
2694
2695     dlt_user.enable_local_print = 1;
2696
2697     return 0;
2698 }
2699
2700 int dlt_disable_local_print(void)
2701 {
2702     if (dlt_user_initialised==0)
2703     {
2704         if (dlt_init()<0)
2705         {
2706             return -1;
2707         }
2708     }
2709
2710     dlt_user.enable_local_print = 0;
2711
2712     return 0;
2713 }
2714
2715 void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
2716 {
2717 #ifdef linux
2718     prctl(PR_SET_NAME, "dlt_receiver", 0, 0, 0);
2719 #endif
2720     while (1)
2721     {
2722         /* Check for new messages from DLT daemon */
2723         if (dlt_user_log_check_user_message()==-1)
2724         {
2725                         /* Critical error */
2726                         dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2727         }
2728
2729         usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2730     }
2731 }
2732
2733 /* Private functions of user library */
2734
2735 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2736 {
2737     if (dlt_user_initialised==0)
2738     {
2739         if (dlt_init()<0)
2740         {
2741             return -1;
2742         }
2743     }
2744
2745     log->handle = handle;
2746
2747     return 0;
2748 }
2749
2750 int dlt_user_queue_resend(void)
2751 {
2752         static unsigned char dlt_user_queue_resend_error_counter = 0;
2753
2754         if(dlt_user.dlt_log_handle < 0)
2755         {
2756                 // Fail silenty. FIFO is not open yet
2757                 return -1;
2758         }
2759     /**
2760      * Ask segmented thread to try emptying the buffer soon.
2761      * This will be freed in dlt_user_trace_network_segmented_thread
2762      * */
2763     s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
2764
2765     if (NULL == resend_data)
2766     {
2767         return -1;
2768     }
2769
2770     resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
2771
2772
2773
2774     /* Open queue if it is not open */
2775         if(dlt_init_message_queue() < 0)
2776         {
2777         if(!dlt_user_queue_resend_error_counter)
2778         {
2779                 // log error only when problem occurred first time
2780                 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2781         }
2782         dlt_user_queue_resend_error_counter = 1;
2783         free(resend_data);
2784                 return -1;
2785         }
2786
2787     if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
2788     {
2789         if(!dlt_user_queue_resend_error_counter)
2790         {
2791                 // log error only when problem occurred first time
2792                         char str[255];
2793                         snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
2794                         dlt_log(LOG_CRIT, str);
2795         }
2796         dlt_user_queue_resend_error_counter = 1;
2797         free(resend_data);
2798         return -1;
2799     }
2800
2801     dlt_user_queue_resend_error_counter = 0;
2802
2803     //thread_data will be freed by the receiver function
2804     //coverity[leaked_storage]
2805     return 0;
2806 }
2807
2808 DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
2809 {
2810     DltMessage msg;
2811     DltUserHeader userheader;
2812     int32_t len;
2813
2814     DltReturnValue ret = DLT_RETURN_OK;
2815
2816     if (log==0)
2817     {
2818         return DLT_RETURN_ERROR;
2819     }
2820
2821     if (log->handle==0)
2822     {
2823         return DLT_RETURN_ERROR;
2824     }
2825
2826     if (dlt_user.appID[0]=='\0')
2827     {
2828         return DLT_RETURN_ERROR;
2829     }
2830
2831     if (log->handle->contextID[0]=='\0')
2832     {
2833         return DLT_RETURN_ERROR;
2834     }
2835
2836     if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2837     {
2838         return DLT_RETURN_ERROR;
2839     }
2840
2841     /* also for Trace messages */
2842 #ifdef DLT_SHM_ENABLE
2843     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2844 #else
2845     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2846 #endif
2847     {
2848                 return DLT_RETURN_ERROR;
2849     }
2850
2851     if (dlt_message_init(&msg,0)==-1)
2852     {
2853         return DLT_RETURN_ERROR;
2854     }
2855
2856     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2857
2858     if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2859     {
2860                 return DLT_RETURN_ERROR;
2861     }
2862
2863     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2864     msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2865
2866     if (dlt_user.verbose_mode)
2867     {
2868         /* In verbose mode, send extended header */
2869         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2870     }
2871     else
2872     {
2873         /* In non-verbose, send extended header if desired */
2874 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2875         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2876 #endif
2877     }
2878
2879 #if (BYTE_ORDER==BIG_ENDIAN)
2880     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2881 #endif
2882
2883     msg.standardheader->mcnt = log->handle->mcnt++;
2884
2885     /* Set header extra parameters */
2886     dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2887     //msg.headerextra.seid = 0;
2888     msg.headerextra.tmsp = dlt_uptime();
2889
2890     if (dlt_message_set_extraparameters(&msg,0)==-1)
2891     {
2892         return DLT_RETURN_ERROR;
2893     }
2894
2895     /* Fill out extended header, if extended header should be provided */
2896     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2897     {
2898         /* with extended header */
2899         msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)  );
2900
2901         switch (mtype)
2902         {
2903         case DLT_TYPE_LOG:
2904         {
2905             msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2906             break;
2907         }
2908         case DLT_TYPE_NW_TRACE:
2909         {
2910             msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2911             break;
2912         }
2913         default:
2914         {
2915                     /* This case should not occur */
2916             return DLT_RETURN_ERROR;
2917             break;
2918         }
2919         }
2920
2921         /* If in verbose mode, set flag in header for verbose mode */
2922         if (dlt_user.verbose_mode)
2923         {
2924             msg.extendedheader->msin |= DLT_MSIN_VERB;
2925         }
2926
2927         msg.extendedheader->noar = log->args_num;              /* number of arguments */
2928         dlt_set_id(msg.extendedheader->apid,dlt_user.appID);       /* application id */
2929         dlt_set_id(msg.extendedheader->ctid,log->handle->contextID);   /* context id */
2930
2931         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2932     }
2933     else
2934     {
2935         /* without extended header */
2936         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2937     }
2938
2939     len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2940     if (len>UINT16_MAX)
2941     {
2942         dlt_log(LOG_CRIT,"Huge message discarded!\n");
2943         return DLT_RETURN_ERROR;
2944     }
2945
2946     msg.standardheader->len = DLT_HTOBE_16(len);
2947
2948     /* print to std out, if enabled */
2949     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2950             (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2951     {
2952         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2953         {
2954             if (dlt_user_print_msg(&msg, log)==-1)
2955             {
2956                                 return DLT_RETURN_ERROR;
2957             }
2958         }
2959     }
2960
2961     if (dlt_user.dlt_is_file)
2962     {
2963         /* log to file */
2964         ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
2965         return ret;
2966     }
2967     else
2968     {
2969         /* Reattach to daemon if neccesary */
2970         dlt_user_log_reattach_to_daemon();
2971
2972         if (dlt_user.overflow_counter)
2973         {
2974             if (dlt_user_log_send_overflow()==0)
2975             {
2976                                 sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
2977                                 dlt_log(LOG_ERR, str);
2978                 dlt_user.overflow_counter=0;
2979             }
2980         }
2981
2982                 /* try to resent old data first */
2983                 ret = DLT_RETURN_OK;
2984                 if(dlt_user.dlt_log_handle!=-1)
2985                         ret = dlt_user_log_resend_buffer();
2986                 if(ret==DLT_RETURN_OK)
2987                 {
2988                         /* resend ok or nothing to resent */
2989 #ifdef DLT_SHM_ENABLE
2990                         if(dlt_user.dlt_log_handle!=-1)
2991                                 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2992                                                                                         log->buffer, log->size,0,0);                   
2993
2994                         /* log to FIFO */
2995                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
2996                                                                         &(userheader), sizeof(DltUserHeader),
2997                                                                         0, 0,
2998                                                                         0, 0);
2999 #else
3000                         /* log to FIFO */
3001 #ifdef DLT_TEST_ENABLE
3002                         if(dlt_user.corrupt_user_header) {
3003                                 userheader.pattern[0]=0xff;
3004                                 userheader.pattern[1]=0xff;
3005                                 userheader.pattern[2]=0xff;
3006                                 userheader.pattern[3]=0xff;
3007                         }
3008                         if(dlt_user.corrupt_message_size) {
3009                                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
3010                         }
3011 #endif
3012                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3013                                                                         &(userheader), sizeof(DltUserHeader),
3014                                                                         msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3015                                                                         log->buffer, log->size);                
3016 #endif                  
3017                 }
3018                 
3019         /* store message in ringbuffer, if an error has occured */
3020         if (ret!=DLT_RETURN_OK)
3021         {
3022             DLT_SEM_LOCK();
3023
3024             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3025                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3026                                 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3027                                 log->buffer, log->size)==-1)
3028                         {
3029                 if(dlt_user.overflow_counter==0)
3030                 {
3031
3032                         dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
3033                 }
3034                 ret = DLT_RETURN_BUFFER_FULL;
3035                         }
3036
3037             DLT_SEM_FREE();
3038
3039                 // Fail silenty if FIFO is not open
3040             if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3041             {
3042                 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
3043             }
3044         }
3045
3046         switch (ret)
3047         {
3048         case DLT_RETURN_BUFFER_FULL:
3049         {
3050                 /* Buffer full */
3051             dlt_user.overflow_counter += 1;
3052                 return DLT_RETURN_BUFFER_FULL;
3053         }
3054         case DLT_RETURN_PIPE_FULL:
3055         {
3056             /* data could not be written */
3057             return DLT_RETURN_PIPE_FULL;
3058         }
3059         case DLT_RETURN_PIPE_ERROR:
3060         {
3061             /* handle not open or pipe error */
3062             close(dlt_user.dlt_log_handle);
3063             dlt_user.dlt_log_handle = -1;
3064
3065 #ifdef DLT_SHM_ENABLE
3066                         /* free shared memory */
3067                         dlt_shm_free_client(&dlt_user.dlt_shm);
3068 #endif
3069
3070             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
3071             {
3072                 dlt_user_print_msg(&msg, log);
3073             }
3074
3075             return DLT_RETURN_PIPE_ERROR;
3076         }
3077         case DLT_RETURN_ERROR:
3078         {
3079             /* other error condition */
3080             return DLT_RETURN_ERROR;
3081         }
3082                 case DLT_RETURN_OK:
3083         {
3084                 return DLT_RETURN_OK;
3085         }
3086                 default:
3087                 {
3088                         /* This case should never occur. */
3089                         return DLT_RETURN_ERROR;
3090                 }
3091         }
3092     }
3093
3094     return DLT_RETURN_OK;
3095 }
3096
3097 int dlt_user_log_send_register_application(void)
3098 {
3099     DltUserHeader userheader;
3100     DltUserControlMsgRegisterApplication usercontext;
3101
3102     DltReturnValue ret;
3103
3104     if (dlt_user.appID[0]=='\0')
3105     {
3106         return -1;
3107     }
3108
3109     /* set userheader */
3110     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
3111     {
3112                 return -1;
3113     }
3114
3115     /* set usercontext */
3116     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3117     usercontext.pid = getpid();
3118
3119     if (dlt_user.application_description!=0)
3120     {
3121         usercontext.description_length = strlen(dlt_user.application_description);
3122     }
3123     else
3124     {
3125         usercontext.description_length = 0;
3126     }
3127
3128     if (dlt_user.dlt_is_file)
3129     {
3130         return 0;
3131     }
3132
3133     /* log to FIFO */
3134     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
3135
3136     /* store message in ringbuffer, if an error has occured */
3137     if (ret!=DLT_RETURN_OK)
3138     {
3139         DLT_SEM_LOCK();
3140
3141         if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3142                             (unsigned char *)&(userheader), sizeof(DltUserHeader),
3143                             (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
3144                             (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
3145              {
3146                     dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3147                     DLT_SEM_FREE();
3148                     return -1;
3149              }
3150
3151         DLT_SEM_FREE();
3152
3153         if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3154         {
3155             ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
3156         }
3157     }
3158
3159     return 0;
3160 }
3161
3162 int dlt_user_log_send_unregister_application(void)
3163 {
3164     DltUserHeader userheader;
3165     DltUserControlMsgUnregisterApplication usercontext;
3166
3167     DltReturnValue ret;
3168
3169     if (dlt_user.appID[0]=='\0')
3170     {
3171         return -1;
3172     }
3173
3174     /* set userheader */
3175     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
3176     {
3177         return -1;
3178     }
3179
3180     /* set usercontext */
3181     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3182     usercontext.pid = getpid();
3183
3184     if (dlt_user.dlt_is_file)
3185     {
3186         return 0;
3187     }
3188
3189     /* log to FIFO */
3190     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
3191     return ((ret==DLT_RETURN_OK)?0:-1);
3192 }
3193
3194 int dlt_user_log_send_register_context(DltContextData *log)
3195 {
3196     DltUserHeader userheader;
3197     DltUserControlMsgRegisterContext usercontext;
3198     DltReturnValue ret;
3199
3200     if (log==0)
3201     {
3202                 return -1;
3203     }
3204
3205     if (log->handle==0)
3206     {
3207         return -1;
3208     }
3209
3210     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3211     {
3212         return -1;
3213     }
3214
3215     /* set userheader */
3216     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
3217     {
3218                 return -1;
3219     }
3220
3221     /* set usercontext */
3222     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3223     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
3224     usercontext.log_level_pos = log->handle->log_level_pos;
3225     usercontext.pid = getpid();
3226
3227     usercontext.log_level = (int8_t)log->log_level;
3228     usercontext.trace_status = (int8_t)log->trace_status;
3229
3230     if (log->context_description!=0)
3231     {
3232         usercontext.description_length = strlen(log->context_description);
3233     }
3234     else
3235     {
3236                 usercontext.description_length = 0;
3237     }
3238
3239     if (dlt_user.dlt_is_file)
3240     {
3241         return 0;
3242     }
3243
3244     /* log to FIFO */
3245     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
3246
3247     /* store message in ringbuffer, if an error has occured */
3248     if (ret!=DLT_RETURN_OK)
3249     {
3250         DLT_SEM_LOCK();
3251
3252         if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3253                             (unsigned char *)&(userheader), sizeof(DltUserHeader),
3254                             (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
3255                             (const unsigned char*)log->context_description, usercontext.description_length)==-1)
3256              {
3257                     dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3258                     DLT_SEM_FREE();
3259                     return -1;
3260              }
3261
3262         DLT_SEM_FREE();
3263
3264         if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3265         {
3266             ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
3267         }
3268     }
3269
3270     return 0;
3271
3272 }
3273
3274 int dlt_user_log_send_unregister_context(DltContextData *log)
3275 {
3276     DltUserHeader userheader;
3277     DltUserControlMsgUnregisterContext usercontext;
3278     DltReturnValue ret;
3279
3280     if (log==0)
3281     {
3282         return -1;
3283     }
3284
3285     if (log->handle==0)
3286     {
3287         return -1;
3288     }
3289
3290     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3291     {
3292         return -1;
3293     }
3294
3295     /* set userheader */
3296     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
3297     {
3298                 return -1;
3299     }
3300
3301     /* set usercontext */
3302     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3303     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
3304     usercontext.pid = getpid();
3305
3306     if (dlt_user.dlt_is_file)
3307     {
3308         return 0;
3309     }
3310
3311     /* log to FIFO */
3312     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
3313         return ((ret==DLT_RETURN_OK)?0:-1);
3314 }
3315
3316 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
3317 {
3318     DltUserHeader userheader;
3319     DltUserControlMsgAppLogLevelTraceStatus usercontext;
3320         DltReturnValue ret;
3321
3322     if ((appid==0) || (appid[0]=='\0'))
3323     {
3324         return -1;
3325     }
3326
3327     /* Removed because of DltLogLevelType and DltTraceStatusType
3328
3329     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
3330     {
3331         return -1;
3332     }
3333
3334     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
3335     {
3336         return -1;
3337     }
3338
3339     */
3340
3341     /* set userheader */
3342     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
3343     {
3344                 return -1;
3345     }
3346
3347     /* set usercontext */
3348     dlt_set_id(usercontext.apid,appid);       /* application id */
3349     usercontext.log_level = loglevel;
3350     usercontext.trace_status = tracestatus;
3351
3352     if (dlt_user.dlt_is_file)
3353     {
3354         return 0;
3355     }
3356
3357     /* log to FIFO */
3358     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
3359     return ((ret==DLT_RETURN_OK)?0:-1);
3360 }
3361
3362 int dlt_user_log_send_log_mode(DltUserLogMode mode)
3363 {
3364     DltUserHeader userheader;
3365     DltUserControlMsgLogMode logmode;
3366
3367     DltReturnValue ret;
3368
3369     /* set userheader */
3370     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
3371     {
3372         return -1;
3373     }
3374
3375     /* set data */
3376     logmode.log_mode = (unsigned char) mode;
3377
3378     if (dlt_user.dlt_is_file)
3379     {
3380         return 0;
3381     }
3382
3383     /* log to FIFO */
3384     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
3385     return ((ret==DLT_RETURN_OK)?0:-1);
3386 }
3387
3388 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
3389 {
3390     uint8_t *databuffer_tmp;
3391     int32_t datasize_tmp;
3392     int32_t databuffersize_tmp;
3393     static char text[DLT_USER_TEXT_LENGTH];
3394
3395     if ((msg==0) || (log==0))
3396     {
3397         return -1;
3398     }
3399
3400     /* Save variables before print */
3401     databuffer_tmp = msg->databuffer;
3402     datasize_tmp = msg->datasize;
3403     databuffersize_tmp = msg->databuffersize;
3404
3405     /* Act like a receiver, convert header back to host format */
3406     msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
3407     dlt_message_get_extraparameters(msg,0);
3408
3409     msg->databuffer = log->buffer;
3410     msg->datasize = log->size;
3411     msg->databuffersize = log->size;
3412
3413     /* Print message as ASCII */
3414     if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
3415     {
3416                 return -1;
3417     }
3418
3419     /* Restore variables and set len to BE*/
3420     msg->databuffer = databuffer_tmp;
3421     msg->databuffersize = databuffersize_tmp;
3422     msg->datasize =  datasize_tmp;
3423
3424     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
3425
3426     return 0;
3427 }
3428
3429 int dlt_user_log_check_user_message(void)
3430 {
3431     int offset=0;
3432     int leave_while=0;
3433
3434     uint32_t i;
3435
3436     DltUserHeader *userheader;
3437     DltReceiver *receiver = &(dlt_user.receiver);
3438
3439     DltUserControlMsgLogLevel *usercontextll;
3440     DltUserControlMsgInjection *usercontextinj;
3441     DltUserControlMsgLogState *userlogstate;
3442     unsigned char *userbuffer;
3443
3444     /* For delayed calling of injection callback, to avoid deadlock */
3445     DltUserInjectionCallback    delayed_injection_callback;
3446     unsigned char                               *delayed_inject_buffer = 0;
3447     uint32_t                                    delayed_inject_data_length = 0;
3448
3449     /* Ensure that callback is null before searching for it */
3450     delayed_injection_callback.injection_callback = 0;
3451     delayed_injection_callback.service_id = 0;
3452
3453     if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
3454     {
3455         while (1)
3456         {
3457             if (dlt_receiver_receive_fd(receiver)<=0)
3458             {
3459                 /* No new message available */
3460                 return 0;
3461             }
3462
3463             /* look through buffer as long as data is in there */
3464             while (1)
3465             {
3466                 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
3467                 {
3468                     break;
3469                 }
3470
3471                 /* resync if necessary */
3472                 offset=0;
3473                 do
3474                 {
3475                     userheader = (DltUserHeader*) (receiver->buf+offset);
3476
3477                     /* Check for user header pattern */
3478                     if (dlt_user_check_userheader(userheader))
3479                     {
3480                         break;
3481                     }
3482                     offset++;
3483
3484                 }
3485                 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
3486
3487                 /* Check for user header pattern */
3488                 if (dlt_user_check_userheader(userheader)<0 ||
3489                     dlt_user_check_userheader(userheader)==0)
3490                 {
3491                     break;
3492                 }
3493
3494                 /* Set new start offset */
3495                 if (offset>0)
3496                 {
3497                     receiver->buf+=offset;
3498                     receiver->bytesRcvd-=offset;
3499                 }
3500
3501                 switch (userheader->message)
3502                 {
3503                 case DLT_USER_MESSAGE_LOG_LEVEL:
3504                 {
3505                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
3506                     {
3507                         leave_while=1;
3508                         break;
3509                     }
3510
3511                     usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
3512
3513                     /* Update log level and trace status */
3514                     if (usercontextll!=0)
3515                     {
3516                         DLT_SEM_LOCK();
3517
3518                         if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
3519                         {
3520                             // printf("Store ll, ts\n");
3521                             if (dlt_user.dlt_ll_ts)
3522                             {
3523                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
3524                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
3525                                 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
3526                                         *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
3527                                 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
3528                                         *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
3529                             }
3530                         }
3531
3532                         DLT_SEM_FREE();
3533                     }
3534
3535                     /* keep not read data in buffer */
3536                     if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
3537                     {
3538                         return -1;
3539                     }
3540                 }
3541                 break;
3542                 case DLT_USER_MESSAGE_INJECTION:
3543                 {
3544                     /* At least, user header, user context, and service id and data_length of injected message is available */
3545                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
3546                     {
3547                         leave_while = 1;
3548                         break;
3549                     }
3550
3551                     usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
3552                     userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
3553
3554                     if (userbuffer!=0)
3555                     {
3556
3557                         if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
3558                         {
3559                             leave_while = 1;
3560                             break;
3561                         }
3562
3563                         DLT_SEM_LOCK();
3564
3565                         if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
3566                         {
3567                             /* Check if injection callback is registered for this context */
3568                             for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
3569                             {
3570                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
3571                                         (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
3572                                 {
3573                                         /* Prepare delayed injection callback call */
3574                                                                         if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
3575                                                                         {
3576                                                                                 delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
3577                                                                                 delayed_injection_callback.service_id = usercontextinj->service_id;
3578                                                                                 delayed_inject_data_length = usercontextinj->data_length_inject;
3579                                                                                 delayed_inject_buffer = malloc(delayed_inject_data_length);
3580                                                                                 if(delayed_inject_buffer != 0) {
3581                                                                                         memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
3582                                                                                 }
3583
3584                                                                         }
3585                                     break;
3586                                 }
3587                             }
3588                         }
3589
3590                         DLT_SEM_FREE();
3591
3592                         /* Delayed injection callback call */
3593                         if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
3594                                 delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
3595                                 delayed_injection_callback.injection_callback = 0;
3596                                 free(delayed_inject_buffer);
3597                                 delayed_inject_buffer = NULL;
3598
3599                         }
3600
3601                         /* keep not read data in buffer */
3602                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
3603                                                 {
3604                                                         return -1;
3605                                                 }
3606                     }
3607                 }
3608                 break;
3609                 case DLT_USER_MESSAGE_LOG_STATE:
3610                 {
3611                     /* At least, user header, user context, and service id and data_length of injected message is available */
3612                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
3613                     {
3614                         leave_while = 1;
3615                         break;
3616                     }
3617
3618                     userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
3619                                         dlt_user.log_state = userlogstate->log_state;
3620
3621                                         /* keep not read data in buffer */
3622                                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
3623                                         {
3624                                                 return -1;
3625                                         }
3626                 }
3627                 break;
3628                 default:
3629                 {
3630                     dlt_log(LOG_ERR,"Invalid user message type received!\n");
3631                     /* Ignore result */
3632                     dlt_receiver_remove(receiver,sizeof(DltUserHeader));
3633                                         /* In next invocation of while loop, a resync will be triggered if additional data was received */
3634                 }
3635                 break;
3636                 } /* switch() */
3637
3638                 if (leave_while==1)
3639                 {
3640                     leave_while=0;
3641                     break;
3642                 }
3643
3644             } /* while buffer*/
3645
3646             if (dlt_receiver_move_to_begin(receiver)==-1)
3647             {
3648                                 return -1;
3649             }
3650         } /* while receive */
3651     } /* if */
3652
3653     return DLT_RETURN_OK;
3654 }
3655
3656 int dlt_user_log_resend_buffer(void)
3657 {
3658         int num,count;
3659     int size;
3660         DltReturnValue ret;
3661         
3662         /* Send content of ringbuffer */
3663         DLT_SEM_LOCK();
3664         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
3665         DLT_SEM_FREE();
3666
3667         for (num=0;num<count;num++)
3668         {
3669
3670                 DLT_SEM_LOCK();
3671                 size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
3672
3673                 if (size>0)
3674                 {
3675 #ifdef DLT_SHM_ENABLE                                           
3676                         dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
3677
3678                         /* log to FIFO */
3679                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
3680 #else
3681                         /* log to FIFO */
3682                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
3683 #endif
3684
3685                         /* in case of error, keep message in ringbuffer */                        
3686                         if (ret==DLT_RETURN_OK)
3687                         {
3688                                 dlt_buffer_remove(&(dlt_user.startup_buffer));
3689                         }
3690                         else
3691                         {
3692                                 /* keep message in ringbuffer */   
3693                                 DLT_SEM_FREE();
3694                                 return -1;
3695                         }
3696                 }
3697                 DLT_SEM_FREE();
3698         }
3699         
3700         return 0;
3701 }
3702
3703 void dlt_user_log_reattach_to_daemon(void)
3704 {
3705         uint32_t num,reregistered=0;
3706
3707         DltContext handle;
3708         DltContextData log_new;
3709
3710     if (dlt_user.dlt_log_handle<0)
3711     {
3712         dlt_user.dlt_log_handle=-1;
3713
3714         /* try to open pipe to dlt daemon */
3715         dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
3716         if (dlt_user.dlt_log_handle > 0)
3717         {
3718             if (dlt_user_log_init(&handle,&log_new)==-1)
3719             {
3720                 return;
3721             }
3722
3723 #ifdef DLT_SHM_ENABLE
3724                         /* init shared memory */
3725                         if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
3726                         {
3727                                 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
3728                                 dlt_log(LOG_WARNING, str);
3729                                 //return 0; 
3730                         }   
3731 #endif
3732
3733             dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
3734
3735             /* Re-register application */
3736             if (dlt_user_log_send_register_application()==-1)
3737             {
3738                 return;
3739             }
3740
3741             DLT_SEM_LOCK();
3742
3743             /* Re-register all stored contexts */
3744             for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
3745             {
3746                 /* Re-register stored context */
3747                 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
3748                 {
3749                     //dlt_set_id(log_new.appID, dlt_user.appID);
3750                     dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
3751                     handle.log_level_pos = num;
3752                     log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
3753
3754                     // Release the mutex for sending context registration:
3755                     // function  dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock
3756                     DLT_SEM_FREE();
3757
3758                     log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
3759                     log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
3760
3761                     if (dlt_user_log_send_register_context(&log_new)==-1)
3762                     {
3763                         return;
3764                     }
3765
3766                     reregistered=1;
3767
3768                     // Lock again the mutex
3769                     // it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section.
3770                     DLT_SEM_LOCK();
3771
3772                 }
3773             }
3774
3775             DLT_SEM_FREE();
3776
3777             if (reregistered==1)
3778             {
3779                                 dlt_user_log_resend_buffer();
3780             }
3781         }
3782     }
3783 }
3784
3785 int dlt_user_log_send_overflow(void)
3786 {
3787     DltUserHeader userheader;
3788     DltUserControlMsgBufferOverflow userpayload;
3789     DltReturnValue ret;
3790
3791     /* set userheader */
3792     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
3793     {
3794         return -1;
3795     }
3796
3797     if (dlt_user.dlt_is_file)
3798     {
3799         return 0;
3800     }
3801
3802     /* set user message parameters */
3803     userpayload.overflow_counter = dlt_user.overflow_counter;
3804     dlt_set_id(userpayload.apid,dlt_user.appID);
3805
3806     /* log to FIFO */
3807     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
3808                               &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
3809     return ((ret==DLT_RETURN_OK)?0:-1);
3810 }
3811
3812 int dlt_user_check_buffer(int *total_size, int *used_size)
3813 {
3814 #ifdef DLT_SHM_ENABLE
3815         *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
3816         *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
3817 #else
3818         *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
3819         *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
3820 #endif
3821         
3822         return 0; /* ok */
3823 }
3824
3825 #ifdef DLT_TEST_ENABLE
3826 void dlt_user_test_corrupt_user_header(int enable)
3827 {
3828     dlt_user.corrupt_user_header = enable;
3829 }
3830 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
3831 {
3832     dlt_user.corrupt_message_size = enable;
3833     dlt_user.corrupt_message_size_size = size;
3834 }
3835 #endif
3836
3837