afedff96bd071b9e2f22f7f8d4e12ca5e10e6e08
[profile/ivi/dlt-daemon.git] / src / daemon / dlt_daemon_common.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012  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 Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
17  *
18  * \file dlt_daemon_common.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23 /*******************************************************************************
24 **                                                                            **
25 **  SRC-MODULE: dlt_daemon_common.c                                           **
26 **                                                                            **
27 **  TARGET    : linux                                                         **
28 **                                                                            **
29 **  PROJECT   : DLT                                                           **
30 **                                                                            **
31 **  AUTHOR    : Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
32 **              Markus Klein                                                  **
33 **                                                                            **
34 **  PURPOSE   :                                                               **
35 **                                                                            **
36 **  REMARKS   :                                                               **
37 **                                                                            **
38 **  PLATFORM DEPENDANT [yes/no]: yes                                          **
39 **                                                                            **
40 **  TO BE CHANGED BY USER [yes/no]: no                                        **
41 **                                                                            **
42 *******************************************************************************/
43
44 /*******************************************************************************
45 **                      Author Identity                                       **
46 ********************************************************************************
47 **                                                                            **
48 ** Initials     Name                       Company                            **
49 ** --------     -------------------------  ---------------------------------- **
50 **  aw          Alexander Wenzel           BMW                                **
51 **  mk          Markus Klein               Fraunhofer ESK                     **
52 *******************************************************************************/
53
54 /*******************************************************************************
55 **                      Revision Control History                              **
56 *******************************************************************************/
57
58 /*
59  * $LastChangedRevision: 1670 $
60  * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
61  * $LastChangedBy$
62  Initials    Date         Comment
63  aw          13.01.2010   initial
64  */
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <syslog.h>
70 #include <errno.h>
71 #include <unistd.h>
72 #include <fcntl.h>
73
74 #include <sys/types.h>  /* send() */
75 #include <sys/socket.h> /* send() */
76
77 #include "dlt_types.h"
78 #include "dlt_daemon_common.h"
79 #include "dlt_daemon_common_cfg.h"
80 #include "dlt_user_shared.h"
81 #include "dlt_user_shared_cfg.h"
82
83 static char str[DLT_DAEMON_COMMON_TEXTBUFSIZE];
84
85 sem_t dlt_daemon_mutex;
86
87 static int dlt_daemon_cmp_apid(const void *m1, const void *m2)
88 {
89     DltDaemonApplication *mi1 = (DltDaemonApplication *) m1;
90     DltDaemonApplication *mi2 = (DltDaemonApplication *) m2;
91
92     return memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
93 }
94
95 static int dlt_daemon_cmp_apid_ctid(const void *m1, const void *m2)
96 {
97
98     int ret, cmp;
99     DltDaemonContext *mi1 = (DltDaemonContext *) m1;
100     DltDaemonContext *mi2 = (DltDaemonContext *) m2;
101
102     cmp=memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
103     if (cmp<0)
104     {
105         ret=-1;
106     }
107     else if (cmp==0)
108     {
109         ret=memcmp(mi1->ctid, mi2->ctid, DLT_ID_SIZE);
110     }
111     else
112     {
113         ret=1;
114     }
115
116     return ret;
117 }
118
119 int dlt_daemon_init(DltDaemon *daemon,const char *runtime_directory, int verbose)
120 {
121     PRINT_FUNCTION_VERBOSE(verbose);
122
123     if (daemon==0)
124     {
125         return -1;
126     }
127
128     int append_length = 0;
129     daemon->num_contexts = 0;
130     daemon->contexts = 0;
131
132     daemon->num_applications = 0;
133     daemon->applications = 0;
134
135     daemon->default_log_level = DLT_DAEMON_INITIAL_LOG_LEVEL ;
136     daemon->default_trace_status = DLT_DAEMON_INITIAL_TRACE_STATUS ;
137
138     daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_NO_OVERFLOW;
139
140     daemon->runtime_context_cfg_loaded = 0;
141     
142     daemon->mode = DLT_USER_MODE_EXTERNAL;
143
144     /* prepare filenames for configuration */
145
146     append_length = PATH_MAX - sizeof(DLT_RUNTIME_APPLICATION_CFG);
147     if(runtime_directory[0])
148         strncpy(daemon->runtime_application_cfg,runtime_directory,append_length);
149     else
150         strcpy(daemon->runtime_application_cfg,DLT_RUNTIME_DEFAULT_DIRECTORY);
151     strcat(daemon->runtime_application_cfg,DLT_RUNTIME_APPLICATION_CFG);
152
153     append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONTEXT_CFG);
154     if(runtime_directory[0])
155         strncpy(daemon->runtime_context_cfg,runtime_directory,append_length);
156     else
157         strcpy(daemon->runtime_context_cfg,DLT_RUNTIME_DEFAULT_DIRECTORY);
158     strcat(daemon->runtime_context_cfg,DLT_RUNTIME_CONTEXT_CFG);
159
160     append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONFIGURATION);
161     if(runtime_directory[0])    
162         strncpy(daemon->runtime_configuration,runtime_directory,append_length);
163     else
164         strcpy(daemon->runtime_configuration,DLT_RUNTIME_DEFAULT_DIRECTORY);
165     strcat(daemon->runtime_configuration,DLT_RUNTIME_CONFIGURATION);
166
167     /* Check for runtime cfg, if it is loadable, load it! */
168     if ((dlt_daemon_applications_load(daemon,daemon->runtime_application_cfg, verbose)==0) &&
169             (dlt_daemon_contexts_load(daemon,daemon->runtime_context_cfg, verbose)==0))
170     {
171         daemon->runtime_context_cfg_loaded = 1;
172     }
173     
174     /* load configuration if available */
175     dlt_daemon_configuration_load(daemon,daemon->runtime_configuration, verbose);
176     
177     daemon->sendserialheader = 0;
178     daemon->timingpackets = 0;
179
180     dlt_set_id(daemon->ecuid,"");
181
182     /* initialize ring buffer for client connection */
183     if (dlt_buffer_init_dynamic(&(daemon->client_ringbuffer), DLT_DAEMON_RINGBUFFER_MIN_SIZE,DLT_DAEMON_RINGBUFFER_MAX_SIZE,DLT_DAEMON_RINGBUFFER_STEP_SIZE)==-1)
184     {
185         return -1;
186     }
187
188     return 0;
189 }
190
191 int dlt_daemon_free(DltDaemon *daemon,int verbose)
192 {
193     PRINT_FUNCTION_VERBOSE(verbose);
194
195     if (daemon==0)
196     {
197         return -1;
198     }
199
200     /* Free contexts */
201     if (dlt_daemon_contexts_clear(daemon, verbose)==-1)
202     {
203                 return -1;
204     }
205
206     /* Free applications */
207     if (dlt_daemon_applications_clear(daemon, verbose)==-1)
208         {
209                 return -1;
210     }
211
212         /* free ringbuffer */
213         dlt_buffer_free_dynamic(&(daemon->client_ringbuffer));
214
215     return 0;
216 }
217
218 int dlt_daemon_applications_invalidate_fd(DltDaemon *daemon,int fd,int verbose)
219 {
220     int i;
221
222     PRINT_FUNCTION_VERBOSE(verbose);
223
224     if (daemon==0)
225     {
226         return -1;
227     }
228
229     for (i=0; i<daemon->num_applications; i++)
230     {
231         if (daemon->applications[i].user_handle==fd)
232         {
233                 daemon->applications[i].user_handle = DLT_FD_INIT;
234         }
235     }
236
237     return 0;
238 }
239
240 int dlt_daemon_applications_clear(DltDaemon *daemon,int verbose)
241 {
242     int i;
243
244     PRINT_FUNCTION_VERBOSE(verbose);
245
246     if (daemon==0)
247     {
248         return -1;
249     }
250
251     for (i=0; i<daemon->num_applications; i++)
252     {
253         if (daemon->applications[i].application_description!=0)
254         {
255             free(daemon->applications[i].application_description);
256             daemon->applications[i].application_description = 0;
257         }
258     }
259
260     if (daemon->applications)
261     {
262         free(daemon->applications);
263     }
264
265     daemon->applications = 0;
266     daemon->num_applications = 0;
267
268     return 0;
269 }
270
271 DltDaemonApplication* dlt_daemon_application_add(DltDaemon *daemon,char *apid,pid_t pid,char *description, int verbose)
272 {
273     DltDaemonApplication *application;
274         DltDaemonApplication *old;
275     int new_application;
276     int dlt_user_handle;
277         char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE];
278
279     if ((daemon==0) || (apid==0) || (apid[0]=='\0'))
280     {
281         return (DltDaemonApplication*) 0;
282     }
283
284     if (daemon->applications == 0)
285     {
286         daemon->applications = (DltDaemonApplication*) malloc(sizeof(DltDaemonApplication)*DLT_DAEMON_APPL_ALLOC_SIZE);
287         if (daemon->applications==0)
288         {
289                 return (DltDaemonApplication*) 0;
290         }
291     }
292
293     new_application=0;
294
295     /* Check if application [apid] is already available */
296     application = dlt_daemon_application_find(daemon, apid, verbose);
297     if (application==0)
298     {
299         daemon->num_applications += 1;
300
301         if (daemon->num_applications!=0)
302         {
303             if ((daemon->num_applications%DLT_DAEMON_APPL_ALLOC_SIZE)==0)
304             {
305                 /* allocate memory in steps of DLT_DAEMON_APPL_ALLOC_SIZE, e.g. 100 */
306                 old = daemon->applications;
307                 daemon->applications = (DltDaemonApplication*) malloc(sizeof(DltDaemonApplication)*
308                                        ((daemon->num_applications/DLT_DAEMON_APPL_ALLOC_SIZE)+1)*DLT_DAEMON_APPL_ALLOC_SIZE);
309                                 if (daemon->applications==0)
310                                 {
311                                         daemon->applications = old;
312                                         daemon->num_applications -= 1;
313                                         return (DltDaemonApplication*) 0;
314                                 }
315                 memcpy(daemon->applications,old,sizeof(DltDaemonApplication)*daemon->num_applications);
316                 free(old);
317             }
318         }
319
320         application = &(daemon->applications[daemon->num_applications-1]);
321
322         dlt_set_id(application->apid,apid);
323         application->pid = 0;
324         application->application_description = 0;
325         application->num_contexts = 0;
326         application->user_handle = DLT_FD_INIT;
327
328         new_application = 1;
329
330     } else {
331
332                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "Duplicate registration of AppId: %s\n",apid);
333                 dlt_log(LOG_ERR, str);
334
335     }
336
337     /* Store application description and pid of application */
338     if (application->application_description)
339     {
340         free(application->application_description);
341         application->application_description=0;
342     }
343
344     if (description)
345     {
346         application->application_description = malloc(strlen(description)+1);
347         if (application->application_description)
348         {
349             strncpy(application->application_description,description,strlen(description)+1);
350             application->application_description[strlen(description)]='\0';
351         }
352     }
353
354     if( application->user_handle != DLT_FD_INIT )
355     {
356         if( application->pid != pid )
357         {
358                 if ( close(application->user_handle) < 0 )
359                 {
360                         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "close() failed to %s, errno=%d (%s)!\n",filename,errno,strerror(errno)); /* errno 2: ENOENT - No such file or directory */
361                     dlt_log(LOG_ERR, str);
362                 }
363
364                 application->user_handle = DLT_FD_INIT;
365                 application->pid = 0;
366         }
367     }
368
369     /* open user pipe only if it is not yet opened */
370     if (application->user_handle==DLT_FD_INIT && pid!=0)
371     {
372         sprintf(filename,"%s/dlt%d",DLT_USER_DIR,pid);
373
374         dlt_user_handle = open(filename, O_WRONLY|O_NONBLOCK);
375         if ( dlt_user_handle < 0 )
376         {
377             snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "open() failed to %s, errno=%d (%s)!\n",filename,errno,strerror(errno)); /* errno 2: ENOENT - No such file or directory */
378             dlt_log(LOG_ERR, str);
379         } /* if */
380
381         /* check if file file descriptor was already used, and make it invalid if it is reused */
382         /* This prevents sending messages to wrong file descriptor */
383         dlt_daemon_applications_invalidate_fd(daemon,dlt_user_handle,verbose);
384         dlt_daemon_contexts_invalidate_fd(daemon,dlt_user_handle,verbose);
385
386         application->pid = pid;
387         application->user_handle = dlt_user_handle;
388     }
389
390     /* Sort */
391     if (new_application)
392     {
393         qsort(daemon->applications,daemon->num_applications,sizeof(DltDaemonApplication),dlt_daemon_cmp_apid);
394
395         /* Find new position of application with apid*/
396         application = dlt_daemon_application_find(daemon, apid, verbose);
397     }
398
399     return application;
400 }
401
402 int dlt_daemon_application_del(DltDaemon *daemon, DltDaemonApplication *application, int verbose)
403 {
404     int pos;
405
406     PRINT_FUNCTION_VERBOSE(verbose);
407
408     if ((daemon==0) || (application==0))
409     {
410         return -1;
411     }
412
413     if (daemon->num_applications>0)
414     {
415         /* Check if user handle is open; if yes, close it */
416         if (application->user_handle >= DLT_FD_MINIMUM)
417         {
418             close(application->user_handle);
419             application->user_handle=DLT_FD_INIT;
420         }
421
422         /* Free description of application to be deleted */
423         if (application->application_description)
424         {
425             free(application->application_description);
426             application->application_description = 0;
427         }
428
429         pos = application-(daemon->applications);
430
431         /* move all applications above pos to pos */
432         memmove(&(daemon->applications[pos]),&(daemon->applications[pos+1]), sizeof(DltDaemonApplication)*((daemon->num_applications-1)-pos));
433
434         /* Clear last application */
435         memset(&(daemon->applications[daemon->num_applications-1]),0,sizeof(DltDaemonApplication));
436
437         daemon->num_applications--;
438
439     }
440
441     return 0;
442 }
443
444 DltDaemonApplication* dlt_daemon_application_find(DltDaemon *daemon,char *apid,int verbose)
445 {
446     DltDaemonApplication application;
447
448     PRINT_FUNCTION_VERBOSE(verbose);
449
450     if ((daemon==0) || (apid==0) || (apid[0]=='\0') || (daemon->num_applications==0))
451     {
452         return (DltDaemonApplication*) 0;
453     }
454
455     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
456     if ((memcmp(apid,daemon->applications[0].apid,DLT_ID_SIZE)<0) ||
457             (memcmp(apid,daemon->applications[daemon->num_applications-1].apid,DLT_ID_SIZE)>0))
458     {
459         return (DltDaemonApplication*) 0;
460     }
461
462     dlt_set_id(application.apid,apid);
463     return (DltDaemonApplication*)bsearch(&application,daemon->applications,daemon->num_applications,sizeof(DltDaemonApplication),dlt_daemon_cmp_apid);
464 }
465
466 int dlt_daemon_applications_load(DltDaemon *daemon,const char *filename, int verbose)
467 {
468     FILE *fd;
469     ID4 apid;
470     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
471     char *ret;
472     char *pb;
473
474     PRINT_FUNCTION_VERBOSE(verbose);
475
476     if ((daemon==0) || (filename==0) || (filename[0]=='\0'))
477     {
478         return -1;
479     }
480
481     fd=fopen(filename, "r");
482
483     if (fd==0)
484     {
485         return -1;
486     }
487
488     while (!feof(fd))
489     {
490         /* Clear buf */
491         memset(buf, 0, sizeof(buf));
492
493         /* Get line */
494         ret=fgets(buf,sizeof(buf),fd);
495         if (NULL == ret)
496         {
497             /* fgets always null pointer if the last byte of the file is a new line
498              * We need to check here if there was an error or was it feof.*/
499             if(ferror(fd))
500             {
501                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_applications_load fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
502                          strerror(errno));
503                 dlt_log(LOG_ERR, str);
504                 fclose(fd);
505                 return -1;
506             }
507             else if(feof(fd))
508             {
509                 fclose(fd);
510                 return 0;
511             }
512             else {
513                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_applications_load fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n");
514                 dlt_log(LOG_ERR, str);
515                 fclose(fd);
516                 return -1;
517             }
518         }
519
520         if (strcmp(buf,"")!=0)
521         {
522             /* Split line */
523             pb=strtok(buf,":");
524             dlt_set_id(apid,pb);
525             pb=strtok(NULL,":");
526             /* pb contains now the description */
527
528             /* pid is unknown at loading time */
529             if (dlt_daemon_application_add(daemon,apid,0,pb,verbose)==0)
530             {
531                 fclose(fd);
532                 return -1;
533             }
534         }
535     }
536     fclose(fd);
537
538     return 0;
539 }
540
541 int dlt_daemon_applications_save(DltDaemon *daemon,const char *filename, int verbose)
542 {
543     FILE *fd;
544     int i;
545
546     char apid[DLT_ID_SIZE+1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
547
548     PRINT_FUNCTION_VERBOSE(verbose);
549
550     if ((daemon==0) || (filename==0) || (filename[0]=='\0'))
551     {
552         return -1;
553     }
554
555     memset(apid,0, sizeof(apid));
556
557     if ((daemon->applications) && (daemon->num_applications>0))
558     {
559         fd=fopen(filename, "w");
560         if (fd!=0)
561         {
562             for (i=0; i<daemon->num_applications; i++)
563             {
564                 dlt_set_id(apid,daemon->applications[i].apid);
565
566                 if ((daemon->applications[i].application_description) &&
567                         (daemon->applications[i].application_description!='\0'))
568                 {
569                     fprintf(fd,"%s:%s:\n",apid, daemon->applications[i].application_description);
570                 }
571                 else
572                 {
573                     fprintf(fd,"%s::\n",apid);
574                 }
575             }
576             fclose(fd);
577         }
578     }
579
580     return 0;
581 }
582
583 DltDaemonContext* dlt_daemon_context_add(DltDaemon *daemon,char *apid,char *ctid,int8_t log_level,int8_t trace_status,int log_level_pos, int user_handle,char *description,int verbose)
584 {
585     DltDaemonApplication *application;
586     DltDaemonContext *context;
587     DltDaemonContext *old;
588     int new_context=0;
589
590     PRINT_FUNCTION_VERBOSE(verbose);
591
592     if ((daemon==0) || (apid==0) || (apid[0]=='\0') || (ctid==0) || (ctid[0]=='\0'))
593     {
594         return (DltDaemonContext*) 0;
595     }
596
597     if ((log_level<DLT_LOG_DEFAULT) || (log_level>DLT_LOG_VERBOSE))
598     {
599         return (DltDaemonContext*) 0;
600     }
601
602     if ((trace_status<DLT_TRACE_STATUS_DEFAULT) || (trace_status>DLT_TRACE_STATUS_ON))
603     {
604         return (DltDaemonContext*) 0;
605     }
606
607     if (daemon->contexts == 0)
608     {
609         daemon->contexts = (DltDaemonContext*) malloc(sizeof(DltDaemonContext)*DLT_DAEMON_CONTEXT_ALLOC_SIZE);
610         if (daemon->contexts==0)
611         {
612                         return (DltDaemonContext*) 0;
613         }
614     }
615
616     /* Check if application [apid] is available */
617     application = dlt_daemon_application_find(daemon, apid, verbose);
618     if (application==0)
619     {
620         return (DltDaemonContext*) 0;
621     }
622
623     /* Check if context [apid, ctid] is already available */
624     context = dlt_daemon_context_find(daemon, apid, ctid, verbose);
625     if (context==0)
626     {
627         daemon->num_contexts += 1;
628
629         if (daemon->num_contexts!=0)
630         {
631             if ((daemon->num_contexts%DLT_DAEMON_CONTEXT_ALLOC_SIZE)==0)
632             {
633                 /* allocate memory for context in steps of DLT_DAEMON_CONTEXT_ALLOC_SIZE, e.g 100 */
634                 old = daemon->contexts;
635                 daemon->contexts = (DltDaemonContext*) malloc(sizeof(DltDaemonContext)*
636                                    ((daemon->num_contexts/DLT_DAEMON_CONTEXT_ALLOC_SIZE)+1)*DLT_DAEMON_CONTEXT_ALLOC_SIZE);
637                                 if (daemon->contexts==0)
638                                 {
639                                         daemon->contexts = old;
640                                         daemon->num_contexts -= 1;
641                                         return (DltDaemonContext*) 0;
642                                 }
643                 memcpy(daemon->contexts,old,sizeof(DltDaemonContext)*daemon->num_contexts);
644                 free(old);
645             }
646         }
647
648         context = &(daemon->contexts[daemon->num_contexts-1]);
649
650         dlt_set_id(context->apid,apid);
651         dlt_set_id(context->ctid,ctid);
652         context->context_description = 0;
653
654         application->num_contexts++;
655         new_context =1;
656     }
657
658     /* Set context description */
659     if (context->context_description)
660     {
661         free(context->context_description);
662         context->context_description=0;
663     }
664
665     if (description)
666     {
667         context->context_description = malloc(strlen(description)+1);
668
669         if (context->context_description)
670         {
671             strncpy(context->context_description,description,strlen(description)+1);
672             context->context_description[strlen(description)]='\0';
673         }
674     }
675
676     /* Store log level and trace status,
677        if this is a new context, or
678        if this is an old context and the runtime cfg was not loaded */
679
680     if ((new_context==1) ||
681             ((new_context==0) && (daemon->runtime_context_cfg_loaded==0)))
682     {
683         context->log_level = log_level;
684         context->trace_status = trace_status;
685     }
686
687     context->log_level_pos = log_level_pos;
688     context->user_handle = user_handle;
689
690     /* Sort */
691     if (new_context)
692     {
693         qsort(daemon->contexts,daemon->num_contexts, sizeof(DltDaemonContext),dlt_daemon_cmp_apid_ctid);
694
695         /* Find new position of context with apid, ctid */
696         context = dlt_daemon_context_find(daemon, apid, ctid, verbose);
697     }
698
699     return context;
700 }
701
702 int dlt_daemon_context_del(DltDaemon *daemon, DltDaemonContext* context, int verbose)
703 {
704     int pos;
705     DltDaemonApplication *application;
706
707     PRINT_FUNCTION_VERBOSE(verbose);
708
709     if ((daemon==0) || (context==0))
710     {
711         return -1;
712     }
713
714     if (daemon->num_contexts>0)
715     {
716         application = dlt_daemon_application_find(daemon, context->apid, verbose);
717
718         /* Free description of context to be deleted */
719         if (context->context_description)
720         {
721             free(context->context_description);
722             context->context_description = 0;
723         }
724
725         pos = context-(daemon->contexts);
726
727         /* move all contexts above pos to pos */
728         memmove(&(daemon->contexts[pos]),&(daemon->contexts[pos+1]), sizeof(DltDaemonContext)*((daemon->num_contexts-1)-pos));
729
730         /* Clear last context */
731         memset(&(daemon->contexts[daemon->num_contexts-1]),0,sizeof(DltDaemonContext));
732
733         daemon->num_contexts--;
734
735         /* Check if application [apid] is available */
736         if (application)
737         {
738             application->num_contexts--;
739         }
740     }
741
742     return 0;
743 }
744
745 DltDaemonContext* dlt_daemon_context_find(DltDaemon *daemon,char *apid,char *ctid,int verbose)
746 {
747     DltDaemonContext context;
748
749     PRINT_FUNCTION_VERBOSE(verbose);
750
751     if ((daemon==0) || (apid==0) || (apid[0]=='\0') || (ctid==0) || (ctid[0]=='\0') || (daemon->num_contexts==0))
752     {
753         return (DltDaemonContext*) 0;
754     }
755
756     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
757     if ((memcmp(apid,daemon->contexts[0].apid,DLT_ID_SIZE)<0) ||
758             (memcmp(apid,daemon->contexts[daemon->num_contexts-1].apid,DLT_ID_SIZE)>0))
759     {
760         return (DltDaemonContext*) 0;
761     }
762
763     dlt_set_id(context.apid,apid);
764     dlt_set_id(context.ctid,ctid);
765
766     return (DltDaemonContext*)bsearch(&context,daemon->contexts,daemon->num_contexts,sizeof(DltDaemonContext),dlt_daemon_cmp_apid_ctid);
767 }
768
769 int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon,int fd,int verbose)
770 {
771     int i;
772
773     PRINT_FUNCTION_VERBOSE(verbose);
774
775     if (daemon==0)
776     {
777         return -1;
778     }
779
780     for (i=0; i<daemon->num_contexts; i++)
781     {
782         if (daemon->contexts[i].user_handle==fd)
783         {
784                 daemon->contexts[i].user_handle = DLT_FD_INIT;
785         }
786     }
787
788     return 0;
789 }
790
791 int dlt_daemon_contexts_clear(DltDaemon *daemon,int verbose)
792 {
793     int i;
794
795     PRINT_FUNCTION_VERBOSE(verbose);
796
797     if (daemon==0)
798     {
799         return -1;
800     }
801
802     for (i=0; i<daemon->num_contexts; i++)
803     {
804         if (daemon->contexts[i].context_description!=0)
805         {
806             free(daemon->contexts[i].context_description);
807             daemon->contexts[i].context_description = 0;
808         }
809     }
810
811     if (daemon->contexts)
812     {
813         free(daemon->contexts);
814     }
815
816     daemon->contexts = 0;
817
818     for (i=0; i<daemon->num_applications; i++)
819     {
820         daemon->applications[i].num_contexts = 0;
821     }
822
823     daemon->num_contexts = 0;
824
825     return 0;
826 }
827
828 int dlt_daemon_contexts_load(DltDaemon *daemon,const char *filename, int verbose)
829 {
830     FILE *fd;
831     ID4 apid, ctid;
832     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
833     char *ret;
834     char *pb;
835     int ll, ts;
836
837     PRINT_FUNCTION_VERBOSE(verbose);
838
839     if ((daemon==0) || (filename==0) ||( filename[0]=='\0'))
840     {
841         return -1;
842     }
843
844     fd=fopen(filename, "r");
845
846     if (fd==0)
847     {
848         return -1;
849     }
850
851     while (!feof(fd))
852     {
853         /* Clear buf */
854         memset(buf, 0, sizeof(buf));
855
856         /* Get line */
857         ret=fgets(buf,sizeof(buf),fd);
858         if (NULL == ret)
859         {
860             /* fgets always returns null pointer if the last byte of the file is a new line.
861              * We need to check here if there was an error or was it feof.*/
862             if(ferror(fd))
863             {
864                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_contexts_load fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
865                          strerror(errno));
866                 dlt_log(LOG_ERR, str);
867                 fclose(fd);
868                 return -1;
869             }
870             else if(feof(fd))
871             {
872                 fclose(fd);
873                 return 0;
874             }
875             else {
876                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_contexts_load fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n");
877                 dlt_log(LOG_ERR, str);
878                 fclose(fd);
879                 return -1;
880             }
881         }
882
883         if (strcmp(buf,"")!=0)
884         {
885             /* Split line */
886             pb=strtok(buf,":");
887             dlt_set_id(apid,pb);
888             pb=strtok(NULL,":");
889             dlt_set_id(ctid,pb);
890             pb=strtok(NULL,":");
891             sscanf(pb,"%d",&ll);
892             pb=strtok(NULL,":");
893             sscanf(pb,"%d",&ts);
894             pb=strtok(NULL,":");
895             /* pb contains now the description */
896
897             /* log_level_pos, and user_handle are unknown at loading time */
898             if (dlt_daemon_context_add(daemon,apid,ctid,(int8_t)ll,(int8_t)ts,0,0,pb,verbose)==0)
899             {
900                                 fclose(fd);
901                                 return -1;
902             }
903         }
904     }
905     fclose(fd);
906
907     return 0;
908 }
909
910 int dlt_daemon_contexts_save(DltDaemon *daemon,const char *filename, int verbose)
911 {
912     FILE *fd;
913     int i;
914
915     char apid[DLT_ID_SIZE+1], ctid[DLT_ID_SIZE+1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
916
917     PRINT_FUNCTION_VERBOSE(verbose);
918
919     if ((daemon==0) || (filename==0) ||( filename[0]=='\0'))
920     {
921         return -1;
922     }
923
924     memset(apid,0, sizeof(apid));
925     memset(ctid,0, sizeof(ctid));
926
927     if ((daemon->contexts) && (daemon->num_contexts>0))
928     {
929         fd=fopen(filename, "w");
930         if (fd!=0)
931         {
932             for (i=0; i<daemon->num_contexts; i++)
933             {
934                 dlt_set_id(apid,daemon->contexts[i].apid);
935                 dlt_set_id(ctid,daemon->contexts[i].ctid);
936
937                 if ((daemon->contexts[i].context_description) &&
938                         (daemon->contexts[i].context_description[0]!='\0'))
939                 {
940                     fprintf(fd,"%s:%s:%d:%d:%s:\n",apid,ctid,
941                             (int)(daemon->contexts[i].log_level),
942                             (int)(daemon->contexts[i].trace_status),
943                             daemon->contexts[i].context_description);
944                 }
945                 else
946                 {
947                     fprintf(fd,"%s:%s:%d:%d::\n",apid,ctid,
948                             (int)(daemon->contexts[i].log_level),
949                             (int)(daemon->contexts[i].trace_status));
950                 }
951             }
952             fclose(fd);
953         }
954     }
955
956     return 0;
957 }
958
959 int dlt_daemon_configuration_save(DltDaemon *daemon,const char *filename, int verbose)
960 {
961     FILE *fd;
962
963     PRINT_FUNCTION_VERBOSE(verbose);
964
965     if ((daemon==0) || (filename==0) ||( filename[0]=='\0'))
966     {
967         return -1;
968     }
969
970         fd=fopen(filename, "w");
971         if (fd!=0)
972         {
973                 fprintf(fd,"# 0 = off, 1 = external, 2 = internal, 3 = both\n");
974                 fprintf(fd,"LoggingMode = %d\n",daemon->mode);
975
976                 fclose(fd);
977         }
978
979     return 0;
980 }
981
982 int dlt_daemon_configuration_load(DltDaemon *daemon,const char *filename, int verbose)
983 {
984         FILE * pFile;
985         char line[1024];
986         char token[1024];
987         char value[1024];
988     char *pch;
989
990     PRINT_FUNCTION_VERBOSE(verbose);
991
992         pFile = fopen (filename,"r");
993
994         if (pFile!=NULL)
995         {
996                 while(1)
997                 {
998                         /* fetch line from configuration file */
999                         if ( fgets (line , 1024 , pFile) != NULL )
1000                         {
1001                                   pch = strtok (line," =\r\n");
1002                                   token[0]=0;
1003                                   value[0]=0;
1004                                   
1005                                   while (pch != NULL)
1006                                   {
1007                                         if(strcmp(pch,"#")==0)
1008                                                 break;
1009
1010                                         if(token[0]==0)
1011                                         {
1012                                                 strncpy(token,pch,sizeof(token));
1013                                         }
1014                                         else
1015                                         {
1016                                                 strncpy(value,pch,sizeof(value));
1017                                                 break;
1018                                         }
1019
1020                                         pch = strtok (NULL, " =\r\n");
1021                                   }
1022                                   
1023                                   if(token[0] && value[0])
1024                                   {
1025                                                 /* parse arguments here */
1026                                                 if(strcmp(token,"LoggingMode")==0)
1027                                                 {
1028                                                         daemon->mode = atoi(value);
1029                                                         sprintf(str,"Runtime Option: %s=%d\n",token,daemon->mode);
1030                                                         dlt_log(LOG_INFO, str);
1031                                                 }
1032                                                 else
1033                                                 {
1034                                                         sprintf(str,"Unknown option: %s=%s\n",token,value);
1035                                                         dlt_log(LOG_ERR, str);
1036                                                 }
1037                                         }
1038                         }
1039                         else
1040                         {
1041                                 break;
1042                         }
1043                 }
1044                 fclose (pFile);
1045         }
1046         else
1047         {
1048         sprintf(str,"Cannot open configuration file: %s\n",filename);
1049         dlt_log(LOG_WARNING, str);
1050         }       
1051         
1052     return 0;
1053 }
1054
1055 int dlt_daemon_user_send_log_level(DltDaemon *daemon,DltDaemonContext *context,int verbose)
1056 {
1057     DltUserHeader userheader;
1058     DltUserControlMsgLogLevel usercontext;
1059     DltReturnValue ret;
1060
1061     PRINT_FUNCTION_VERBOSE(verbose);
1062
1063     if ((daemon==0) || (context==0))
1064     {
1065         return -1;
1066     }
1067
1068     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_LEVEL)==-1)
1069     {
1070         return -1;
1071     }
1072
1073     usercontext.log_level = ((context->log_level == DLT_LOG_DEFAULT)?daemon->default_log_level:context->log_level);
1074     usercontext.trace_status = ((context->trace_status == DLT_TRACE_STATUS_DEFAULT)?daemon->default_trace_status:context->trace_status);
1075
1076     usercontext.log_level_pos = context->log_level_pos;
1077
1078     /* log to FIFO */
1079     ret = dlt_user_log_out2(context->user_handle, &(userheader), sizeof(DltUserHeader),  &(usercontext), sizeof(DltUserControlMsgLogLevel));
1080
1081     if (ret!=DLT_RETURN_OK)
1082     {
1083         if (errno==EPIPE)
1084         {
1085             /* Close connection */
1086             close(context->user_handle);
1087             context->user_handle=DLT_FD_INIT;
1088         }
1089     }
1090
1091     return ((ret==DLT_RETURN_OK)?0:-1);
1092 }
1093
1094 int dlt_daemon_user_send_log_state(DltDaemon *daemon,DltDaemonApplication *app,int verbose)
1095 {
1096     DltUserHeader userheader;
1097     DltUserControlMsgLogState logstate;
1098     DltReturnValue ret;
1099
1100     PRINT_FUNCTION_VERBOSE(verbose);
1101
1102     if ((daemon==0) || (app==0))
1103     {
1104         return -1;
1105     }
1106
1107     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_STATE)==-1)
1108     {
1109         return -1;
1110     }
1111
1112     logstate.log_state = daemon->state;
1113
1114     /* log to FIFO */
1115     ret = dlt_user_log_out2(app->user_handle, &(userheader), sizeof(DltUserHeader),  &(logstate), sizeof(DltUserControlMsgLogState));
1116
1117     if (ret!=DLT_RETURN_OK)
1118     {
1119         if (errno==EPIPE)
1120         {
1121             /* Close connection */
1122             close(app->user_handle);
1123             app->user_handle=DLT_FD_INIT;
1124         }
1125     }
1126
1127     return ((ret==DLT_RETURN_OK)?0:-1);
1128 }
1129
1130 int dlt_daemon_control_process_control(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1131 {
1132     uint32_t id,id_tmp=0;
1133
1134     PRINT_FUNCTION_VERBOSE(verbose);
1135
1136     if ((daemon==0) || (msg==0))
1137     {
1138         return -1;
1139     }
1140
1141     if (msg->datasize < (int32_t)sizeof(uint32_t))
1142     {
1143         return -1;
1144     }
1145
1146     id_tmp = *((uint32_t*)(msg->databuffer));
1147     id=DLT_ENDIAN_GET_32(msg->standardheader->htyp ,id_tmp);
1148
1149     if ((id > 0) && (id <= DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW))
1150     {
1151         /* Control message handling */
1152         switch (id)
1153         {
1154         case DLT_SERVICE_ID_SET_LOG_LEVEL:
1155         {
1156             dlt_daemon_control_set_log_level(sock, daemon, msg,  verbose);
1157             break;
1158         }
1159         case DLT_SERVICE_ID_SET_TRACE_STATUS:
1160         {
1161             dlt_daemon_control_set_trace_status(sock, daemon, msg,  verbose);
1162             break;
1163         }
1164         case DLT_SERVICE_ID_GET_LOG_INFO:
1165         {
1166             dlt_daemon_control_get_log_info(sock, daemon, msg, verbose);
1167             break;
1168         }
1169         case DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL:
1170         {
1171             dlt_daemon_control_get_default_log_level(sock, daemon,  verbose);
1172             break;
1173         }
1174         case DLT_SERVICE_ID_STORE_CONFIG:
1175         {
1176             if (dlt_daemon_applications_save(daemon, daemon->runtime_application_cfg, verbose)==0)
1177             {
1178                                 if (dlt_daemon_contexts_save(daemon, daemon->runtime_context_cfg, verbose)==0)
1179                                 {
1180                                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1181                                 }
1182                                 else
1183                                 {
1184                                         /* Delete saved files */
1185                                         dlt_daemon_control_reset_to_factory_default(daemon, daemon->runtime_application_cfg, daemon->runtime_context_cfg, verbose);
1186                                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1187                                 }
1188             }
1189             else
1190             {
1191                 dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1192             }
1193             break;
1194         }
1195         case DLT_SERVICE_ID_RESET_TO_FACTORY_DEFAULT:
1196         {
1197             dlt_daemon_control_reset_to_factory_default(daemon, daemon->runtime_application_cfg, daemon->runtime_context_cfg, verbose);
1198             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1199             break;
1200         }
1201         case DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS:
1202         {
1203             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1204             break;
1205         }
1206         case DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH:
1207         {
1208             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1209             break;
1210         }
1211         case DLT_SERVICE_ID_SET_VERBOSE_MODE:
1212         {
1213             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1214             break;
1215         }
1216         case DLT_SERVICE_ID_SET_MESSAGE_FILTERING:
1217         {
1218             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1219             break;
1220         }
1221         case DLT_SERVICE_ID_SET_TIMING_PACKETS:
1222         {
1223             dlt_daemon_control_set_timing_packets(sock, daemon, msg,  verbose);
1224             break;
1225         }
1226         case DLT_SERVICE_ID_GET_LOCAL_TIME:
1227         {
1228             /* Send response with valid timestamp (TMSP) field */
1229             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1230             break;
1231         }
1232         case DLT_SERVICE_ID_USE_ECU_ID:
1233         {
1234             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1235             break;
1236         }
1237         case DLT_SERVICE_ID_USE_SESSION_ID:
1238         {
1239             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1240             break;
1241         }
1242         case DLT_SERVICE_ID_USE_TIMESTAMP:
1243         {
1244             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1245             break;
1246         }
1247         case DLT_SERVICE_ID_USE_EXTENDED_HEADER:
1248         {
1249             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1250             break;
1251         }
1252         case DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL:
1253         {
1254             dlt_daemon_control_set_default_log_level(sock, daemon, msg,  verbose);
1255             break;
1256         }
1257         case DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS:
1258         {
1259             dlt_daemon_control_set_default_trace_status(sock, daemon, msg,  verbose);
1260             break;
1261         }
1262         case DLT_SERVICE_ID_GET_SOFTWARE_VERSION:
1263         {
1264             dlt_daemon_control_get_software_version(sock, daemon,  verbose);
1265             break;
1266         }
1267         case DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW:
1268         {
1269             dlt_daemon_control_message_buffer_overflow(sock, daemon,  verbose);
1270             break;
1271         }
1272         default:
1273         {
1274             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1275             break;
1276         }
1277         }
1278     }
1279     else
1280     {
1281         /* Injection handling */
1282         dlt_daemon_control_callsw_cinjection(sock, daemon, msg,  verbose);
1283     }
1284
1285     return 0;
1286 }
1287
1288 void dlt_daemon_control_callsw_cinjection(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1289 {
1290     char apid[DLT_ID_SIZE],ctid[DLT_ID_SIZE];
1291     uint32_t id=0,id_tmp=0;
1292     uint8_t *ptr;
1293     DltDaemonContext *context;
1294         int32_t data_length_inject=0;
1295         uint32_t data_length_inject_tmp=0;
1296
1297         int32_t datalength;
1298
1299         DltUserHeader userheader;
1300         DltUserControlMsgInjection usercontext;
1301         uint8_t *userbuffer;
1302
1303     PRINT_FUNCTION_VERBOSE(verbose);
1304
1305     if ((daemon==0) || (msg==0))
1306     {
1307         return;
1308     }
1309
1310     datalength = msg->datasize;
1311     ptr = msg->databuffer;
1312
1313     if (ptr==0)
1314     {
1315         return;
1316     }
1317
1318     DLT_MSG_READ_VALUE(id_tmp,ptr,datalength,uint32_t); /* Get service id */
1319     id=DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp);
1320
1321     if ((id>=DLT_DAEMON_INJECTION_MIN) && (id<=DLT_DAEMON_INJECTION_MAX))
1322     {
1323         /* This a a real SW-C injection call */
1324         data_length_inject=0;
1325         data_length_inject_tmp=0;
1326
1327         DLT_MSG_READ_VALUE(data_length_inject_tmp,ptr,datalength,uint32_t); /* Get data length */
1328         data_length_inject=DLT_ENDIAN_GET_32(msg->standardheader->htyp, data_length_inject_tmp);
1329
1330         /* Get context handle for apid, ctid (and seid) */
1331         /* Warning: seid is ignored in this implementation! */
1332         if (DLT_IS_HTYP_UEH(msg->standardheader->htyp))
1333         {
1334             dlt_set_id(apid, msg->extendedheader->apid);
1335             dlt_set_id(ctid, msg->extendedheader->ctid);
1336         }
1337         else
1338         {
1339             /* No extended header, and therefore no apid and ctid available */
1340             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1341             return;
1342         }
1343
1344         /* At this point, apid and ctid is available */
1345         context=dlt_daemon_context_find(daemon, apid, ctid, verbose);
1346
1347         if (context==0)
1348         {
1349             // dlt_log(LOG_INFO,"No context found!\n");
1350             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1351             return;
1352         }
1353
1354         /* Send user message to handle, specified in context */
1355                 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_INJECTION)==-1)
1356                 {
1357                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1358                         return;
1359                 }
1360
1361                 usercontext.log_level_pos = context->log_level_pos;
1362
1363                 if(data_length_inject > msg->databuffersize)
1364                 {
1365                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1366                         return;
1367                 }
1368
1369                 userbuffer = malloc(data_length_inject);
1370
1371                 if (userbuffer==0)
1372                 {
1373                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1374                         return;
1375                 }
1376
1377                 usercontext.data_length_inject = data_length_inject;
1378                 usercontext.service_id = id;
1379
1380                 memcpy(userbuffer,ptr,data_length_inject);  /* Copy received injection to send buffer */
1381
1382                 /* write to FIFO */
1383                 DltReturnValue ret =
1384                                 dlt_user_log_out3(context->user_handle, &(userheader), sizeof(DltUserHeader),
1385                                   &(usercontext), sizeof(DltUserControlMsgInjection),
1386                                   userbuffer, data_length_inject);
1387                 if (ret != DLT_RETURN_OK)
1388                 {
1389                         if (ret == DLT_RETURN_PIPE_ERROR)
1390                         {
1391                                 /* Close connection */
1392                                 close(context->user_handle);
1393                                 context->user_handle=DLT_FD_INIT;
1394                         }
1395                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1396                 }
1397                 else
1398                 {
1399                         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1400                 }
1401
1402                 free(userbuffer);
1403                 userbuffer=0;
1404
1405     }
1406     else
1407     {
1408         /* Invalid ID */
1409         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_NOT_SUPPORTED,  verbose);
1410     }
1411 }
1412
1413 void dlt_daemon_control_set_log_level(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1414 {
1415     PRINT_FUNCTION_VERBOSE(verbose);
1416
1417     char apid[DLT_ID_SIZE],ctid[DLT_ID_SIZE];
1418     DltServiceSetLogLevel *req;
1419     DltDaemonContext *context;
1420     int32_t id=DLT_SERVICE_ID_SET_LOG_LEVEL;
1421
1422         int8_t old_log_level;
1423
1424     if ((daemon==0) || (msg==0))
1425     {
1426         return;
1427     }
1428
1429     req = (DltServiceSetLogLevel*) (msg->databuffer);
1430
1431     dlt_set_id(apid, req->apid);
1432     dlt_set_id(ctid, req->ctid);
1433
1434     context=dlt_daemon_context_find(daemon, apid, ctid, verbose);
1435
1436     /* Set log level */
1437     if (context!=0)
1438     {
1439         old_log_level = context->log_level;
1440         context->log_level = req->log_level; /* No endianess conversion necessary*/
1441
1442         if ((context->user_handle >= DLT_FD_MINIMUM) &&
1443                 (dlt_daemon_user_send_log_level(daemon, context, verbose)==0))
1444         {
1445             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1446         }
1447         else
1448         {
1449             //dlt_log(LOG_ERR, "Log level could not be sent!\n");
1450             context->log_level = old_log_level;
1451             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1452         }
1453     }
1454     else
1455     {
1456         //dlt_log(LOG_ERR, "Context not found!\n");
1457         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1458     }
1459 }
1460
1461 void dlt_daemon_control_set_trace_status(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1462 {
1463     PRINT_FUNCTION_VERBOSE(verbose);
1464
1465     char apid[DLT_ID_SIZE],ctid[DLT_ID_SIZE];
1466     DltServiceSetLogLevel *req;             /* request uses same struct as set log level */
1467     DltDaemonContext *context;
1468     int32_t id=DLT_SERVICE_ID_SET_TRACE_STATUS;
1469
1470         int8_t old_trace_status;
1471
1472     if ((daemon==0) || (msg==0))
1473     {
1474         return;
1475     }
1476
1477     req = (DltServiceSetLogLevel*) (msg->databuffer);
1478
1479     dlt_set_id(apid, req->apid);
1480     dlt_set_id(ctid, req->ctid);
1481
1482     context=dlt_daemon_context_find(daemon, apid, ctid, verbose);
1483
1484     /* Set log level */
1485     if (context!=0)
1486     {
1487         old_trace_status = context->trace_status;
1488         context->trace_status = req->log_level;   /* No endianess conversion necessary */
1489
1490         if ((context->user_handle >= DLT_FD_MINIMUM ) &&
1491                 (dlt_daemon_user_send_log_level(daemon, context, verbose)==0))
1492         {
1493             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1494         }
1495         else
1496         {
1497             //dlt_log(LOG_ERR, "Trace Status could not be sent!\n");
1498             context->trace_status = old_trace_status;
1499             dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1500         }
1501     }
1502     else
1503     {
1504         //dlt_log(LOG_ERR, "Context not found!\n");
1505         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1506     }
1507 }
1508
1509 void dlt_daemon_control_set_default_log_level(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1510 {
1511     PRINT_FUNCTION_VERBOSE(verbose);
1512
1513     DltServiceSetDefaultLogLevel *req;
1514     int32_t id=DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL;
1515
1516     if ((daemon==0) || (msg==0))
1517     {
1518         return;
1519     }
1520
1521     req = (DltServiceSetDefaultLogLevel*) (msg->databuffer);
1522
1523     /* No endianess conversion necessary */
1524     if (/*(req->log_level>=0) &&*/
1525             (req->log_level<=DLT_LOG_VERBOSE))
1526     {
1527         daemon->default_log_level = req->log_level; /* No endianess conversion necessary */
1528
1529         /* Send Update to all contexts using the default log level */
1530         dlt_daemon_user_send_default_update(daemon, verbose);
1531
1532         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1533     }
1534     else
1535     {
1536         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1537     }
1538 }
1539
1540 void dlt_daemon_control_set_default_trace_status(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1541 {
1542     PRINT_FUNCTION_VERBOSE(verbose);
1543
1544     /* Payload of request message */
1545     DltServiceSetDefaultLogLevel *req;
1546     int32_t id=DLT_SERVICE_ID_SET_DEFAULT_TRACE_STATUS;
1547
1548     if ((daemon==0) || (msg==0))
1549     {
1550         return;
1551     }
1552
1553     req = (DltServiceSetDefaultLogLevel*) (msg->databuffer);
1554
1555     /* No endianess conversion necessary */
1556     if ((req->log_level==DLT_TRACE_STATUS_OFF) ||
1557             (req->log_level==DLT_TRACE_STATUS_ON))
1558     {
1559         daemon->default_trace_status = req->log_level; /* No endianess conversion necessary*/
1560
1561         /* Send Update to all contexts using the default trace status */
1562         dlt_daemon_user_send_default_update(daemon, verbose);
1563
1564         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1565     }
1566     else
1567     {
1568         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1569     }
1570 }
1571
1572 void dlt_daemon_control_set_timing_packets(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1573 {
1574     PRINT_FUNCTION_VERBOSE(verbose);
1575
1576     DltServiceSetVerboseMode *req;  /* request uses same struct as set verbose mode */
1577     int32_t id=DLT_SERVICE_ID_SET_TIMING_PACKETS;
1578
1579     if ((daemon==0) || (msg==0))
1580     {
1581         return;
1582     }
1583
1584     req = (DltServiceSetVerboseMode*) (msg->databuffer);
1585     if ((req->new_status==0) || (req->new_status==1))
1586     {
1587         daemon->timingpackets = req->new_status;
1588
1589         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_OK,  verbose);
1590     }
1591     else
1592     {
1593         dlt_daemon_control_service_response(sock, daemon, id, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1594     }
1595 }
1596
1597 void dlt_daemon_control_get_software_version(int sock, DltDaemon *daemon, int verbose)
1598 {
1599     DltMessage msg;
1600     uint32_t len;
1601         DltServiceGetSoftwareVersionResponse *resp;
1602
1603     PRINT_FUNCTION_VERBOSE(verbose);
1604
1605     if (daemon==0)
1606     {
1607         return;
1608     }
1609
1610     /* initialise new message */
1611     if (dlt_message_init(&msg,0)==-1)
1612     {
1613         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_SOFTWARE_VERSION, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1614                 return;
1615     }
1616
1617     /* prepare payload of data */
1618     len = strlen(daemon->ECUVersionString);
1619
1620     msg.datasize = sizeof(DltServiceGetSoftwareVersionResponse) + len;
1621     if (msg.databuffer && (msg.databuffersize < msg.datasize))
1622     {
1623         free(msg.databuffer);
1624         msg.databuffer=0;
1625     }
1626     if (msg.databuffer == 0){
1627         msg.databuffer = (uint8_t *) malloc(msg.datasize);
1628         msg.databuffersize = msg.datasize;
1629     }
1630     if (msg.databuffer==0)
1631     {
1632         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_SOFTWARE_VERSION, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1633         return;
1634     }
1635
1636     resp = (DltServiceGetSoftwareVersionResponse*) msg.databuffer;
1637     resp->service_id = DLT_SERVICE_ID_GET_SOFTWARE_VERSION;
1638     resp->status = DLT_SERVICE_RESPONSE_OK;
1639     resp->length = len;
1640     memcpy(msg.databuffer+sizeof(DltServiceGetSoftwareVersionResponse),daemon->ECUVersionString,len);
1641
1642     /* send message */
1643     dlt_daemon_control_send_control_message(sock, daemon, &msg,"","",  verbose);
1644
1645     /* free message */
1646     dlt_message_free(&msg,0);
1647 }
1648
1649 void dlt_daemon_control_get_default_log_level(int sock, DltDaemon *daemon, int verbose)
1650 {
1651     DltMessage msg;
1652         DltServiceGetDefaultLogLevelResponse *resp;
1653
1654     PRINT_FUNCTION_VERBOSE(verbose);
1655
1656     if (daemon==0)
1657     {
1658         return;
1659     }
1660
1661     /* initialise new message */
1662     if (dlt_message_init(&msg,0)==-1)
1663     {
1664         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1665         return;
1666     }
1667
1668     msg.datasize = sizeof(DltServiceGetDefaultLogLevelResponse);
1669     if (msg.databuffer && (msg.databuffersize<msg.datasize))
1670     {
1671         free(msg.databuffer);
1672         msg.databuffer=0;
1673     }
1674     if (msg.databuffer == 0){
1675         msg.databuffer = (uint8_t *) malloc(msg.datasize);
1676         msg.databuffersize = msg.datasize;
1677     }
1678     if (msg.databuffer==0)
1679     {
1680         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1681         return;
1682     }
1683
1684     resp = (DltServiceGetDefaultLogLevelResponse*) msg.databuffer;
1685     resp->service_id = DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL;
1686     resp->status = DLT_SERVICE_RESPONSE_OK;
1687     resp->log_level = daemon->default_log_level;
1688
1689     /* send message */
1690     dlt_daemon_control_send_control_message(sock,daemon,&msg,"","",  verbose);
1691
1692     /* free message */
1693     dlt_message_free(&msg,0);
1694 }
1695
1696 void dlt_daemon_control_get_log_info(int sock, DltDaemon *daemon, DltMessage *msg, int verbose)
1697 {
1698     DltServiceGetLogInfoRequest *req;
1699     DltMessage resp;
1700     DltDaemonContext *context=0;
1701     DltDaemonApplication *application=0;
1702
1703     int num_applications=0, num_contexts=0;
1704     uint16_t count_app_ids=0, count_con_ids=0;
1705
1706 #if (DLT_DEBUG_GETLOGINFO==1)
1707     char buf[255];
1708 #endif
1709
1710     int32_t i,j,offset=0;
1711     char *apid=0;
1712     int8_t ll,ts;
1713     uint16_t len;
1714     int8_t value;
1715     int32_t sizecont=0;
1716     int offset_base;
1717
1718     uint32_t sid;
1719
1720     PRINT_FUNCTION_VERBOSE(verbose);
1721
1722     if ((daemon==0) || (msg==0))
1723     {
1724         return;
1725     }
1726
1727     /* prepare pointer to message request */
1728     req = (DltServiceGetLogInfoRequest*) (msg->databuffer);
1729
1730     /* initialise new message */
1731     if (dlt_message_init(&resp,0)==-1)
1732     {
1733                 dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_LOG_INFO, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1734         return;
1735     }
1736
1737     /* check request */
1738     if ((req->options < 3 ) || (req->options>7))
1739     {
1740         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_LOG_INFO, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1741         return;
1742     }
1743
1744     if (req->apid[0]!='\0')
1745     {
1746         application = dlt_daemon_application_find(daemon, req->apid, verbose);
1747         if (application)
1748         {
1749             num_applications = 1;
1750             if (req->ctid[0]!='\0')
1751             {
1752                 context = dlt_daemon_context_find(daemon, req->apid, req->ctid, verbose);
1753
1754                 num_contexts = ((context)?1:0);
1755             }
1756             else
1757             {
1758                 num_contexts = application->num_contexts;
1759             }
1760         }
1761         else
1762         {
1763             num_applications = 0;
1764             num_contexts = 0;
1765         }
1766     }
1767     else
1768     {
1769         /* Request all applications and contexts */
1770         num_applications = daemon->num_applications;
1771         num_contexts = daemon->num_contexts;
1772     }
1773
1774     /* prepare payload of data */
1775
1776     /* Calculate maximum size for a response */
1777     resp.datasize = sizeof(uint32_t) /* SID */ + sizeof(int8_t) /* status*/ + sizeof(ID4) /* DLT_DAEMON_REMO_STRING */;
1778
1779     sizecont = sizeof(uint32_t) /* context_id */;
1780
1781     /* Add additional size for response of Mode 4, 6, 7 */
1782     if ((req->options==4) || (req->options==6) || (req->options==7))
1783     {
1784         sizecont += sizeof(int8_t); /* log level */
1785     }
1786
1787     /* Add additional size for response of Mode 5, 6, 7 */
1788     if ((req->options==5) || (req->options==6) || (req->options==7))
1789     {
1790         sizecont+= sizeof(int8_t); /* trace status */
1791     }
1792
1793     resp.datasize+= (num_applications * (sizeof(uint32_t) /* app_id */  + sizeof(uint16_t) /* count_con_ids */)) +
1794                     (num_contexts * sizecont);
1795
1796     resp.datasize+= sizeof(uint16_t) /* count_app_ids */;
1797
1798     /* Add additional size for response of Mode 7 */
1799     if (req->options==7)
1800     {
1801         if (req->apid[0]!='\0')
1802         {
1803             if (req->ctid[0]!='\0')
1804             {
1805                 /* One application, one context */
1806                 // context = dlt_daemon_context_find(daemon, req->apid, req->ctid, verbose);
1807                 if (context)
1808                 {
1809                     resp.datasize+=sizeof(uint16_t) /* len_context_description */;
1810                     if (context->context_description!=0)
1811                     {
1812                         resp.datasize+=strlen(context->context_description); /* context_description */
1813                     }
1814                 }
1815             }
1816             else
1817             {
1818                 /* One application, all contexts */
1819                 if ((daemon->applications) && (application))
1820                 {
1821                     /* Calculate start offset within contexts[] */
1822                     offset_base=0;
1823                     for (i=0; i<(application-(daemon->applications)); i++)
1824                     {
1825                         offset_base+=daemon->applications[i].num_contexts;
1826                     }
1827
1828                     /* Iterate over all contexts belonging to this application */
1829                     for (j=0;j<application->num_contexts;j++)
1830                     {
1831
1832                         context = &(daemon->contexts[offset_base+j]);
1833                         if (context)
1834                         {
1835                             resp.datasize+=sizeof(uint16_t) /* len_context_description */;
1836                             if (context->context_description!=0)
1837                             {
1838                                 resp.datasize+=strlen(context->context_description); /* context_description */
1839                             }
1840                         }
1841                     }
1842                 }
1843             }
1844
1845             /* Space for application description */
1846             if (application)
1847             {
1848                 resp.datasize+=sizeof(uint16_t) /* len_app_description */;
1849                 if (application->application_description!=0)
1850                 {
1851                     resp.datasize+=strlen(application->application_description); /* app_description */
1852                 }
1853             }
1854         }
1855         else
1856         {
1857             /* All applications, all contexts */
1858             for (i=0;i<daemon->num_contexts;i++)
1859             {
1860                 resp.datasize+=sizeof(uint16_t) /* len_context_description */;
1861                 if (daemon->contexts[i].context_description!=0)
1862                 {
1863                     resp.datasize+=strlen(daemon->contexts[i].context_description); /* context_description */
1864                 }
1865             }
1866
1867             for (i=0;i<daemon->num_applications;i++)
1868             {
1869                 resp.datasize+=sizeof(uint16_t) /* len_app_description */;
1870                 if (daemon->applications[i].application_description!=0)
1871                 {
1872                     resp.datasize+=strlen(daemon->applications[i].application_description); /* app_description */
1873                 }
1874             }
1875         }
1876     }
1877
1878     if (verbose)
1879     {
1880         sprintf(str,"Allocate %d bytes for response msg databuffer\n", resp.datasize);
1881         dlt_log(LOG_INFO, str);
1882     }
1883
1884     /* Allocate buffer for response message */
1885     resp.databuffer = (uint8_t *) malloc(resp.datasize);
1886     resp.databuffersize = resp.datasize;
1887
1888     if (resp.databuffer==0)
1889     {
1890         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_GET_LOG_INFO, DLT_SERVICE_RESPONSE_ERROR,  verbose);
1891         return;
1892     }
1893     memset(resp.databuffer,0,resp.datasize);
1894     /* Preparation finished */
1895
1896     /* Prepare response */
1897     sid = DLT_SERVICE_ID_GET_LOG_INFO;
1898     memcpy(resp.databuffer,&sid,sizeof(uint32_t));
1899     offset+=sizeof(uint32_t);
1900
1901     value = (((num_applications!=0)&&(num_contexts!=0))?req->options:8); /* 8 = no matching context found */
1902
1903     memcpy(resp.databuffer+offset,&value,sizeof(int8_t));
1904     offset+=sizeof(int8_t);
1905
1906     count_app_ids = num_applications;
1907
1908     if (count_app_ids!=0)
1909     {
1910         memcpy(resp.databuffer+offset,&count_app_ids,sizeof(uint16_t));
1911         offset+=sizeof(uint16_t);
1912
1913 #if (DLT_DEBUG_GETLOGINFO==1)
1914         sprintf(str,"#apid: %d \n", count_app_ids);
1915         dlt_log(LOG_DEBUG, str);
1916 #endif
1917
1918         for (i=0;i<count_app_ids;i++)
1919         {
1920             if (req->apid[0]!='\0')
1921             {
1922                 apid = req->apid;
1923             }
1924             else
1925             {
1926                 if (daemon->applications)
1927                 {
1928                     apid = daemon->applications[i].apid;
1929                 }
1930                 else
1931                 {
1932                     /* This should never occur! */
1933                     apid=0;
1934                 }
1935             }
1936
1937             application = dlt_daemon_application_find(daemon, apid, verbose);
1938
1939             if (application)
1940             {
1941                 /* Calculate start offset within contexts[] */
1942                 offset_base=0;
1943                 for (j=0; j<(application-(daemon->applications)); j++)
1944                 {
1945                     offset_base+=daemon->applications[j].num_contexts;
1946                 }
1947
1948                 dlt_set_id((char*)(resp.databuffer+offset),apid);
1949                 offset+=sizeof(ID4);
1950
1951 #if (DLT_DEBUG_GETLOGINFO==1)
1952                 dlt_print_id(buf, apid);
1953                 sprintf(str,"apid: %s\n",buf);
1954                 dlt_log(LOG_DEBUG, str);
1955 #endif
1956
1957                 if (req->apid[0]!='\0')
1958                 {
1959                     count_con_ids = num_contexts;
1960                 }
1961                 else
1962                 {
1963                     count_con_ids = application->num_contexts;
1964                 }
1965
1966                 memcpy(resp.databuffer+offset,&count_con_ids,sizeof(uint16_t));
1967                 offset+=sizeof(uint16_t);
1968
1969 #if (DLT_DEBUG_GETLOGINFO==1)
1970                 sprintf(str,"#ctid: %d \n", count_con_ids);
1971                 dlt_log(LOG_DEBUG, str);
1972 #endif
1973
1974                 for (j=0;j<count_con_ids;j++)
1975                 {
1976 #if (DLT_DEBUG_GETLOGINFO==1)
1977                     sprintf(str,"j: %d \n",j);
1978                     dlt_log(LOG_DEBUG, str);
1979 #endif
1980                     if (!((count_con_ids==1) && (req->apid[0]!='\0') && (req->ctid[0]!='\0')))
1981                     {
1982                         context = &(daemon->contexts[offset_base+j]);
1983                     }
1984                     /* else: context was already searched and found
1985                              (one application (found) with one context (found))*/
1986
1987                     if ((context) &&
1988                             ((req->ctid[0]=='\0') ||
1989                              ((req->ctid[0]!='\0') && (memcmp(context->ctid,req->ctid,DLT_ID_SIZE)==0)))
1990                        )
1991                     {
1992                         dlt_set_id((char*)(resp.databuffer+offset),context->ctid);
1993                         offset+=sizeof(ID4);
1994
1995 #if (DLT_DEBUG_GETLOGINFO==1)
1996                         dlt_print_id(buf, context->ctid);
1997                         sprintf(str,"ctid: %s \n",buf);
1998                         dlt_log(LOG_DEBUG, str);
1999 #endif
2000
2001                         /* Mode 4, 6, 7 */
2002                         if ((req->options==4) || (req->options==6) || (req->options==7))
2003                         {
2004                             ll=context->log_level;
2005                             memcpy(resp.databuffer+offset,&ll,sizeof(int8_t));
2006                             offset+=sizeof(int8_t);
2007                         }
2008
2009                         /* Mode 5, 6, 7 */
2010                         if ((req->options==5) || (req->options==6) || (req->options==7))
2011                         {
2012                             ts=context->trace_status;
2013                             memcpy(resp.databuffer+offset,&ts,sizeof(int8_t));
2014                             offset+=sizeof(int8_t);
2015                         }
2016
2017                         /* Mode 7 */
2018                         if (req->options==7)
2019                         {
2020                             if (context->context_description)
2021                             {
2022                                 len = strlen(context->context_description);
2023                                 memcpy(resp.databuffer+offset,&len,sizeof(uint16_t));
2024                                 offset+=sizeof(uint16_t);
2025                                 memcpy(resp.databuffer+offset,context->context_description,strlen(context->context_description));
2026                                 offset+=strlen(context->context_description);
2027                             }
2028                             else
2029                             {
2030                                 len = 0;
2031                                 memcpy(resp.databuffer+offset,&len,sizeof(uint16_t));
2032                                 offset+=sizeof(uint16_t);
2033                             }
2034                         }
2035
2036 #if (DLT_DEBUG_GETLOGINFO==1)
2037                         sprintf(str,"ll=%d ts=%d \n",(int32_t)ll,(int32_t)ts);
2038                         dlt_log(LOG_DEBUG, str);
2039 #endif
2040                     }
2041
2042 #if (DLT_DEBUG_GETLOGINFO==1)
2043                     dlt_log(LOG_DEBUG,"\n");
2044 #endif
2045                 }
2046
2047                 /* Mode 7 */
2048                 if (req->options==7)
2049                 {
2050                     if (application->application_description)
2051                     {
2052                         len = strlen(application->application_description);
2053                         memcpy(resp.databuffer+offset,&len,sizeof(uint16_t));
2054                         offset+=sizeof(uint16_t);
2055                         memcpy(resp.databuffer+offset,application->application_description,strlen(application->application_description));
2056                         offset+=strlen(application->application_description);
2057                     }
2058                     else
2059                     {
2060                         len = 0;
2061                         memcpy(resp.databuffer+offset,&len,sizeof(uint16_t));
2062                         offset+=sizeof(uint16_t);
2063                     }
2064                 }
2065             } /* if (application) */
2066         } /* for (i=0;i<count_app_ids;i++) */
2067     } /* if (count_app_ids!=0) */
2068
2069     dlt_set_id((char*)(resp.databuffer+offset),DLT_DAEMON_REMO_STRING);
2070
2071     /* send message */
2072     dlt_daemon_control_send_control_message(sock,daemon,&resp,"","",  verbose);
2073
2074     /* free message */
2075     dlt_message_free(&resp,0);
2076 }
2077
2078 void dlt_daemon_control_message_buffer_overflow(int sock, DltDaemon *daemon, int verbose)
2079 {
2080     DltMessage msg;
2081         DltServiceMessageBufferOverflowResponse *resp;
2082
2083     PRINT_FUNCTION_VERBOSE(verbose);
2084
2085     if (daemon==0)
2086     {
2087         return;
2088     }
2089
2090     /* initialise new message */
2091     if (dlt_message_init(&msg,0)==-1)
2092     {
2093         dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW, DLT_SERVICE_RESPONSE_ERROR,  verbose);
2094         return;
2095     }
2096
2097     /* prepare payload of data */
2098     msg.datasize = sizeof(DltServiceMessageBufferOverflowResponse);
2099     if (msg.databuffer && (msg.databuffersize < msg.datasize))
2100     {
2101         free(msg.databuffer);
2102         msg.databuffer=0;
2103     }
2104     if (msg.databuffer == 0){
2105         msg.databuffer = (uint8_t *) malloc(msg.datasize);
2106         msg.databuffersize = msg.datasize;
2107     }
2108     if (msg.databuffer==0)
2109     {
2110         if (sock!=DLT_DAEMON_STORE_TO_BUFFER)
2111         {
2112             dlt_daemon_control_service_response(sock, daemon, DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW, DLT_SERVICE_RESPONSE_ERROR,  verbose);
2113         }
2114         return;
2115     }
2116
2117     resp = (DltServiceMessageBufferOverflowResponse*) msg.databuffer;
2118     resp->service_id = DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW;
2119     resp->status = DLT_SERVICE_RESPONSE_OK;
2120     resp->overflow = daemon->message_buffer_overflow;
2121
2122     /* send message */
2123     dlt_daemon_control_send_control_message(sock,daemon,&msg,"","",  verbose);
2124
2125     /* free message */
2126     dlt_message_free(&msg,0);
2127 }
2128
2129 void dlt_daemon_control_service_response( int sock, DltDaemon *daemon, uint32_t service_id, int8_t status , int verbose)
2130 {
2131     DltMessage msg;
2132     DltServiceResponse *resp;
2133
2134     PRINT_FUNCTION_VERBOSE(verbose);
2135
2136     if (daemon==0)
2137     {
2138         return;
2139     }
2140
2141     /* initialise new message */
2142     if (dlt_message_init(&msg,0)==-1)
2143     {
2144                 return;
2145     }
2146
2147     /* prepare payload of data */
2148     msg.datasize = sizeof(DltServiceResponse);
2149     if (msg.databuffer && (msg.databuffersize < msg.datasize))
2150     {
2151         free(msg.databuffer);
2152         msg.databuffer=0;
2153     }
2154     if (msg.databuffer == 0){
2155         msg.databuffer = (uint8_t *) malloc(msg.datasize);
2156         msg.databuffersize = msg.datasize;
2157     }
2158     if (msg.databuffer==0)
2159     {
2160         return;
2161     }
2162
2163     resp = (DltServiceResponse*) msg.databuffer;
2164     resp->service_id = service_id;
2165     resp->status = status;
2166
2167     /* send message */
2168     dlt_daemon_control_send_control_message(sock,daemon,&msg,"","",  verbose);
2169
2170     /* free message */
2171     dlt_message_free(&msg,0);
2172 }
2173
2174 void dlt_daemon_control_send_control_message( int sock, DltDaemon *daemon, DltMessage *msg, char* appid, char* ctid, int verbose)
2175 {
2176     ssize_t ret;
2177     int32_t len;
2178
2179     PRINT_FUNCTION_VERBOSE(verbose);
2180
2181     if ((daemon==0) || (msg==0) || (appid==0) || (ctid==0))
2182     {
2183         return;
2184     }
2185
2186     /* prepare storage header */
2187     msg->storageheader = (DltStorageHeader*)msg->headerbuffer;
2188
2189     if (dlt_set_storageheader(msg->storageheader,daemon->ecuid)==-1)
2190     {
2191                 return;
2192     }
2193
2194     /* prepare standard header */
2195     msg->standardheader = (DltStandardHeader*)(msg->headerbuffer + sizeof(DltStorageHeader));
2196     msg->standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1 ;
2197
2198 #if (BYTE_ORDER==BIG_ENDIAN)
2199     msg->standardheader->htyp = ( msg->standardheader->htyp | DLT_HTYP_MSBF);
2200 #endif
2201
2202     msg->standardheader->mcnt = 0;
2203
2204     /* Set header extra parameters */
2205     dlt_set_id(msg->headerextra.ecu,daemon->ecuid);
2206
2207     //msg->headerextra.seid = 0;
2208
2209     msg->headerextra.tmsp = dlt_uptime();
2210
2211     dlt_message_set_extraparameters(msg, verbose);
2212
2213     /* prepare extended header */
2214     msg->extendedheader = (DltExtendedHeader*)(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp));
2215     msg->extendedheader->msin = DLT_MSIN_CONTROL_RESPONSE;
2216
2217     msg->extendedheader->noar = 1; /* number of arguments */
2218     if (strcmp(appid,"")==0)
2219     {
2220         dlt_set_id(msg->extendedheader->apid,DLT_DAEMON_CTRL_APID);       /* application id */
2221     }
2222     else
2223     {
2224         dlt_set_id(msg->extendedheader->apid, appid);
2225     }
2226     if (strcmp(ctid,"")==0)
2227     {
2228         dlt_set_id(msg->extendedheader->ctid,DLT_DAEMON_CTRL_CTID);       /* context id */
2229     }
2230     else
2231     {
2232         dlt_set_id(msg->extendedheader->ctid, ctid);
2233     }
2234
2235     /* prepare length information */
2236     msg->headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp);
2237
2238     len=msg->headersize - sizeof(DltStorageHeader) + msg->datasize;
2239     if (len>UINT16_MAX)
2240     {
2241         dlt_log(LOG_CRIT,"Huge control message discarded!\n");
2242         return;
2243     }
2244
2245     msg->standardheader->len = DLT_HTOBE_16(((uint16_t)len));
2246
2247     if (sock!=DLT_DAEMON_STORE_TO_BUFFER)
2248     {
2249         /* Send message */
2250         if (isatty(sock))
2251         {
2252             DLT_DAEMON_SEM_LOCK();
2253
2254             /* Optional: Send serial header, if requested */
2255             if (daemon->sendserialheader)
2256             {
2257                 ret=write(sock,dltSerialHeader,sizeof(dltSerialHeader));
2258                 if (0 > ret)
2259                 {
2260                         dlt_log(LOG_CRIT,"dlt_daemon_control_send_control_message: write dltSerialHeader failed\n");
2261                         DLT_DAEMON_SEM_FREE();
2262                         return;
2263                 }
2264             }
2265
2266             /* Send data */
2267             ret=write(sock, msg->headerbuffer+sizeof(DltStorageHeader),msg->headersize-sizeof(DltStorageHeader));
2268             if (0 > ret)
2269             {
2270                     dlt_log(LOG_CRIT,"dlt_daemon_control_send_control_message: write msg->headerbuffer failed\n");
2271                     DLT_DAEMON_SEM_FREE();
2272                     return;
2273             }
2274             ret=write(sock, msg->databuffer,msg->datasize);
2275             if (0 > ret)
2276             {
2277                     dlt_log(LOG_CRIT,"dlt_daemon_control_send_control_message: write msg->databuffer failed\n");
2278                     DLT_DAEMON_SEM_FREE();
2279                     return;
2280             }
2281
2282             DLT_DAEMON_SEM_FREE();
2283         }
2284         else
2285         {
2286             DLT_DAEMON_SEM_LOCK();
2287
2288             /* Optional: Send serial header, if requested */
2289             if (daemon->sendserialheader)
2290             {
2291                 if (0 > send(sock, dltSerialHeader,sizeof(dltSerialHeader),0))
2292                     dlt_log(LOG_WARNING,"dlt_daemon_control_send_control_message: send serialheader failed\n");
2293
2294             }
2295
2296             /* Send data */
2297
2298             if ( 0 > send(sock, msg->headerbuffer+sizeof(DltStorageHeader),msg->headersize-sizeof(DltStorageHeader),0))
2299                 dlt_log(LOG_WARNING,"dlt_daemon_control_send_control_message: send DltStorageHeader failed\n");
2300
2301             if ( 0 > send(sock, msg->databuffer,msg->datasize,0))
2302                 dlt_log(LOG_WARNING,"dlt_daemon_control_send_control_message: send databuffer failed\n");
2303
2304             DLT_DAEMON_SEM_FREE();
2305         }
2306     }
2307     else
2308     {
2309         DLT_DAEMON_SEM_LOCK();
2310         /* Store message in history buffer */
2311         if (dlt_buffer_push3(&(daemon->client_ringbuffer),
2312                             msg->headerbuffer+sizeof(DltStorageHeader),msg->headersize-sizeof(DltStorageHeader),
2313                             msg->databuffer,msg->datasize,
2314                             0, 0
2315                            )<0)
2316                 {
2317                 DLT_DAEMON_SEM_FREE();
2318                         dlt_log(LOG_ERR,"Storage of message in history buffer failed! Message discarded.\n");
2319                         return;
2320                 }
2321         DLT_DAEMON_SEM_FREE();
2322     }
2323 }
2324
2325 void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon,const char *filename, const char *filename1, int verbose)
2326 {
2327     FILE *fd;
2328
2329     PRINT_FUNCTION_VERBOSE(verbose);
2330
2331     if ((daemon==0) || (filename==0) || (filename1==0) || (filename[0]=='\0') || (filename1[0]=='\0'))
2332     {
2333         return;
2334     }
2335
2336     /* Check for runtime cfg file and delete it, if available */
2337     fd=fopen(filename, "r");
2338
2339     if (fd!=0)
2340     {
2341         /* Close and delete file */
2342         fclose(fd);
2343         unlink(filename);
2344     }
2345
2346     fd=fopen(filename1, "r");
2347
2348     if (fd!=0)
2349     {
2350         /* Close and delete file */
2351         fclose(fd);
2352         unlink(filename1);
2353     }
2354
2355     daemon->default_log_level = DLT_DAEMON_INITIAL_LOG_LEVEL ;
2356     daemon->default_trace_status = DLT_DAEMON_INITIAL_TRACE_STATUS ;
2357
2358     daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_NO_OVERFLOW;
2359
2360     /* Reset all other things (log level, trace status, etc.
2361                                                    to default values             */
2362
2363     /* Inform user libraries about changed default log level/trace status */
2364     dlt_daemon_user_send_default_update(daemon, verbose);
2365 }
2366
2367 void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose)
2368 {
2369     int32_t count;
2370     DltDaemonContext *context;
2371
2372     PRINT_FUNCTION_VERBOSE(verbose);
2373
2374     if (daemon==0)
2375     {
2376         return;
2377     }
2378
2379     for (count=0;count<daemon->num_contexts; count ++)
2380     {
2381         context = &(daemon->contexts[count]);
2382
2383         if (context)
2384         {
2385             if ((context->log_level == DLT_LOG_DEFAULT) ||
2386                     (context->trace_status == DLT_TRACE_STATUS_DEFAULT))
2387             {
2388                 if (context->user_handle >= DLT_FD_MINIMUM)
2389                 {
2390                     if (dlt_daemon_user_send_log_level(daemon, context, verbose)==-1)
2391                     {
2392                         return;
2393                     }
2394                 }
2395             }
2396         }
2397     }
2398 }
2399
2400 void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose)
2401 {
2402     int32_t count;
2403     DltDaemonApplication *app;
2404
2405     PRINT_FUNCTION_VERBOSE(verbose);
2406
2407     if (daemon==0)
2408     {
2409         return;
2410     }
2411
2412     for (count=0;count<daemon->num_applications; count ++)
2413     {
2414         app = &(daemon->applications[count]);
2415
2416         if (app)
2417         {
2418                         if (app->user_handle >= DLT_FD_MINIMUM)
2419                         {
2420                                 if (dlt_daemon_user_send_log_state(daemon, app, verbose)==-1)
2421                                 {
2422                                         return;
2423                                 }
2424                         }
2425         }
2426     }
2427 }
2428
2429 void dlt_daemon_control_message_time(int sock, DltDaemon *daemon, int verbose)
2430 {
2431     DltMessage msg;
2432     ssize_t ret;
2433     int32_t len;
2434
2435     PRINT_FUNCTION_VERBOSE(verbose);
2436
2437     if (daemon==0)
2438     {
2439         return;
2440     }
2441
2442     if (sock==DLT_DAEMON_STORE_TO_BUFFER)
2443     {
2444         return;
2445     }
2446
2447     /* initialise new message */
2448     if (dlt_message_init(&msg,0)==-1)
2449     {
2450         return;
2451     }
2452
2453     /* send message */
2454
2455     /* prepare storage header */
2456     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2457     dlt_set_storageheader(msg.storageheader,daemon->ecuid);
2458
2459     /* prepare standard header */
2460     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2461     msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1 ;
2462
2463 #if (BYTE_ORDER==BIG_ENDIAN)
2464     msg.standardheader->htyp = ( msg.standardheader->htyp | DLT_HTYP_MSBF);
2465 #endif
2466
2467     msg.standardheader->mcnt = 0;
2468
2469     /* Set header extra parameters */
2470     dlt_set_id(msg.headerextra.ecu,daemon->ecuid);
2471     msg.headerextra.tmsp = dlt_uptime();
2472
2473     dlt_message_set_extraparameters(&msg, verbose);
2474
2475     /* prepare extended header */
2476     msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
2477     msg.extendedheader->msin = DLT_MSIN_CONTROL_TIME;
2478
2479     msg.extendedheader->noar = 0;                  /* number of arguments */
2480     dlt_set_id(msg.extendedheader->apid,"");       /* application id */
2481     dlt_set_id(msg.extendedheader->ctid,"");       /* context id */
2482
2483     /* prepare length information */
2484     msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2485
2486     len=msg.headersize - sizeof(DltStorageHeader) + msg.datasize;
2487     if (len>UINT16_MAX)
2488     {
2489         dlt_log(LOG_CRIT,"Huge control message discarded!\n");
2490
2491         /* free message */
2492         dlt_message_free(&msg,0);
2493
2494         return;
2495     }
2496
2497     msg.standardheader->len = DLT_HTOBE_16(((uint16_t)len));
2498
2499     /* Send message */
2500     if (isatty(sock))
2501     {
2502         DLT_DAEMON_SEM_LOCK();
2503
2504         /* Optional: Send serial header, if requested */
2505         if (daemon->sendserialheader)
2506         {
2507             ret=write(sock,dltSerialHeader,sizeof(dltSerialHeader));
2508         }
2509
2510         /* Send data */
2511         ret=write(sock, msg.headerbuffer+sizeof(DltStorageHeader),msg.headersize-sizeof(DltStorageHeader));
2512         if(msg.datasize > 0)
2513         {
2514                 ret=write(sock, msg.databuffer,msg.datasize);
2515                 if (0 > ret){
2516                         dlt_log(LOG_CRIT,"dlt_daemon_control_message_time: Failed to write databuffer\n");
2517                         dlt_message_free(&msg,0);
2518                         DLT_DAEMON_SEM_FREE();
2519                         return;
2520                 }
2521         }
2522
2523         DLT_DAEMON_SEM_FREE();
2524     }
2525     else
2526     {
2527         DLT_DAEMON_SEM_LOCK();
2528
2529         /* Optional: Send serial header, if requested */
2530         if (daemon->sendserialheader)
2531         {
2532             if ( -1 == send(sock, dltSerialHeader,sizeof(dltSerialHeader),0) )
2533                 dlt_log(LOG_ERR,"dlt_daemon_control_message_time: Failed to send dltSerialHeader");
2534
2535         }
2536
2537         /* Send data */
2538         if (-1 == send(sock, msg.headerbuffer+sizeof(DltStorageHeader),msg.headersize-sizeof(DltStorageHeader),0))
2539             dlt_log(LOG_ERR,"dlt_daemon_control_message_time: Failed to send DltStorageHeader");
2540
2541         if(msg.datasize > 0)
2542         {
2543             if (-1 == send(sock, msg.databuffer,msg.datasize,0) )
2544                 dlt_log(LOG_ERR,"dlt_daemon_control_message_time: Failed to send databuffer");
2545         }
2546
2547         DLT_DAEMON_SEM_FREE();
2548     }
2549
2550     /* free message */
2551     dlt_message_free(&msg,0);
2552 }