78d232ffb88ecaafa851c8dcd65620c15a53a79d
[profile/ivi/dlt-daemon.git] / src / daemon / dlt-daemon.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.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23 /*******************************************************************************
24 **                                                                            **
25 **  SRC-MODULE: dlt-daemon.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 <netdb.h>
67 #include <ctype.h>
68 #include <stdio.h>      /* for printf() and fprintf() */
69 #include <sys/socket.h> /* for socket(), connect(), (), and recv() */
70 #include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
71 #include <stdlib.h>     /* for atoi() and exit() */
72 #include <string.h>     /* for memset() */
73 #include <unistd.h>     /* for close() */
74 #include <fcntl.h>
75 #include <signal.h>
76 #include <syslog.h>
77 #include <errno.h>
78 #include <pthread.h>
79
80 #include <sys/timerfd.h>
81 #include <sys/stat.h>
82 #include <sys/time.h>
83 #include <linux/stat.h>
84
85 #include "dlt_types.h"
86 #include "dlt-daemon.h"
87 #include "dlt-daemon_cfg.h"
88
89 #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE)
90 #include "sd-daemon.h"
91 #endif
92
93 /**
94   \defgroup daemon DLT Daemon
95   \addtogroup daemon
96   \{
97 */
98
99 /** Global text output buffer, mainly used for creation of error/warning strings */
100 static char str[DLT_DAEMON_TEXTBUFSIZE];
101
102 /**
103  * Print usage information of tool.
104  */
105 void usage()
106 {
107         char version[DLT_DAEMON_TEXTBUFSIZE];
108         dlt_get_version(version);
109
110     //printf("DLT logging daemon %s %s\n", _DLT_PACKAGE_VERSION, _DLT_PACKAGE_VERSION_STATE);
111     //printf("Compile options: %s %s %s %s",_DLT_SYSTEMD_ENABLE, _DLT_SYSTEMD_WATCHDOG_ENABLE, _DLT_TEST_ENABLE, _DLT_SHM_ENABLE);
112     printf("%s", version);
113     printf("Usage: dlt-daemon [options]\n");
114     printf("Options:\n");
115     printf("  -d            Daemonize\n");
116     printf("  -h            Usage\n");
117     printf("  -c filename   DLT daemon configuration file (Default: /etc/dlt.conf)\n");
118 } /* usage() */
119
120 /**
121  * Option handling
122  */
123 int option_handling(DltDaemonLocal *daemon_local,int argc, char* argv[])
124  {
125         int c;
126
127         if (daemon_local==0)
128         {
129                 fprintf (stderr, "Invalid parameter passed to option_handling()\n");
130                 return -1;
131         }
132
133     /* Initialize flags */
134     memset(daemon_local,0,sizeof(DltDaemonLocal));
135
136     opterr = 0;
137
138     while ((c = getopt (argc, argv, "hdc:")) != -1)
139     {
140         switch (c)
141         {
142         case 'd':
143         {
144             daemon_local->flags.dflag = 1;
145             break;
146         }
147         case 'c':
148         {
149             strncpy(daemon_local->flags.cvalue,optarg,NAME_MAX);
150             break;
151         }
152         case 'h':
153         {
154             usage();
155             return -2; /* return no error */
156         }
157         case '?':
158         {
159             if (optopt == 'c')
160             {
161                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
162             }
163             else if (isprint (optopt))
164             {
165                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
166             }
167             else
168             {
169                 fprintf (stderr, "Unknown option character `\\x%x'.\n",optopt);
170             }
171             /* unknown or wrong option used, show usage information and terminate */
172             usage();
173             return -1;
174         }
175         default:
176         {
177                 fprintf (stderr, "Invalid option, this should never occur!\n");
178             return -1;
179         }
180         } /* switch() */
181     }
182
183     return 0;
184
185  } /* option_handling() */
186
187 /**
188  * Option file parser
189  */
190 int option_file_parser(DltDaemonLocal *daemon_local)
191 {
192         FILE * pFile;
193         int value_length = 1024;
194         char line[value_length-1];
195         char token[value_length];
196         char value[value_length];
197     char *pch;
198     const char *filename;
199
200         /* set default values for configuration */
201         daemon_local->flags.sharedMemorySize = DLT_SHM_SIZE;
202         daemon_local->flags.sendMessageTime = 0;
203         daemon_local->flags.offlineTraceDirectory[0] = 0;
204         daemon_local->flags.offlineTraceFileSize = 1000000;
205         daemon_local->flags.offlineTraceMaxSize = 0;
206         daemon_local->flags.loggingMode = 0;
207         daemon_local->flags.loggingLevel = 6;
208         strncpy(daemon_local->flags.loggingFilename, DLT_USER_DIR "/dlt.log",sizeof(daemon_local->flags.loggingFilename));
209         daemon_local->timeoutOnSend = 4;
210         daemon_local->flags.sendECUSoftwareVersion = 0;
211         memset(daemon_local->flags.pathToECUSoftwareVersion, 0, sizeof(daemon_local->flags.pathToECUSoftwareVersion));
212         daemon_local->flags.sendTimezone = 0;
213
214         /* open configuration file */
215         if(daemon_local->flags.cvalue[0])
216                 filename = daemon_local->flags.cvalue;
217         else
218                 filename = "/etc/dlt.conf";
219     //printf("Load configuration from file: %s\n",filename);
220         pFile = fopen (filename,"r");
221
222         if (pFile!=NULL)
223         {
224                 while(1)
225                 {
226                         /* fetch line from configuration file */
227                         if ( fgets (line , value_length - 1 , pFile) != NULL )
228                         {
229                                   pch = strtok (line," =\r\n");
230                                   token[0]=0;
231                                   value[0]=0;
232                                   
233                                   while (pch != NULL)
234                                   {
235                                         if(strcmp(pch,"#")==0)
236                                                 break;
237
238                                         if(token[0]==0)
239                                         {
240                                                 strncpy(token,pch,sizeof(token) - 1);
241                                         }
242                                         else
243                                         {
244                                                 strncpy(value,pch,sizeof(value) - 1);
245                                                 break;
246                                         }
247
248                                         pch = strtok (NULL, " =\r\n");
249                                   }
250                                   
251                                   if(token[0] && value[0])
252                                   {
253                                                 /* parse arguments here */
254                                                 if(strcmp(token,"Verbose")==0)
255                                                 {
256                                                         daemon_local->flags.vflag = atoi(value);
257                                                         //printf("Option: %s=%s\n",token,value);
258                                                 }
259                                                 else if(strcmp(token,"PrintASCII")==0)
260                                                 {
261                                                         daemon_local->flags.aflag = atoi(value);
262                                                         //printf("Option: %s=%s\n",token,value);
263                                                 }
264                                                 else if(strcmp(token,"PrintHex")==0)
265                                                 {
266                                                         daemon_local->flags.xflag = atoi(value);
267                                                         //printf("Option: %s=%s\n",token,value);
268                                                 }
269                                                 else if(strcmp(token,"PrintHeadersOnly")==0)
270                                                 {
271                                                         daemon_local->flags.sflag = atoi(value);
272                                                         //printf("Option: %s=%s\n",token,value);
273                                                 }
274                                                 else if(strcmp(token,"SendSerialHeader")==0)
275                                                 {
276                                                         daemon_local->flags.lflag = atoi(value);
277                                                         //printf("Option: %s=%s\n",token,value);
278                                                 }
279                                                 else if(strcmp(token,"SendContextRegistration")==0)
280                                                 {
281                                                         daemon_local->flags.rflag = atoi(value);
282                                                         //printf("Option: %s=%s\n",token,value);
283                                                 }
284                                                 else if(strcmp(token,"SendMessageTime")==0)
285                                                 {
286                                                         daemon_local->flags.sendMessageTime = atoi(value);
287                                                         //printf("Option: %s=%s\n",token,value);
288                                                 }
289                                                 else if(strcmp(token,"RS232SyncSerialHeader")==0)
290                                                 {
291                                                         daemon_local->flags.mflag = atoi(value);
292                                                         //printf("Option: %s=%s\n",token,value);
293                                                 }
294                                                 else if(strcmp(token,"TCPSyncSerialHeader")==0)
295                                                 {
296                                                         daemon_local->flags.nflag = atoi(value);
297                                                         //printf("Option: %s=%s\n",token,value);
298                                                 }
299                                                 else if(strcmp(token,"RS232DeviceName")==0)
300                                                 {
301                                                         strncpy(daemon_local->flags.yvalue,value,NAME_MAX);
302                                                         //printf("Option: %s=%s\n",token,value);
303                                                 }
304                                                 else if(strcmp(token,"RS232Baudrate")==0)
305                                                 {
306                                                         strncpy(daemon_local->flags.bvalue,value,NAME_MAX);
307                                                         //printf("Option: %s=%s\n",token,value);
308                                                 }
309                                                 else if(strcmp(token,"ECUId")==0)
310                                                 {
311                                                         strncpy(daemon_local->flags.evalue,value,NAME_MAX);
312                                                         //printf("Option: %s=%s\n",token,value);
313                                                 }
314                                                 else if(strcmp(token,"PersistanceStoragePath")==0)
315                                                 {
316                                                         strncpy(daemon_local->flags.ivalue,value,NAME_MAX);
317                                                         //printf("Option: %s=%s\n",token,value);
318                                                 }
319                                                 else if(strcmp(token,"LoggingMode")==0)
320                                                 {
321                                                         daemon_local->flags.loggingMode = atoi(value);
322                                                         //printf("Option: %s=%s\n",token,value);
323                                                 }
324                                                 else if(strcmp(token,"LoggingLevel")==0)
325                                                 {
326                                                         daemon_local->flags.loggingLevel = atoi(value);
327                                                         //printf("Option: %s=%s\n",token,value);
328                                                 }
329                                                 else if(strcmp(token,"LoggingFilename")==0)
330                                                 {
331                                                         strncpy(daemon_local->flags.loggingFilename,value,sizeof(daemon_local->flags.loggingFilename) - 1);
332                                                         //printf("Option: %s=%s\n",token,value);
333                                                 }
334                         else if(strcmp(token,"TimeOutOnSend")==0)
335                                                 {
336                                                         daemon_local->timeoutOnSend = atoi(value);
337                                                         //printf("Option: %s=%s\n",token,value);
338                                                 }
339                                                 else if(strcmp(token,"SharedMemorySize")==0)
340                                                 {
341                                                         daemon_local->flags.sharedMemorySize = atoi(value);
342                                                         //printf("Option: %s=%s\n",token,value);
343                                                 }
344                                                 else if(strcmp(token,"OfflineTraceDirectory")==0)
345                                                 {
346                                                         strncpy(daemon_local->flags.offlineTraceDirectory,value,sizeof(daemon_local->flags.offlineTraceDirectory) - 1);
347                                                         //printf("Option: %s=%s\n",token,value);
348                                                 }
349                                                 else if(strcmp(token,"OfflineTraceFileSize")==0)
350                                                 {
351                                                         daemon_local->flags.offlineTraceFileSize = atoi(value);
352                                                         //printf("Option: %s=%s\n",token,value);
353                                                 }
354                                                 else if(strcmp(token,"OfflineTraceMaxSize")==0)
355                                                 {
356                                                         daemon_local->flags.offlineTraceMaxSize = atoi(value);
357                                                         //printf("Option: %s=%s\n",token,value);
358                                                 }
359                                                 else if(strcmp(token,"SendECUSoftwareVersion")==0)
360                                                 {
361                                                         daemon_local->flags.sendECUSoftwareVersion = atoi(value);
362                                                         //printf("Option: %s=%s\n",token,value);
363                                                 }
364                                                 else if(strcmp(token,"PathToECUSoftwareVersion")==0)
365                                                 {
366                                                         strncpy(daemon_local->flags.pathToECUSoftwareVersion,value,sizeof(daemon_local->flags.pathToECUSoftwareVersion) - 1);
367                                                         //printf("Option: %s=%s\n",token,value);
368                                                 }
369                                                 else if(strcmp(token,"SendTimezone")==0)
370                                                 {
371                                                         daemon_local->flags.sendTimezone = atoi(value);
372                                                         //printf("Option: %s=%s\n",token,value);
373                                                 }
374                                                 else
375                                                 {
376                                                         fprintf(stderr, "Unknown option: %s=%s\n",token,value);
377                                                 }
378                                         }
379                         }
380                         else
381                         {
382                                 break;
383                         }
384                 }
385                 fclose (pFile);
386         }
387         else
388         {
389                 fprintf(stderr, "Cannot open configuration file: %s\n",filename);
390         }       
391
392         return 0;
393 }
394
395 /**
396  * Main function of tool.
397  */
398 int main(int argc, char* argv[])
399 {
400         char version[DLT_DAEMON_TEXTBUFSIZE];
401     DltDaemonLocal daemon_local;
402     DltDaemon daemon;
403     int i,back;
404
405     /* Command line option handling */
406         if ((back = option_handling(&daemon_local,argc,argv))<0)
407         {
408                 if(back!=-2) {
409                         fprintf (stderr, "option_handling() failed!\n");
410                 }
411                 return -1;
412         }
413
414     /* Configuration file option handling */
415         if ((back = option_file_parser(&daemon_local))<0)
416         {
417                 if(back!=-2) {
418                         fprintf (stderr, "option_file_parser() failed!\n");
419                 }
420                 return -1;
421         }
422         
423     /* Initialize internal logging facility */
424     dlt_log_set_filename(daemon_local.flags.loggingFilename);
425     dlt_log_set_level(daemon_local.flags.loggingLevel);
426     dlt_log_init(daemon_local.flags.loggingMode);
427
428     /* Print version information */
429     dlt_get_version(version);
430
431     sprintf(str,"Starting DLT Daemon; %s\n", version );
432     dlt_log(LOG_NOTICE, str);
433
434         PRINT_FUNCTION_VERBOSE(daemon_local.flags.vflag);
435
436     /* --- Daemon init phase 1 begin --- */
437     if (dlt_daemon_local_init_p1(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
438     {
439         dlt_log(LOG_CRIT,"Initialization of phase 1 failed!\n");
440         return -1;
441     }
442     /* --- Daemon init phase 1 end --- */
443
444     /* --- Daemon connection init begin */
445     if (dlt_daemon_local_connection_init(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
446     {
447         dlt_log(LOG_CRIT,"Initialization of local connections failed!\n");
448         return -1;
449     }
450     /* --- Daemon connection init end */
451
452     /* --- Daemon init phase 2 begin --- */
453     if (dlt_daemon_local_init_p2(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
454     {
455         dlt_log(LOG_CRIT,"Initialization of phase 2 failed!\n");
456         return -1;
457     }
458     /* --- Daemon init phase 2 end --- */
459
460     // create fd for watchdog
461 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
462     {
463         char* watchdogUSec = getenv("WATCHDOG_USEC");
464         int watchdogTimeoutSeconds = 0;
465
466         dlt_log(LOG_DEBUG, "Systemd watchdog initialization\n");
467         if( watchdogUSec )
468         {
469             watchdogTimeoutSeconds = atoi(watchdogUSec)/2000000;
470         }
471         create_timer_fd(&daemon_local, watchdogTimeoutSeconds, watchdogTimeoutSeconds, &daemon_local.timer_wd, "Systemd watchdog");
472     }
473 #endif
474
475     // create fd for timer timing packets
476     create_timer_fd(&daemon_local, 1, 1, &daemon_local.timer_timingpacket, "Timing packet");
477
478     // create fd for timer ecu version
479     if(daemon_local.flags.sendECUSoftwareVersion > 0 || daemon_local.flags.sendTimezone > 0)
480     {
481         //dlt_daemon_init_ecuversion(&daemon_local);
482         create_timer_fd(&daemon_local, 60, 60, &daemon_local.timer_ecuversion, "ECU version");
483     }
484
485     while (1)
486     {
487
488         /* wait for events from all FIFO and sockets */
489         daemon_local.read_fds = daemon_local.master;
490         if (select(daemon_local.fdmax+1, &(daemon_local.read_fds), NULL, NULL, NULL) == -1)
491         {
492             dlt_log(LOG_CRIT, "select() failed!\n");
493             return -1 ;
494         } /* if */
495
496         /* run through the existing FIFO and sockets to check for events */
497         for (i = 0; i <= daemon_local.fdmax; i++)
498         {
499             if (FD_ISSET(i, &(daemon_local.read_fds)))
500             {
501                 if (i == daemon_local.sock && ((daemon.mode == DLT_USER_MODE_EXTERNAL) || (daemon.mode == DLT_USER_MODE_BOTH)))
502                 {
503                     /* event from TCP server socket, new connection */
504                     if (dlt_daemon_process_client_connect(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
505                     {
506                         dlt_log(LOG_CRIT,"Connect to dlt client failed!\n");
507                         return -1;
508                     }
509                 }
510                 else if (i == daemon_local.fp)
511                 {
512                     /* event from the FIFO happened */
513                     if (dlt_daemon_process_user_messages(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
514                     {
515                         dlt_log(LOG_CRIT,"Processing of messages from user connection failed!\n");
516                         return -1;
517                     }
518                 }
519                 else if ((i == daemon_local.fdserial) && (daemon_local.flags.yvalue[0]))
520                 {
521                     /* event from serial connection to client received */
522                     if (dlt_daemon_process_client_messages_serial(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
523                     {
524                         dlt_log(LOG_CRIT,"Processing of messages from serial connection failed!\n");
525                         return -1;
526                     }
527                 }
528 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
529                 else if (i == daemon_local.timer_wd)
530                 {
531                     uint64_t expir=0;
532                     ssize_t res = read(daemon_local.timer_wd, &expir, sizeof(expir));
533                     if(res < 0) {
534                         sprintf(str,"Failed to read timer_wd; %s\n", strerror(errno) );
535                         dlt_log(LOG_WARNING, str);
536                         // Activity received on timer_wd, but unable to read the fd:
537                         // let's go on sending notification
538                     }
539
540                     dlt_log(LOG_DEBUG, "Timer watchdog\n");
541
542                     if(sd_notify(0, "WATCHDOG=1") < 0)
543                     {
544                         dlt_log(LOG_CRIT, "Could not reset systemd watchdog\n");
545                     }
546                 }
547 #endif
548                 else if (i == daemon_local.timer_timingpacket)
549                 {
550                     uint64_t expir=0;
551                     ssize_t res = read(daemon_local.timer_timingpacket, &expir, sizeof(expir));
552                     if(res < 0) {
553                         sprintf(str,"Failed to read timer_timingpacket; %s\n", strerror(errno) );
554                         dlt_log(LOG_WARNING, str);
555                         // Activity received on timer_wd, but unable to read the fd:
556                         // let's go on sending notification
557                     }
558                     dlt_daemon_send_timingpacket(&daemon, &daemon_local);
559                     dlt_log(LOG_DEBUG, "Timer timingpacket\n");
560
561                  }
562
563                 else if (i == daemon_local.timer_ecuversion)
564                 {
565                     uint64_t expir=0;
566                     ssize_t res = read(daemon_local.timer_ecuversion, &expir, sizeof(expir));
567                     if(res < 0) {
568                         sprintf(str,"Failed to read timer_ecuversion; %s\n", strerror(errno) );
569                         dlt_log(LOG_WARNING, str);
570                         // Activity received on timer_wd, but unable to read the fd:
571                         // let's go on sending notification
572                     }
573                     dlt_daemon_send_ecuversion(&daemon, &daemon_local);
574                     dlt_log(LOG_DEBUG, "Timer ecuversion\n");
575
576                 }
577                 else
578                 {
579                     /* event from tcp connection to client received */
580                     daemon_local.receiverSock.fd = i;
581                     if (dlt_daemon_process_client_messages(&daemon, &daemon_local, daemon_local.flags.vflag)==-1)
582                     {
583                         dlt_log(LOG_CRIT,"Processing of messages from client connection failed!\n");
584                                                 return -1;
585                     }
586                 } /* else */
587             } /* if */
588         } /* for */
589     } /* while */
590
591     dlt_daemon_local_cleanup(&daemon, &daemon_local, daemon_local.flags.vflag);
592
593     dlt_log(LOG_NOTICE, "Leaving DLT daemon\n");
594
595     return 0;
596
597 } /* main() */
598
599 int dlt_daemon_local_init_p1(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
600 {
601 #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE)
602         int ret;
603 #endif
604
605
606     PRINT_FUNCTION_VERBOSE(verbose);
607
608     if ((daemon==0)  || (daemon_local==0))
609     {
610         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p1()\n");
611         return -1;
612     }
613
614 #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE)
615     ret = sd_booted();
616
617     if(ret == 0){
618         dlt_log(LOG_CRIT, "system not booted with systemd!\n");
619 //      return -1;
620     }
621     else if(ret < 0)
622     {
623         dlt_log(LOG_CRIT, "sd_booted failed!\n");
624         return -1;
625     }
626     else
627     {
628         dlt_log(LOG_INFO, "system booted with systemd\n");
629     }
630 #endif
631
632
633
634     /* Check for daemon mode */
635     if (daemon_local->flags.dflag)
636     {
637         dlt_daemon_daemonize(daemon_local->flags.vflag);
638     }
639
640     /* initialise structure to use DLT file */
641     if (dlt_file_init(&(daemon_local->file),daemon_local->flags.vflag)==-1)
642     {
643                 dlt_log(LOG_ERR,"Could not initialize file structure\n");
644                 /* Return value ignored, dlt daemon will exit */
645                 dlt_file_free(&(daemon_local->file),daemon_local->flags.vflag);
646                 return -1;
647     }
648
649     signal(SIGPIPE,SIG_IGN);
650
651     signal(SIGTERM, dlt_daemon_signal_handler); /* software termination signal from kill */
652     signal(SIGHUP,  dlt_daemon_signal_handler); /* hangup signal */
653     signal(SIGQUIT, dlt_daemon_signal_handler);
654     signal(SIGINT,  dlt_daemon_signal_handler);
655         
656     return 0;
657 }
658
659 int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
660 {
661     PRINT_FUNCTION_VERBOSE(verbose);
662
663     if ((daemon==0)  || (daemon_local==0))
664     {
665         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p2()\n");
666         return -1;
667     }
668
669     /* Daemon data */
670     if (dlt_daemon_init(daemon,daemon_local->flags.ivalue,daemon_local->flags.vflag)==-1)
671     {
672         dlt_log(LOG_ERR,"Could not initialize daemon data\n");
673                 return -1;
674     }
675
676         /* init offline trace */
677         if(((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) && daemon_local->flags.offlineTraceDirectory[0])
678         {
679                 if (dlt_offline_trace_init(&(daemon_local->offlineTrace),daemon_local->flags.offlineTraceDirectory,daemon_local->flags.offlineTraceFileSize,daemon_local->flags.offlineTraceMaxSize)==-1)
680                 {
681                         dlt_log(LOG_ERR,"Could not initialize offline trace\n");
682                         return -1;
683                 }
684         }
685
686     /* Set ECU id of daemon */
687     if (daemon_local->flags.evalue[0])
688     {
689         dlt_set_id(daemon->ecuid,daemon_local->flags.evalue);
690     }
691     else
692     {
693         dlt_set_id(daemon->ecuid,DLT_DAEMON_ECU_ID);
694     }
695
696     /* Set flag for optional sending of serial header */
697     daemon->sendserialheader = daemon_local->flags.lflag;
698
699 #ifdef DLT_SHM_ENABLE
700         /* init shared memory */
701     if (dlt_shm_init_server(&(daemon_local->dlt_shm),DLT_SHM_KEY,daemon_local->flags.sharedMemorySize)==-1)
702     {
703         dlt_log(LOG_ERR,"Could not initialize shared memory\n");
704                 return -1;
705     }
706 #endif
707         
708     /* prepare main loop */
709     if (dlt_message_init(&(daemon_local->msg),daemon_local->flags.vflag)==-1)
710     {
711         dlt_log(LOG_ERR,"Could not initialize message\n");
712                 return -1;
713     }
714
715     if (dlt_receiver_init(&(daemon_local->receiver),daemon_local->fp,DLT_DAEMON_RCVBUFSIZE)==-1)
716     {
717         dlt_log(LOG_ERR,"Could not initialize receiver\n");
718                 return -1;
719     }
720     if (dlt_receiver_init(&(daemon_local->receiverSock),daemon_local->sock,DLT_DAEMON_RCVBUFSIZESOCK)==-1)
721         {
722         dlt_log(LOG_ERR,"Could not initialize receiver for socket\n");
723                 return -1;
724     }
725     if (daemon_local->flags.yvalue[0])
726     {
727         if (dlt_receiver_init(&(daemon_local->receiverSerial),daemon_local->fdserial,DLT_DAEMON_RCVBUFSIZESERIAL)==-1)
728         {
729                         dlt_log(LOG_ERR,"Could not initialize receiver for serial connection\n");
730                         return -1;
731         }
732     }
733     
734     /* configure sending timing packets */
735     if (daemon_local->flags.sendMessageTime)    
736     {
737                 daemon->timingpackets = 1;
738         }
739         
740     /* Binary semaphore for thread */
741     if (sem_init(&dlt_daemon_mutex, 0, 1)==-1)
742     {
743         dlt_log(LOG_ERR,"Could not initialize binary semaphore\n");
744         return -1;
745     }
746
747     /* Get ECU version info from a file. If it fails, use dlt_version as fallback. */
748     if(dlt_daemon_local_ecu_version_init(daemon, daemon_local, daemon_local->flags.vflag) < 0)
749     {
750         daemon->ECUVersionString = malloc(DLT_DAEMON_TEXTBUFSIZE);
751         dlt_get_version(daemon->ECUVersionString);
752     }
753
754     return 0;
755 }
756
757 int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
758 {
759     int ret;
760     int yes = 1;
761
762     struct sockaddr_in servAddr;
763     unsigned int servPort = DLT_DAEMON_TCP_PORT;
764
765     PRINT_FUNCTION_VERBOSE(verbose);
766
767     if ((daemon==0)  || (daemon_local==0))
768     {
769         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_connection_init()\n");
770         return -1;
771     }
772
773     /* open named pipe(FIFO) to receive DLT messages from users */
774     umask(0);
775
776     ret=mkdir(DLT_USER_DIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH  | S_IWOTH | S_ISVTX );
777     if (ret==-1 && errno != EEXIST)
778     {
779         sprintf(str,"FIFO user dir %s cannot be created!\n", DLT_USER_DIR);
780         dlt_log(LOG_ERR, str);
781         return -1;
782     }
783
784     // S_ISGID cannot be set by mkdir, let's reassign right bits
785     ret=chmod(DLT_USER_DIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH  | S_IWOTH | S_IXOTH | S_ISGID | S_ISVTX );
786     if (ret==-1)
787     {
788         sprintf(str,"FIFO user dir %s cannot be chmoded!\n", DLT_USER_DIR);
789         dlt_log(LOG_ERR, str);
790         return -1;
791     }
792
793     /* Try to delete existing pipe, ignore result of unlink */
794     unlink(DLT_USER_FIFO);
795
796     ret=mkfifo(DLT_USER_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
797     if (ret==-1)
798     {
799         sprintf(str,"FIFO user %s cannot be created!\n",DLT_USER_FIFO);
800         dlt_log(LOG_ERR, str);
801         return -1;
802     } /* if */
803
804     daemon_local->fp = open(DLT_USER_FIFO, O_RDWR);
805     if (daemon_local->fp==-1)
806     {
807         sprintf(str,"FIFO user %s cannot be opened!\n",DLT_USER_FIFO);
808         dlt_log(LOG_ERR, str);
809         return -1;
810     } /* if */
811
812     /* create and open socket to receive incoming connections from client */
813     if ((daemon_local->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
814     {
815         dlt_log(LOG_ERR, "socket() failed!\n");
816         return -1;
817     } /* if */
818
819     if ( -1 == setsockopt(daemon_local->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)))
820     {
821         sprintf(str,"Setsockopt error in dlt_daemon_local_connection_init: %s\n",strerror(errno));
822         dlt_log(LOG_ERR, str);
823         return -1;
824     }
825     memset(&servAddr, 0, sizeof(servAddr));
826     servAddr.sin_family      = AF_INET;
827     servAddr.sin_addr.s_addr = INADDR_ANY;
828     servAddr.sin_port        = htons(servPort);
829
830     if (bind(daemon_local->sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
831     {
832         dlt_log(LOG_ERR, "bind() failed!\n");
833         return -1;
834     } /* if */
835
836     if (daemon_local->flags.vflag)
837     {
838         dlt_log(LOG_INFO, "Bind succesfull\n");
839     }
840
841     if (listen(daemon_local->sock, 3) < 0)
842     {
843         dlt_log(LOG_ERR, "listen() failed!\n");
844         return -1;
845     } /* if */
846
847     if (daemon_local->flags.vflag)
848     {
849         dlt_log(LOG_INFO, "Listen succesfull\n");
850     }
851
852     /* prepare usage of select(), add FIFO and receiving socket */
853     FD_ZERO(&(daemon_local->master));
854     FD_ZERO(&(daemon_local->read_fds));
855     FD_SET(daemon_local->sock, &(daemon_local->master));
856
857     daemon_local->fdmax = daemon_local->sock;
858
859     FD_SET(daemon_local->fp, &(daemon_local->master));
860
861     if (daemon_local->fp > daemon_local->fdmax)
862     {
863         daemon_local->fdmax = daemon_local->fp;
864     }
865
866     if (daemon_local->flags.yvalue[0])
867     {
868         /* create and open serial connection from/to client */
869         /* open serial connection */
870         daemon_local->fdserial=open(daemon_local->flags.yvalue,O_RDWR);
871         if (daemon_local->fdserial<0)
872         {
873             sprintf(str,"Failed to open serial device %s\n", daemon_local->flags.yvalue);
874             daemon_local->flags.yvalue[0] = 0;
875             dlt_log(LOG_ERR, str);
876             return -1;
877         }
878
879         if (isatty(daemon_local->fdserial))
880         {
881             if (daemon_local->flags.bvalue[0])
882             {
883                 daemon_local->baudrate = dlt_convert_serial_speed(atoi(daemon_local->flags.bvalue));
884             }
885             else
886             {
887                 daemon_local->baudrate = dlt_convert_serial_speed(DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE);
888             }
889
890             if (dlt_setup_serial(daemon_local->fdserial,daemon_local->baudrate)<0)
891             {
892                 close(daemon_local->fdserial);
893                 sprintf(str,"Failed to configure serial device %s (%s) \n", daemon_local->flags.yvalue, strerror(errno));
894                 daemon_local->flags.yvalue[0] = 0;
895                 dlt_log(LOG_ERR, str);
896                 return -1;
897             }
898
899             FD_SET(daemon_local->fdserial, &(daemon_local->master));
900
901             if (daemon_local->fdserial > daemon_local->fdmax)
902             {
903                 daemon_local->fdmax = daemon_local->fdserial;
904             }
905
906             if (daemon_local->flags.vflag)
907             {
908                 dlt_log(LOG_INFO, "Serial init done\n");
909             }
910         }
911         else
912         {
913             close(daemon_local->fdserial);
914             fprintf(stderr,"Device is not a serial device, device = %s (%s) \n", daemon_local->flags.yvalue, strerror(errno));
915             daemon_local->flags.yvalue[0] = 0;
916             return -1;
917         }
918     }
919
920     return 0;
921 }
922
923 int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
924 {
925         char *version   = NULL;
926         FILE *f                 = NULL;
927
928         PRINT_FUNCTION_VERBOSE(verbose);
929
930         /* By default, version string is null. */
931         daemon->ECUVersionString = NULL;
932
933         /* Open the file. Bail out if error occurs */
934         f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r");
935         if(f == NULL)
936         {
937                 /* Error level notice, because this might be deliberate choice */
938                 dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n");
939                 return -1;
940         }
941
942         /* Get the file size. Bail out if stat fails. */
943         int fd = fileno(f);
944         struct stat s_buf;
945         if(fstat(fd, &s_buf) < 0)
946         {
947                 dlt_log(LOG_ERR, "Failed to stat ECU Software version file.\n");
948                 fclose(f);
949                 return -1;
950         }
951
952         /* Bail out if file is too large. Use DLT_DAEMON_TEXTBUFSIZE max.
953          * Reserve one byte for trailing '\0' */
954         off_t size = s_buf.st_size;
955         if(size >= DLT_DAEMON_TEXTBUFSIZE)
956         {
957                 dlt_log(LOG_ERR, "Too large file for ECU version.\n");
958                 fclose(f);
959                 return -1;
960         }
961
962         /* Allocate permanent buffer for version info */
963         version = malloc(size + 1);
964         off_t offset = 0;
965         while(!feof(f))
966         {
967                 offset += fread(version + offset, 1, size, f);
968                 if(ferror(f))
969                 {
970                         dlt_log(LOG_ERR, "Failed to read ECU Software version file.\n");
971                         free(version);
972             fclose(f);
973                         return -1;
974                 }
975         if(offset > size)
976                 {
977                         dlt_log(LOG_ERR, "Too long file for ECU Software version info.\n");
978                         free(version);
979                         fclose(f);
980                         return -1;
981                 }
982         }
983         version[offset] = '\0';//append null termination at end of version string
984         daemon->ECUVersionString = version;
985         fclose(f);
986         return 0;
987 }
988
989 void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
990 {
991     PRINT_FUNCTION_VERBOSE(verbose);
992
993     if ((daemon==0)  || (daemon_local==0))
994     {
995                 dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_cleanup()\n");
996         return;
997     }
998
999         /* Ignore result */
1000     dlt_receiver_free(&(daemon_local->receiver));
1001     /* Ignore result */
1002     dlt_receiver_free(&(daemon_local->receiverSock));
1003
1004         /* Ignore result */
1005     dlt_message_free(&(daemon_local->msg),daemon_local->flags.vflag);
1006     close(daemon_local->fp);
1007
1008         /* free shared memory */
1009         if(daemon_local->flags.offlineTraceDirectory[0])
1010                 dlt_offline_trace_free(&(daemon_local->offlineTrace));
1011 #if 0
1012     if (daemon_local->flags.ovalue[0])
1013     {
1014         close(daemon_local->ohandle);
1015     } /* if */
1016 #endif
1017
1018         /* Ignore result */
1019     dlt_file_free(&(daemon_local->file),daemon_local->flags.vflag);
1020
1021     /* Try to delete existing pipe, ignore result of unlink() */
1022     unlink(DLT_USER_FIFO);
1023
1024 #ifdef DLT_SHM_ENABLE
1025         /* free shared memory */
1026         dlt_shm_free_server(&(daemon_local->dlt_shm));
1027 #endif
1028
1029     /* Try to delete lock file, ignore result of unlink() */
1030     unlink(DLT_DAEMON_LOCK_FILE);
1031 }
1032
1033 void dlt_daemon_signal_handler(int sig)
1034 {
1035     switch (sig)
1036     {
1037     case SIGHUP:
1038     case SIGTERM:
1039     case SIGINT:
1040     case SIGQUIT:
1041     {
1042         /* finalize the server */
1043         //dlt_log("terminate signal catched");
1044         dlt_log(LOG_NOTICE, "Exiting DLT daemon\n");
1045
1046         /* Try to delete existing pipe, ignore result of unlink() */
1047         unlink(DLT_USER_FIFO);
1048
1049         /* Try to delete lock file, ignore result of unlink() */
1050         unlink(DLT_DAEMON_LOCK_FILE);
1051
1052                 /* Terminate program */
1053         exit(0);
1054         break;
1055     }
1056     default:
1057     {
1058         /* This case should never occur */
1059         break;
1060     }
1061     } /* switch */
1062 } /* dlt_daemon_signal_handler() */
1063
1064 void dlt_daemon_daemonize(int verbose)
1065 {
1066     int i,lfp;
1067     ssize_t pid_len;
1068
1069     PRINT_FUNCTION_VERBOSE(verbose);
1070
1071     dlt_log(LOG_NOTICE, "Daemon mode\n");
1072
1073     /* Daemonize */
1074     i=fork();
1075     if (i<0)
1076     {
1077         dlt_log(LOG_CRIT, "Unable to fork(), exiting DLT daemon\n");
1078         exit(-1); /* fork error */
1079     }
1080
1081     if (i>0)
1082     {
1083         exit(0); /* parent exits */
1084     }
1085     /* child (daemon) continues */
1086
1087     /* Process independency */
1088
1089      /* obtain a new process group */
1090     if (setsid()==-1)
1091     {
1092         dlt_log(LOG_CRIT, "setsid() failed, exiting DLT daemon\n");
1093         exit(-1); /* fork error */
1094     }
1095
1096     /* Close descriptors */
1097     for (i=getdtablesize();i>=0;--i)
1098     {
1099         close(i); /* close all descriptors */
1100     }
1101
1102     /* Open standard descriptors stdin, stdout, stderr */
1103     i=open("/dev/null",O_RDWR); /* open stdin */
1104     if (-1 < i)
1105         {
1106         if(dup(i) < 0)
1107             dlt_log(LOG_ERR, "Failed to direct stdout to /dev/null.\n");/* stdout */
1108         if(dup(i) < 0)
1109             dlt_log(LOG_ERR, "Failed to direct stderr to /dev/null.\n"); /* stderr */
1110         }
1111
1112     /* Set umask */
1113     umask(DLT_DAEMON_UMASK);
1114
1115     /* Change to known directory */
1116     if(chdir(DLT_USER_DIR) < 0)
1117         dlt_log(LOG_ERR, "Failed to chdir to DLT_USER_DIR.\n");;
1118
1119     /* Ensure single copy of daemon;
1120        run only one instance at a time */
1121     lfp=open(DLT_DAEMON_LOCK_FILE,O_RDWR|O_CREAT,DLT_DAEMON_LOCK_FILE_PERM);
1122     if (lfp<0)
1123     {
1124         dlt_log(LOG_CRIT, "can't open lock file, exiting DLT daemon\n");
1125         exit(-1); /* can not open */
1126     }
1127     if (lockf(lfp,F_TLOCK,0)<0)
1128     {
1129         dlt_log(LOG_CRIT, "can't lock lock file, exiting DLT daemon\n");
1130         exit(-1); /* can not lock */
1131     }
1132     /* only first instance continues */
1133
1134     sprintf(str,"%d\n",getpid());
1135     pid_len = strlen(str);
1136     if(write(lfp,str,pid_len) != pid_len) /* record pid to lockfile */
1137         dlt_log(LOG_ERR, "Could not write pid to file in dlt_daemon_daemonize.\n");
1138
1139     /* Catch signals */
1140     signal(SIGCHLD,SIG_IGN); /* ignore child */
1141     signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
1142     signal(SIGTTOU,SIG_IGN);
1143     signal(SIGTTIN,SIG_IGN);
1144
1145 } /* dlt_daemon_daemonize() */
1146
1147 int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1148 {
1149     socklen_t cli_size;
1150     struct sockaddr cli;
1151
1152     int in_sock = -1;
1153
1154     PRINT_FUNCTION_VERBOSE(verbose);
1155
1156     if ((daemon==0)  || (daemon_local==0))
1157     {
1158         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_client_connect()\n");
1159         return -1;
1160     }
1161
1162     /* event from TCP server socket, new connection */
1163     cli_size = sizeof(cli);
1164     if ((in_sock  = accept(daemon_local->sock,&cli, &cli_size)) < 0)
1165     {
1166         dlt_log(LOG_ERR, "accept() failed!\n");
1167         return -1 ;
1168     }
1169
1170     /* check if file file descriptor was already used, and make it invalid if it is reused */
1171     /* This prevents sending messages to wrong file descriptor */
1172     dlt_daemon_applications_invalidate_fd(daemon,in_sock,verbose);
1173     dlt_daemon_contexts_invalidate_fd(daemon,in_sock,verbose);
1174
1175     /* Set socket timeout in reception */
1176     struct timeval timeout_send;
1177     timeout_send.tv_sec = daemon_local->timeoutOnSend;
1178     timeout_send.tv_usec = 0;
1179     if (setsockopt (in_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout_send, sizeof(timeout_send)) < 0)
1180         dlt_log(LOG_ERR, "setsockopt failed\n");
1181
1182     //sprintf("str,"Client Connection from %s\n", inet_ntoa(cli.sin_addr));
1183     //dlt_log(str);
1184     FD_SET(in_sock, &(daemon_local->master)); /* add to master set */
1185     if (in_sock > daemon_local->fdmax)
1186     {
1187         /* keep track of the maximum */
1188         daemon_local->fdmax = in_sock;
1189     } /* if */
1190
1191     daemon_local->client_connections++;
1192     if (daemon_local->flags.vflag)
1193     {
1194         sprintf(str, "New connection to client established, #connections: %d\n",daemon_local->client_connections);
1195         dlt_log(LOG_INFO, str);
1196     }
1197
1198     // send connection info about connected
1199     dlt_daemon_control_message_connection_info(in_sock,daemon,DLT_CONNECTION_STATUS_CONNECTED,"",verbose);
1200
1201     // send ecu version string
1202     if(daemon_local->flags.sendECUSoftwareVersion > 0)
1203     {
1204         dlt_daemon_send_ecuversion(daemon,daemon_local);
1205     }
1206
1207     if (daemon_local->client_connections==1)
1208     {
1209         if (daemon_local->flags.vflag)
1210         {
1211             dlt_log(LOG_INFO, "Send ring-buffer to client\n");
1212         }
1213         if (dlt_daemon_send_ringbuffer_to_client(daemon, daemon_local, verbose)==-1)
1214         {
1215                 dlt_log(LOG_ERR,"Can't send contents of ringbuffer to clients\n");
1216                         return -1;
1217         }
1218                 
1219                 /* send new log state to all applications */
1220                 daemon->state = 1;              
1221                 dlt_daemon_user_send_all_log_state(daemon,verbose);
1222     }
1223
1224     return 0;
1225 }
1226
1227 int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1228 {
1229     int bytes_to_be_removed=0;
1230
1231     PRINT_FUNCTION_VERBOSE(verbose);
1232
1233     if ((daemon==0)  || (daemon_local==0))
1234     {
1235         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_client_messages()\n");
1236         return -1;
1237     }
1238
1239     if (dlt_receiver_receive_socket(&(daemon_local->receiverSock))<=0)
1240     {
1241         dlt_daemon_close_socket(daemon_local->receiverSock.fd, daemon, daemon_local, verbose);
1242         daemon_local->receiverSock.fd = -1;
1243         /* check: return 0; */
1244     }
1245
1246     /* Process all received messages */
1247     while (dlt_message_read(&(daemon_local->msg),(uint8_t*)daemon_local->receiverSock.buf,daemon_local->receiverSock.bytesRcvd,daemon_local->flags.nflag,daemon_local->flags.vflag)==0)
1248     {
1249         /* Check for control message */
1250         if ( 0 < daemon_local->receiverSock.fd && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)) )
1251         {
1252             dlt_daemon_control_process_control(daemon_local->receiverSock.fd, daemon, &(daemon_local->msg), daemon_local->flags.vflag);
1253         }
1254
1255         bytes_to_be_removed = daemon_local->msg.headersize+daemon_local->msg.datasize-sizeof(DltStorageHeader);
1256         if (daemon_local->msg.found_serialheader)
1257         {
1258             bytes_to_be_removed += sizeof(dltSerialHeader);
1259         }
1260         if (daemon_local->msg.resync_offset)
1261         {
1262             bytes_to_be_removed += daemon_local->msg.resync_offset;
1263         }
1264
1265         if (dlt_receiver_remove(&(daemon_local->receiverSock),bytes_to_be_removed)==-1)
1266         {
1267                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for sockets\n");
1268                         return -1;
1269         }
1270
1271     } /* while */
1272
1273
1274     if (dlt_receiver_move_to_begin(&(daemon_local->receiverSock))==-1)
1275     {
1276         dlt_log(LOG_ERR,"Can't move bytes to beginning of receiver buffer for sockets\n");
1277                 return -1;
1278     }
1279
1280     return 0;
1281 }
1282
1283 int dlt_daemon_process_client_messages_serial(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1284 {
1285     int bytes_to_be_removed=0;
1286
1287     PRINT_FUNCTION_VERBOSE(verbose);
1288
1289     if ((daemon==0)  || (daemon_local==0))
1290     {
1291                 dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_client_messages_serial()\n");
1292         return -1;
1293     }
1294
1295     if (dlt_receiver_receive_fd(&(daemon_local->receiverSerial))<=0)
1296     {
1297                 dlt_log(LOG_ERR, "dlt_receiver_receive_fd() for messages from serial interface failed!\n");
1298         return -1;
1299     }
1300
1301     /* Process all received messages */
1302     while (dlt_message_read(&(daemon_local->msg),(uint8_t*)daemon_local->receiverSerial.buf,daemon_local->receiverSerial.bytesRcvd,daemon_local->flags.mflag,daemon_local->flags.vflag)==0)
1303     {
1304         /* Check for control message */
1305         if (DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)))
1306         {
1307             if (dlt_daemon_control_process_control(daemon_local->receiverSerial.fd, daemon, &(daemon_local->msg), daemon_local->flags.vflag)==-1)
1308             {
1309                                 dlt_log(LOG_ERR,"Can't process control messages\n");
1310                                 return -1;
1311             }
1312         }
1313
1314         bytes_to_be_removed = daemon_local->msg.headersize+daemon_local->msg.datasize-sizeof(DltStorageHeader);
1315         if (daemon_local->msg.found_serialheader)
1316         {
1317             bytes_to_be_removed += sizeof(dltSerialHeader);
1318         }
1319         if (daemon_local->msg.resync_offset)
1320         {
1321             bytes_to_be_removed += daemon_local->msg.resync_offset;
1322         }
1323
1324         if (dlt_receiver_remove(&(daemon_local->receiverSerial),bytes_to_be_removed)==-1)
1325                 {
1326                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for serial connection\n");
1327                         return -1;
1328         }
1329
1330     } /* while */
1331
1332
1333     if (dlt_receiver_move_to_begin(&(daemon_local->receiverSerial))==-1)
1334         {
1335         dlt_log(LOG_ERR,"Can't move bytes to beginning of receiver buffer for serial connection\n");
1336                 return -1;
1337     }
1338
1339     return 0;
1340 }
1341
1342 int dlt_daemon_process_user_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1343 {
1344     int offset=0;
1345     int run_loop=1;
1346     DltUserHeader *userheader;
1347
1348     PRINT_FUNCTION_VERBOSE(verbose);
1349
1350     if ((daemon==0)  || (daemon_local==0))
1351     {
1352         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_messages()\n");
1353         return -1;
1354     }
1355
1356     /* read data from FIFO */
1357     if (dlt_receiver_receive_fd(&(daemon_local->receiver))<0)
1358     {
1359         dlt_log(LOG_ERR, "dlt_receiver_receive_fd() for user messages failed!\n");
1360         return -1;
1361     }
1362
1363     /* look through buffer as long as data is in there */
1364     do
1365     {
1366         if (daemon_local->receiver.bytesRcvd < (int32_t)sizeof(DltUserHeader))
1367         {
1368             break;
1369         }
1370
1371         /* resync if necessary */
1372         offset=0;
1373         do
1374         {
1375             userheader = (DltUserHeader*) (daemon_local->receiver.buf+offset);
1376
1377             /* Check for user header pattern */
1378             if (dlt_user_check_userheader(userheader))
1379             {
1380                 break;
1381             }
1382
1383             offset++;
1384
1385         }
1386         while ((int32_t)(sizeof(DltUserHeader)+offset)<=daemon_local->receiver.bytesRcvd);
1387
1388         /* Check for user header pattern */
1389         if (dlt_user_check_userheader(userheader)==0)
1390         {
1391             break;
1392         }
1393
1394         /* Set new start offset */
1395         if (offset>0)
1396         {
1397             daemon_local->receiver.buf+=offset;
1398             daemon_local->receiver.bytesRcvd-=offset;
1399         }
1400
1401         switch (userheader->message)
1402         {
1403         case DLT_USER_MESSAGE_OVERFLOW:
1404         {
1405             if (dlt_daemon_process_user_message_overflow(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1406             {
1407                 run_loop=0;
1408             }
1409             break;
1410         }
1411         case DLT_USER_MESSAGE_REGISTER_CONTEXT:
1412         {
1413             if (dlt_daemon_process_user_message_register_context(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1414             {
1415                 run_loop=0;
1416             }
1417             break;
1418         }
1419         case DLT_USER_MESSAGE_UNREGISTER_CONTEXT:
1420         {
1421             if (dlt_daemon_process_user_message_unregister_context(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1422             {
1423                 run_loop=0;
1424             }
1425             break;
1426         }
1427         case DLT_USER_MESSAGE_LOG:
1428         {
1429             if (dlt_daemon_process_user_message_log(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1430             {
1431                 run_loop=0;
1432             }
1433             break;
1434         }
1435 #ifdef DLT_SHM_ENABLE
1436         case DLT_USER_MESSAGE_LOG_SHM:
1437         {
1438             if (dlt_daemon_process_user_message_log_shm(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1439             {
1440                 run_loop=0;
1441             }
1442             break;
1443         }
1444 #endif
1445         case DLT_USER_MESSAGE_REGISTER_APPLICATION:
1446         {
1447             if (dlt_daemon_process_user_message_register_application(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1448             {
1449                 run_loop=0;
1450             }
1451             break;
1452         }
1453         case DLT_USER_MESSAGE_UNREGISTER_APPLICATION:
1454         {
1455             if (dlt_daemon_process_user_message_unregister_application(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1456             {
1457                 run_loop=0;
1458             }
1459             break;
1460         }
1461         case DLT_USER_MESSAGE_APP_LL_TS:
1462         {
1463             if (dlt_daemon_process_user_message_set_app_ll_ts(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1464             {
1465                 run_loop=0;
1466             }
1467             break;
1468         }
1469         case DLT_USER_MESSAGE_LOG_MODE:
1470         {
1471             if (dlt_daemon_process_user_message_log_mode(daemon, daemon_local, daemon_local->flags.vflag)==-1)
1472             {
1473                 run_loop=0;
1474             }
1475             break;
1476         }
1477         default:
1478         {
1479             dlt_log(LOG_ERR,"(Internal) Invalid user message type received!\n");
1480
1481             /* remove user header */
1482             if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader))==-1)
1483             {
1484                                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user messages\n");
1485                                 return -1;
1486                         }
1487
1488             /* In next invocation of do-while loop, a resync will be triggered if additional data was received */
1489             run_loop=0;
1490
1491             break;
1492         }
1493         }
1494
1495     }
1496     while (run_loop);
1497
1498     /* keep not read data in buffer */
1499     if (dlt_receiver_move_to_begin(&(daemon_local->receiver))==-1)
1500         {
1501         dlt_log(LOG_ERR,"Can't move bytes to beginning of receiver buffer for user messages\n");
1502                 return -1;
1503     }
1504
1505     return 0;
1506 }
1507
1508 int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1509 {
1510     int j, sent;
1511     DltUserControlMsgBufferOverflow *userpayload;
1512
1513     PRINT_FUNCTION_VERBOSE(verbose);
1514
1515     if ((daemon==0)  || (daemon_local==0))
1516     {
1517         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
1518         return -1;
1519     }
1520
1521     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgBufferOverflow)))
1522     {
1523         /* Not enough bytes received */
1524         return -1;
1525     }
1526
1527     /* get the payload of the user message */
1528     userpayload = (DltUserControlMsgBufferOverflow*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
1529
1530     /* Store in daemon, that a message buffer overflow has occured */
1531     daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_OVERFLOW;
1532
1533     /* look if TCP connection to client is available */
1534     sent = 0;
1535
1536     for (j = 0; j <= daemon_local->fdmax; j++)
1537     {
1538         /* send to everyone! */
1539         if (FD_ISSET(j, &(daemon_local->master)))
1540         {
1541             /* except the listener and ourselves */
1542             if ((j != daemon_local->fp) && (j != daemon_local->sock)
1543 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
1544                         && (j!=daemon_local->timer_wd)
1545 #endif
1546                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
1547             {
1548                 dlt_daemon_control_message_buffer_overflow(j, daemon, userpayload->overflow_counter,userpayload->apid,verbose);
1549                 sent=1;
1550                 /* Reset overflow state */
1551                 daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_NO_OVERFLOW;
1552             } /* if */
1553         } /* if */
1554     } /* for */
1555
1556     /* message was not sent, so store it in ringbuffer */
1557     if (sent==0)
1558     {
1559         if(dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_STORE_TO_BUFFER, daemon, userpayload->overflow_counter,
1560                                                               userpayload->apid,verbose))
1561         {
1562                 /* there was an error when storing message */
1563                 /* add the counter of lost messages to the daemon counter */
1564                 daemon->overflow_counter+=userpayload->overflow_counter;
1565         }
1566     }
1567
1568     /* keep not read data in buffer */
1569     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgBufferOverflow))==-1)
1570     {
1571                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message overflow\n");
1572                 return -1;
1573     }
1574
1575     return 0;
1576 }
1577
1578 int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1579 {
1580     int j, sent;
1581
1582     PRINT_FUNCTION_VERBOSE(verbose);
1583
1584     if ((daemon==0)  || (daemon_local==0))
1585     {
1586         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
1587         return -1;
1588     }
1589
1590     /* Store in daemon, that a message buffer overflow has occured */
1591     daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_OVERFLOW;
1592
1593     /* look if TCP connection to client is available */
1594     sent = 0;
1595
1596     for (j = 0; j <= daemon_local->fdmax; j++)
1597     {
1598         /* send to everyone! */
1599         if (FD_ISSET(j, &(daemon_local->master)))
1600         {
1601             /* except the listener and ourselves */
1602             if ((j != daemon_local->fp) && (j != daemon_local->sock)
1603 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
1604                         && (j!=daemon_local->timer_wd)
1605 #endif
1606                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
1607             {
1608                 dlt_daemon_control_message_buffer_overflow(j, daemon,daemon->overflow_counter,"", verbose);
1609                 sent=1;
1610                 /* Reset overflow state */
1611                 daemon->message_buffer_overflow = DLT_MESSAGE_BUFFER_NO_OVERFLOW;
1612             } /* if */
1613         } /* if */
1614     } /* for */
1615
1616     /* message was not sent, so report to caller that sending failed */
1617     if (sent==0)
1618     {
1619         return -1;
1620     }
1621
1622     return 0;
1623 }
1624
1625 int dlt_daemon_process_user_message_register_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1626 {
1627     uint32_t len=0;
1628     DltDaemonApplication *application;
1629     char description[DLT_DAEMON_DESCSIZE];
1630     DltUserControlMsgRegisterApplication *usercontext;
1631
1632     PRINT_FUNCTION_VERBOSE(verbose);
1633
1634     if ((daemon==0)  || (daemon_local==0))
1635     {
1636         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_register_application()\n");
1637         return -1;
1638     }
1639
1640     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterApplication)))
1641     {
1642         /* Not enough bytes received */
1643         return -1;
1644     }
1645
1646     usercontext = (DltUserControlMsgRegisterApplication*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
1647
1648     memset(description,0,sizeof(description));
1649
1650     len=usercontext->description_length;
1651     if ((len>0) && (len<=DLT_DAEMON_DESCSIZE))
1652     {
1653         /* Read and store application description */
1654         strncpy(description, (daemon_local->receiver.buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterApplication)), len);
1655     }
1656
1657     application=dlt_daemon_application_add(daemon,usercontext->apid,usercontext->pid,description,verbose);
1658
1659         /* send log state to new application */
1660         dlt_daemon_user_send_log_state(daemon,application,verbose);
1661
1662     /* keep not read data in buffer */
1663     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterApplication)+len)==-1)
1664         {
1665                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message register application\n");
1666                 return -1;
1667     }
1668
1669     if (application==0)
1670     {
1671         dlt_log(LOG_CRIT,"Can't add application");
1672         return -1;
1673     }
1674
1675     return 0;
1676 }
1677
1678 int dlt_daemon_process_user_message_register_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1679 {
1680     uint32_t len=0;
1681     int8_t loglevel, tracestatus;
1682     DltUserControlMsgRegisterContext *usercontext;
1683     char description[DLT_DAEMON_DESCSIZE];
1684         DltDaemonApplication *application;
1685         DltDaemonContext *context;
1686         DltServiceGetLogInfoRequest *req;
1687
1688         DltMessage msg;
1689         int j;
1690         int sent;
1691
1692     PRINT_FUNCTION_VERBOSE(verbose);
1693
1694     if ((daemon==0)  || (daemon_local==0))
1695     {
1696         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_register_context()\n");
1697         return -1;
1698     }
1699
1700     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)))
1701     {
1702         /* Not enough bytes received */
1703         return -1;
1704     }
1705
1706     usercontext = (DltUserControlMsgRegisterContext*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
1707
1708     memset(description,0,sizeof(description));
1709
1710     len=usercontext->description_length;
1711     if ((len>0) && (len<=DLT_DAEMON_DESCSIZE))
1712     {
1713         /* Read and store context description */
1714         strncpy(description, (daemon_local->receiver.buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)), len);
1715     }
1716
1717     application = dlt_daemon_application_find(daemon,usercontext->apid,verbose);
1718
1719     if (application==0)
1720     {
1721         dlt_log(LOG_ERR, "Application not found in dlt_daemon_process_user_message_register_context()\n");
1722         if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)+len)==-1)
1723                 {
1724                         dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message register context\n");
1725                         return -1;
1726                 }
1727         return 0;
1728     }
1729
1730     /* Pre-set loglevel */
1731     if (usercontext->log_level == DLT_USER_LOG_LEVEL_NOT_SET)
1732     {
1733         loglevel=DLT_LOG_DEFAULT;
1734     }
1735     else
1736     {
1737         loglevel=usercontext->log_level;
1738         /* Plausibility check */
1739         if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1740         {
1741             if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)+len)==-1)
1742             {
1743                                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message register context\n");
1744                         }
1745             return -1;
1746         }
1747     }
1748
1749     /* Pre-set tracestatus */
1750     if (usercontext->trace_status == DLT_USER_TRACE_STATUS_NOT_SET)
1751     {
1752         tracestatus=DLT_TRACE_STATUS_DEFAULT;
1753     }
1754     else
1755     {
1756         tracestatus=usercontext->trace_status;
1757
1758         /* Plausibility check */
1759         if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1760         {
1761             if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)+len)==-1)
1762                         {
1763                                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message register context\n");
1764                         }
1765             return -1;
1766         }
1767     }
1768
1769     context = dlt_daemon_context_add(daemon,usercontext->apid,usercontext->ctid, loglevel, tracestatus, usercontext->log_level_pos,application->user_handle,description,verbose);
1770
1771     if (context==0)
1772     {
1773         if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)+len)==-1)
1774                 {
1775                         dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message register context\n");
1776                 }
1777
1778                 dlt_log(LOG_CRIT,"Can't add context");
1779         return -1;
1780     }
1781     /* Create automatic get log info response for registered context */
1782     if (daemon_local->flags.rflag)
1783     {
1784         /* Prepare request for get log info with one application and one context */
1785         if (dlt_message_init(&msg, verbose)==-1)
1786         {
1787                 dlt_log(LOG_ERR,"Can't initialize message");
1788                 return -1;
1789         }
1790
1791         msg.datasize = sizeof(DltServiceGetLogInfoRequest);
1792         if (msg.databuffer && (msg.databuffersize < msg.datasize))
1793         {
1794             free(msg.databuffer);
1795             msg.databuffer=0;
1796         }
1797         if (msg.databuffer == 0){
1798                 msg.databuffer = (uint8_t *) malloc(msg.datasize);
1799                 msg.databuffersize = msg.datasize;
1800         }
1801         if (msg.databuffer==0)
1802         {
1803                 dlt_log(LOG_ERR,"Can't allocate buffer for get log info message\n");
1804                         return -1;
1805         }
1806
1807         req = (DltServiceGetLogInfoRequest*) msg.databuffer;
1808
1809         req->service_id = DLT_SERVICE_ID_GET_LOG_INFO;
1810         req->options = 7;
1811         dlt_set_id(req->apid, usercontext->apid);
1812         dlt_set_id(req->ctid, usercontext->ctid);
1813         dlt_set_id(req->com,"remo");
1814
1815         sent=0;
1816
1817         /* Send response to get log info request to DLT clients */
1818         for (j = 0; j <= daemon_local->fdmax; j++)
1819         {
1820             /* send to everyone! */
1821             if (FD_ISSET(j, &(daemon_local->master)))
1822             {
1823                 /* except the listener and ourselves */
1824                 if ((j != daemon_local->fp) && (j != daemon_local->sock)
1825     #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
1826                             && (j!=daemon_local->timer_wd)
1827     #endif
1828                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
1829                 {
1830                     dlt_daemon_control_get_log_info(j , daemon, &msg, verbose);
1831                     sent=1;
1832                 }
1833             }
1834         }
1835
1836         if (sent==0)
1837         {
1838             /* Store to buffer */
1839             dlt_daemon_control_get_log_info(DLT_DAEMON_STORE_TO_BUFFER , daemon, &msg, verbose);
1840         }
1841
1842         dlt_message_free(&msg, verbose);
1843     }
1844
1845     if (context->user_handle >= DLT_FD_MINIMUM)
1846     {
1847         /* This call also replaces the default values with the values defined for default */
1848         if (dlt_daemon_user_send_log_level(daemon, context, verbose)==-1)
1849         {
1850                         dlt_log(LOG_ERR,"Can't send current log level as response to user message register context\n");
1851                         return -1;
1852         }
1853     }
1854
1855     /* keep not read data in buffer */
1856     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgRegisterContext)+len)==-1)
1857         {
1858                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message register context\n");
1859                 return -1;
1860         }
1861
1862     return 0;
1863 }
1864
1865 int dlt_daemon_process_user_message_unregister_application(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1866 {
1867     DltUserControlMsgUnregisterApplication *usercontext;
1868     DltDaemonApplication *application;
1869     DltDaemonContext *context;
1870     int i, offset_base;
1871
1872     PRINT_FUNCTION_VERBOSE(verbose);
1873
1874     if ((daemon==0)  || (daemon_local==0))
1875     {
1876         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_unregister_application()\n");
1877         return -1;
1878     }
1879
1880     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgUnregisterApplication)))
1881     {
1882         /* Not enough bytes received */
1883         return -1;
1884     }
1885
1886     if (daemon->num_applications>0)
1887     {
1888         usercontext = (DltUserControlMsgUnregisterApplication*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
1889
1890         /* Delete this application and all corresponding contexts for this application from internal table */
1891         application = dlt_daemon_application_find(daemon,usercontext->apid, verbose);
1892
1893         if (application)
1894         {
1895             /* Calculate start offset within contexts[] */
1896             offset_base=0;
1897             for (i=0; i<(application-(daemon->applications)); i++)
1898             {
1899                 offset_base+=daemon->applications[i].num_contexts;
1900             }
1901
1902             for (i=application->num_contexts-1; i>=0; i--)
1903             {
1904                 context = &(daemon->contexts[offset_base+i]);
1905                 if (context)
1906                 {
1907                     /* Delete context */
1908                     if (dlt_daemon_context_del(daemon, context, verbose)==-1)
1909                     {
1910                         dlt_log(LOG_ERR,"Can't delete context for user message unregister application\n");
1911                         return -1;
1912                     }
1913                 }
1914             }
1915
1916             /* Delete this application entry from internal table*/
1917             if (dlt_daemon_application_del(daemon, application, verbose)==-1)
1918             {
1919                 dlt_log(LOG_ERR,"Can't delete application for user message unregister application\n");
1920                                 return -1;
1921             }
1922         }
1923     }
1924
1925     /* keep not read data in buffer */
1926     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgUnregisterApplication))==-1)
1927     {
1928         dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message unregister application\n");
1929                 return -1;
1930     }
1931
1932     return 0;
1933 }
1934
1935 int dlt_daemon_process_user_message_unregister_context(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
1936 {
1937         DltUserControlMsgUnregisterContext *usercontext;
1938         DltDaemonContext *context;
1939
1940     PRINT_FUNCTION_VERBOSE(verbose);
1941
1942     if ((daemon==0)  || (daemon_local==0))
1943     {
1944         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_unregister_context()\n");
1945         return -1;
1946     }
1947
1948     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgUnregisterContext)))
1949     {
1950         /* Not enough bytes received */
1951         return -1;
1952     }
1953
1954     usercontext = (DltUserControlMsgUnregisterContext*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
1955     context = dlt_daemon_context_find(daemon,usercontext->apid, usercontext->ctid, verbose);
1956
1957     if (context)
1958     {
1959         /* Delete this connection entry from internal table*/
1960         if (dlt_daemon_context_del(daemon, context, verbose)==-1)
1961         {
1962                         dlt_log(LOG_ERR,"Can't delete context for user message unregister context\n");
1963                         return -1;
1964                 }
1965     }
1966
1967     /* Create automatic unregister context response for unregistered context */
1968     if (daemon_local->flags.rflag)
1969     {
1970         int sent=0;
1971         int j;
1972
1973         /* Send response to get log info request to DLT clients */
1974         for (j = 0; j <= daemon_local->fdmax; j++)
1975         {
1976             /* send to everyone! */
1977             if (FD_ISSET(j, &(daemon_local->master)))
1978             {
1979                 /* except the listener and ourselves */
1980                 if ((j != daemon_local->fp) && (j != daemon_local->sock)
1981     #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
1982                             && (j!=daemon_local->timer_wd)
1983     #endif
1984                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
1985                 {
1986                         dlt_daemon_control_message_unregister_context(j,daemon,usercontext->apid, usercontext->ctid, "remo",verbose);
1987                     sent=1;
1988                 }
1989             }
1990         }
1991
1992         if (sent==0)
1993         {
1994             /* Store to buffer */
1995                 dlt_daemon_control_message_unregister_context(DLT_DAEMON_STORE_TO_BUFFER,daemon,usercontext->apid, usercontext->ctid, "remo",verbose);
1996         }
1997     }
1998
1999     /* keep not read data in buffer */
2000     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgUnregisterContext))==-1)
2001     {
2002         dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message unregister context\n");
2003                 return -1;
2004     }
2005
2006     return 0;
2007 }
2008
2009 int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2010 {
2011     int bytes_to_be_removed;
2012     int j,sent,third_value;
2013     ssize_t ret;
2014
2015     static char text[DLT_DAEMON_TEXTSIZE];
2016
2017     PRINT_FUNCTION_VERBOSE(verbose);
2018
2019     if ((daemon==0)  || (daemon_local==0))
2020     {
2021         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_log()\n");
2022         return -1;
2023     }
2024
2025     if (dlt_message_read(&(daemon_local->msg),(unsigned char*)daemon_local->receiver.buf+sizeof(DltUserHeader),daemon_local->receiver.bytesRcvd-sizeof(DltUserHeader),0,verbose)==0)
2026     {
2027         /* set overwrite ecu id */
2028         if (daemon_local->flags.evalue!=0)
2029         {
2030             /* Set header extra parameters */
2031             dlt_set_id(daemon_local->msg.headerextra.ecu, daemon->ecuid );
2032             //msg.headerextra.seid = 0;
2033             if (dlt_message_set_extraparameters(&(daemon_local->msg),0)==-1)
2034             {
2035                 dlt_log(LOG_ERR,"Can't set message extra parameters in process user message log\n");
2036                                 return -1;
2037             }
2038
2039             /* Correct value of timestamp, this was changed by dlt_message_set_extraparameters() */
2040             daemon_local->msg.headerextra.tmsp = DLT_BETOH_32(daemon_local->msg.headerextra.tmsp);
2041         }
2042
2043         /* prepare storage header */
2044         if (DLT_IS_HTYP_WEID(daemon_local->msg.standardheader->htyp))
2045         {
2046             if (dlt_set_storageheader(daemon_local->msg.storageheader,daemon_local->msg.headerextra.ecu)==-1)
2047             {
2048                                 dlt_log(LOG_ERR,"Can't set storage header in process user message log\n");
2049                                 return -1;
2050             }
2051         }
2052         else
2053         {
2054             if (dlt_set_storageheader(daemon_local->msg.storageheader,daemon->ecuid)==-1)
2055             {
2056                                 dlt_log(LOG_ERR,"Can't set storage header in process user message log\n");
2057                                 return -1;
2058             }
2059         }
2060
2061         {
2062             /* if no filter set or filter is matching display message */
2063             if (daemon_local->flags.xflag)
2064             {
2065                 if (dlt_message_print_hex(&(daemon_local->msg),text,DLT_DAEMON_TEXTSIZE,verbose)==-1)
2066                                 {
2067                                         dlt_log(LOG_ERR,"dlt_message_print_hex() failed!\n");
2068                                 }
2069             } /*  if */
2070             else if (daemon_local->flags.aflag)
2071             {
2072                 if (dlt_message_print_ascii(&(daemon_local->msg),text,DLT_DAEMON_TEXTSIZE,verbose)==-1)
2073                 {
2074                                         dlt_log(LOG_ERR,"dlt_message_print_ascii() failed!\n");
2075                                 }
2076             } /* if */
2077             else if (daemon_local->flags.sflag)
2078             {
2079                 if (dlt_message_print_header(&(daemon_local->msg),text,DLT_DAEMON_TEXTSIZE,verbose)==-1)
2080                                 {
2081                                         dlt_log(LOG_ERR,"dlt_message_print_header() failed!\n");
2082                                 }
2083                 /* print message header only */
2084             } /* if */
2085
2086             sent=0;
2087
2088                         /* write message to offline trace */
2089                         if(((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) && daemon_local->flags.offlineTraceDirectory[0])
2090                         {
2091                                 dlt_offline_trace_write(&(daemon_local->offlineTrace),daemon_local->msg.headerbuffer,daemon_local->msg.headersize,
2092                                                                                 daemon_local->msg.databuffer,daemon_local->msg.datasize,0,0);
2093                                 sent = 1;
2094                         }
2095
2096                         /* check if overflow occurred */
2097                         if(daemon->overflow_counter)
2098                         {
2099                                 if(dlt_daemon_send_message_overflow(daemon,daemon_local,verbose)==0)
2100                                 {
2101                                         sprintf(str,"%u messages discarded!\n",daemon->overflow_counter);
2102                                         dlt_log(LOG_ERR, str);
2103                                         daemon->overflow_counter=0;
2104                                 }
2105                         }
2106
2107             /* look if TCP connection to client is available */
2108             for (j = 0;((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) &&  (j <= daemon_local->fdmax); j++)
2109             {
2110                 /* send to everyone! */
2111                 if (FD_ISSET(j, &(daemon_local->master)))
2112                 {
2113                     /* except the listener and ourselves */
2114                     if (daemon_local->flags.yvalue[0])
2115                     {
2116                         third_value = daemon_local->fdserial;
2117                     }
2118                     else
2119                     {
2120                         third_value = daemon_local->sock;
2121                     }
2122
2123                                         if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value)
2124                 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
2125                                                                 && (j!=daemon_local->timer_wd)
2126                 #endif
2127                                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
2128                     {
2129                                                 int failed = 0;
2130
2131                         DLT_DAEMON_SEM_LOCK();
2132
2133                         if (daemon_local->flags.lflag)
2134                         {
2135                             if(0 > send(j,dltSerialHeader,sizeof(dltSerialHeader),0))
2136                             {
2137                                 dlt_daemon_close_socket(j, daemon, daemon_local, verbose);
2138                                 failed = 1;
2139                             }
2140                         }
2141
2142                         if(!failed && 0 > send(j,daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),daemon_local->msg.headersize-sizeof(DltStorageHeader),0))
2143                         {
2144                                 dlt_daemon_close_socket(j, daemon, daemon_local, verbose);
2145                                 failed = 1;
2146                         }
2147
2148                         if(!failed && 0 > send(j,daemon_local->msg.databuffer,daemon_local->msg.datasize,0))
2149                         {
2150                                 dlt_daemon_close_socket(j, daemon, daemon_local, verbose);
2151                                 failed = 1;
2152                         }
2153
2154                         DLT_DAEMON_SEM_FREE();
2155
2156                         sent=1;
2157                     } /* if */
2158                     else if ((j == daemon_local->fdserial) && (daemon_local->flags.yvalue!=0))
2159                     {
2160                         DLT_DAEMON_SEM_LOCK();
2161
2162                         if (daemon_local->flags.lflag)
2163                         {
2164                             ret=write(j,dltSerialHeader,sizeof(dltSerialHeader));
2165                                                 if (0 > ret)
2166                             {
2167                                   dlt_log(LOG_ERR,"write(j,dltSerialHeader failed\n");
2168                             }
2169                         }
2170                         int32_t diff = daemon_local->msg.headersize-sizeof(DltStorageHeader);
2171                         //extra calculation for coverity
2172                         if ( 0 <= diff ){
2173                                 ret=write(j,daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),diff);
2174                                                                 if (0 > ret)
2175                                         {
2176                                                 dlt_log(LOG_ERR,"write(j,daemon_local->msg.headerbuffer failed\n");
2177                                         }
2178                                 ret=write(j,daemon_local->msg.databuffer,daemon_local->msg.datasize);
2179                                                                 if (0 > ret)
2180                                         {
2181                                                                         dlt_log(LOG_ERR,"write(j,daemon_local->msg.databuffer failed\n");
2182                                         }
2183                         }
2184
2185                         DLT_DAEMON_SEM_FREE();
2186
2187                         sent=1;
2188                     }
2189                 } /* if */
2190             } /* for */
2191
2192             /* Message was not sent to client, so store it in client ringbuffer */
2193             if (sent==0)
2194             {
2195                 DLT_DAEMON_SEM_LOCK();
2196                 if (dlt_buffer_push3(&(daemon->client_ringbuffer),
2197                                     daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),daemon_local->msg.headersize-sizeof(DltStorageHeader),
2198                                     daemon_local->msg.databuffer,daemon_local->msg.datasize,
2199                                     0, 0
2200                                    )<0)
2201                                 {
2202                         if(daemon->overflow_counter==0)
2203                                         dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
2204                         daemon->overflow_counter+=1;
2205                                 }
2206                 DLT_DAEMON_SEM_FREE();
2207             }
2208
2209         }
2210         /* keep not read data in buffer */
2211         bytes_to_be_removed = daemon_local->msg.headersize+daemon_local->msg.datasize-sizeof(DltStorageHeader)+sizeof(DltUserHeader);
2212         if (daemon_local->msg.found_serialheader)
2213         {
2214             bytes_to_be_removed += sizeof(dltSerialHeader);
2215         }
2216
2217         if (dlt_receiver_remove(&(daemon_local->receiver),bytes_to_be_removed)==-1)
2218         {
2219                 dlt_log(LOG_ERR,"Can't remove bytes from receiver\n");
2220                 return -1;
2221         }
2222     }
2223     else
2224     {
2225         dlt_log(LOG_ERR,"Can't read messages from receiver\n");
2226         return -1;
2227     }
2228
2229     return 0;
2230 }
2231
2232 #ifdef DLT_SHM_ENABLE
2233 int dlt_daemon_process_user_message_log_shm(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2234 {
2235     int bytes_to_be_removed=0;
2236     int j,sent,third_value;
2237     ssize_t ret;
2238     uint8_t rcv_buffer[10000];
2239     int size;
2240     DltUserHeader *userheader;
2241
2242     static char text[DLT_DAEMON_TEXTSIZE];
2243
2244     PRINT_FUNCTION_VERBOSE(verbose);
2245
2246     if ((daemon==0)  || (daemon_local==0))
2247     {
2248         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_log()\n");
2249         return -1;
2250     }
2251
2252     userheader = (DltUserHeader*) (daemon_local->receiver.buf);
2253   
2254         //dlt_shm_status(&(daemon_local->dlt_shm));
2255         while (1)
2256     {           
2257                 /* log message in SHM */
2258                 if((size = dlt_shm_copy(&(daemon_local->dlt_shm),rcv_buffer,10000)) <= 0)
2259                         break;
2260                 if (dlt_message_read(&(daemon_local->msg),rcv_buffer,size,0,verbose)!=0) {
2261                         break;
2262                         dlt_log(LOG_ERR,"Can't read messages from shm\n");
2263                         return -1;
2264                 }                               
2265                 bytes_to_be_removed = daemon_local->msg.headersize+daemon_local->msg.datasize-sizeof(DltStorageHeader)+sizeof(DltUserHeader);
2266                 if (daemon_local->msg.found_serialheader)
2267                 {
2268                         bytes_to_be_removed += sizeof(dltSerialHeader);
2269                 }
2270                 
2271                 /* set overwrite ecu id */
2272                 if (daemon_local->flags.evalue[0])
2273                 {
2274                         /* Set header extra parameters */
2275                         dlt_set_id(daemon_local->msg.headerextra.ecu, daemon->ecuid );
2276                         //msg.headerextra.seid = 0;
2277                         if (dlt_message_set_extraparameters(&(daemon_local->msg),0)==-1)
2278                         {
2279                                 dlt_log(LOG_ERR,"Can't set message extra parameters in process user message log\n");
2280                                 dlt_shm_remove(&(daemon_local->dlt_shm));
2281                                 return -1;
2282                         }
2283
2284                         /* Correct value of timestamp, this was changed by dlt_message_set_extraparameters() */
2285                         daemon_local->msg.headerextra.tmsp = DLT_BETOH_32(daemon_local->msg.headerextra.tmsp);
2286                 }
2287
2288                 /* prepare storage header */
2289                 if (DLT_IS_HTYP_WEID(daemon_local->msg.standardheader->htyp))
2290                 {
2291                         if (dlt_set_storageheader(daemon_local->msg.storageheader,daemon_local->msg.headerextra.ecu)==-1)
2292                         {
2293                                 dlt_log(LOG_ERR,"Can't set storage header in process user message log\n");
2294                                 dlt_shm_remove(&(daemon_local->dlt_shm));
2295                                 return -1;
2296                         }
2297                 }
2298                 else
2299                 {
2300                         if (dlt_set_storageheader(daemon_local->msg.storageheader,daemon->ecuid)==-1)
2301                         {
2302                                 dlt_log(LOG_ERR,"Can't set storage header in process user message log\n");
2303                                 dlt_shm_remove(&(daemon_local->dlt_shm));
2304                                 return -1;
2305                         }
2306                 }
2307
2308                 /* display message */
2309                 if (daemon_local->flags.xflag)
2310                 {
2311                         if (dlt_message_print_hex(&(daemon_local->msg),text,DLT_DAEMON_TEXTSIZE,verbose)==-1)
2312                         {
2313                                 dlt_log(LOG_ERR,"dlt_message_print_hex() failed!\n");
2314                         }
2315                 } /*  if */
2316                 else if (daemon_local->flags.aflag)
2317                 {
2318                         if (dlt_message_print_ascii(&(daemon_local->msg),text,DLT_DAEMON_TEXTSIZE,verbose)==-1)
2319                         {
2320                                 dlt_log(LOG_ERR,"dlt_message_print_ascii() failed!\n");
2321                         }
2322                 } /* if */
2323                 else if (daemon_local->flags.sflag)
2324                 {
2325                         if (dlt_message_print_header(&(daemon_local->msg),text,DLT_DAEMON_TEXTSIZE,verbose)==-1)
2326                         {
2327                                 dlt_log(LOG_ERR,"dlt_message_print_header() failed!\n");
2328                         }
2329                         /* print message header only */
2330                 } /* if */
2331
2332                 sent=0;
2333
2334                 /* write message to offline trace */
2335                 if(((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) && daemon_local->flags.offlineTraceDirectory[0])
2336                 {
2337                         dlt_offline_trace_write(&(daemon_local->offlineTrace),daemon_local->msg.headerbuffer,daemon_local->msg.headersize,
2338                                                                         daemon_local->msg.databuffer,daemon_local->msg.datasize,0,0);
2339                         sent = 1;
2340                 }
2341
2342                 /* look if TCP connection to client is available */
2343                 for (j = 0;((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) &&  (j <= daemon_local->fdmax); j++)
2344                 {
2345                         /* send to everyone! */
2346                         if (FD_ISSET(j, &(daemon_local->master)))
2347                         {
2348                                 /* except the listener and ourselves */
2349                                 if (daemon_local->flags.yvalue[0])
2350                                 {
2351                                         third_value = daemon_local->fdserial;
2352                                 }
2353                                 else
2354                                 {
2355                                         third_value = daemon_local->sock;
2356                                 }
2357
2358                                 if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value))
2359                                 {
2360                                         DLT_DAEMON_SEM_LOCK();
2361
2362                                         if (daemon_local->flags.lflag)
2363                                         {
2364                                                 send(j,dltSerialHeader,sizeof(dltSerialHeader),0);
2365                                         }
2366
2367                                         send(j,daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),daemon_local->msg.headersize-sizeof(DltStorageHeader),0);
2368                                         send(j,daemon_local->msg.databuffer,daemon_local->msg.datasize,0);
2369
2370                                         DLT_DAEMON_SEM_FREE();
2371
2372                                         sent=1;
2373                                 } /* if */
2374                                 else if ((j == daemon_local->fdserial) && (daemon_local->flags.yvalue[0]))
2375                                 {
2376                                         DLT_DAEMON_SEM_LOCK();
2377
2378                                         if (daemon_local->flags.lflag)
2379                                         {
2380                                                 ret=write(j,dltSerialHeader,sizeof(dltSerialHeader));
2381                                         }
2382
2383                                         ret=write(j,daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),daemon_local->msg.headersize-sizeof(DltStorageHeader));
2384                                         ret=write(j,daemon_local->msg.databuffer,daemon_local->msg.datasize);
2385
2386                                         DLT_DAEMON_SEM_FREE();
2387
2388                                         sent=1;
2389                                 }
2390                         } /* if */
2391                 } /* for */
2392
2393                 /* Message was not sent to client, so store it in client ringbuffer */
2394                 if (sent==1 || (daemon->mode == DLT_USER_MODE_OFF))
2395                 {
2396                         if(userheader->message == DLT_USER_MESSAGE_LOG_SHM) {
2397                                 /* dlt message was sent, remove from buffer if log message from shm */
2398                                 dlt_shm_remove(&(daemon_local->dlt_shm));
2399                         }                       
2400                 }
2401                 else
2402                 {
2403                         /* dlt message was not sent, keep in buffer */
2404                         break;
2405                 }
2406                 
2407         }
2408
2409     /* keep not read data in buffer */
2410     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader))==-1)
2411     {
2412                 dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message overflow\n");
2413                 return -1;
2414     }
2415     
2416     return 0;
2417 }
2418 #endif
2419
2420 int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2421 {
2422     DltUserControlMsgAppLogLevelTraceStatus *usercontext;
2423     DltDaemonApplication *application;
2424     DltDaemonContext *context;
2425     int i, offset_base;
2426     int8_t old_log_level, old_trace_status;
2427
2428     PRINT_FUNCTION_VERBOSE(verbose);
2429
2430     if ((daemon==0)  || (daemon_local==0))
2431     {
2432         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_set_app_ll_ts()\n");
2433         return -1;
2434     }
2435
2436     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgAppLogLevelTraceStatus )))
2437     {
2438         /* Not enough bytes receeived */
2439         return -1;
2440     }
2441
2442     if (daemon->num_applications>0)
2443     {
2444         usercontext = (DltUserControlMsgAppLogLevelTraceStatus*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
2445
2446         /* Get all contexts with application id matching the received application id */
2447         application = dlt_daemon_application_find(daemon, usercontext->apid, verbose);
2448         if (application)
2449         {
2450             /* Calculate start offset within contexts[] */
2451             offset_base=0;
2452             for (i=0; i<(application-(daemon->applications)); i++)
2453             {
2454                 offset_base+=daemon->applications[i].num_contexts;
2455             }
2456
2457             for (i=0; i < application->num_contexts; i++)
2458             {
2459                 context = &(daemon->contexts[offset_base+i]);
2460                 if (context)
2461                 {
2462                     old_log_level = context->log_level;
2463                     context->log_level = usercontext->log_level; /* No endianess conversion necessary*/
2464
2465                     old_trace_status = context->trace_status;
2466                     context->trace_status = usercontext->trace_status;   /* No endianess conversion necessary */
2467
2468                     /* The folowing function sends also the trace status */
2469                     if (context->user_handle >= DLT_FD_MINIMUM && dlt_daemon_user_send_log_level(daemon, context, verbose)!=0)
2470                     {
2471                         context->log_level = old_log_level;
2472                         context->trace_status = old_trace_status;
2473                     }
2474                 }
2475             }
2476         }
2477     }
2478
2479     /* keep not read data in buffer */
2480     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgAppLogLevelTraceStatus))==-1)
2481         {
2482                 dlt_log(LOG_ERR,"Can't remove bytes from receiver\n");
2483                 return -1;
2484         }
2485
2486     return 0;
2487 }
2488
2489 int dlt_daemon_process_user_message_log_mode(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2490 {
2491         DltUserControlMsgLogMode *logmode;
2492
2493     PRINT_FUNCTION_VERBOSE(verbose);
2494
2495     if ((daemon==0)  || (daemon_local==0))
2496     {
2497         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_log_mode()\n");
2498         return -1;
2499     }
2500
2501     if (daemon_local->receiver.bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgUnregisterContext)))
2502     {
2503         /* Not enough bytes received */
2504         return -1;
2505     }
2506
2507     logmode = (DltUserControlMsgLogMode*) (daemon_local->receiver.buf+sizeof(DltUserHeader));
2508
2509         /* set the new log mode */
2510         daemon->mode = logmode->log_mode;
2511
2512         /* write configuration persistantly */
2513         dlt_daemon_configuration_save(daemon, daemon->runtime_configuration, verbose);
2514
2515     /* keep not read data in buffer */
2516     if (dlt_receiver_remove(&(daemon_local->receiver),sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogMode))==-1)
2517     {
2518         dlt_log(LOG_ERR,"Can't remove bytes from receiver for user message log mode\n");
2519                 return -1;
2520     }
2521
2522     return 0;
2523 }
2524
2525 int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2526 {
2527     static uint8_t data[DLT_DAEMON_RCVBUFSIZE];
2528     int length;
2529     int j, third_value;
2530     ssize_t ret;
2531
2532     PRINT_FUNCTION_VERBOSE(verbose);
2533
2534     if ((daemon==0)  || (daemon_local==0))
2535     {
2536         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_send_ringbuffer_to_client()\n");
2537         return -1;
2538     }
2539
2540         /* Attention: If the message can't be send at this time, it will be silently discarded. */
2541     while ((length = dlt_buffer_pull(&(daemon->client_ringbuffer), data, sizeof(data) )) > 0)
2542     {
2543         /* look if TCP connection to client is available */
2544         for (j = 0; j <= daemon_local->fdmax; j++)
2545         {
2546             /* send to everyone! */
2547             if (FD_ISSET(j, &(daemon_local->master)))
2548             {
2549                 /* except the listener and ourselves */
2550                 if (daemon_local->flags.yvalue[0])
2551                 {
2552                     third_value = daemon_local->fdserial;
2553                 }
2554                 else
2555                 {
2556                     third_value = daemon_local->sock;
2557                 }
2558
2559                                 if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value)
2560         #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
2561                                                         && (j!=daemon_local->timer_wd)
2562         #endif
2563                                 && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
2564                 {
2565                                         int failed = 0;
2566                     DLT_DAEMON_SEM_LOCK();
2567
2568                     if (daemon_local->flags.lflag)
2569                     {
2570                         if(!failed && 0 > send(j,dltSerialHeader,sizeof(dltSerialHeader),0))
2571                         {
2572                                 dlt_daemon_close_socket(j, daemon, daemon_local, verbose);
2573                                 failed = 1;
2574                         }
2575                     }
2576                     if(!failed && 0 > send(j,data,length,0))
2577                     {
2578                         dlt_daemon_close_socket(j, daemon, daemon_local, verbose);
2579                         failed = 1;
2580                     }
2581
2582                     DLT_DAEMON_SEM_FREE();
2583
2584                 } /* if */
2585                 else if ((j == daemon_local->fdserial) && (daemon_local->flags.yvalue[0]))
2586                 {
2587                     DLT_DAEMON_SEM_LOCK();
2588
2589                     if (daemon_local->flags.lflag)
2590                     {
2591                         ret=write(j,dltSerialHeader,sizeof(dltSerialHeader));
2592                         if (0 > ret)
2593                         {
2594                                 dlt_log(LOG_ERR, "dlt_daemon_send_ringbuffer_to_client: write(j,dltSerialHeader,sizeof(dltSerialHeader)) failed!\n");
2595                                 DLT_DAEMON_SEM_FREE();
2596                                 return -1;
2597                         }
2598                     }
2599                     ret=write(j,data,length);
2600                     if (0 > ret)
2601                     {
2602                             dlt_log(LOG_ERR, "dlt_daemon_send_ringbuffer_to_client: write(j,data,length) failed!\n");
2603                             DLT_DAEMON_SEM_FREE();
2604                             return -1;
2605                     }
2606                     DLT_DAEMON_SEM_FREE();
2607
2608                 }
2609             } /* if */
2610         } /* for */
2611         length = sizeof(data);
2612     }
2613
2614     return 0;
2615 }
2616
2617 int dlt_daemon_make_periodic (unsigned int period, DltDaemonPeriodicData *info, int verbose)
2618 {
2619     int ret;
2620     unsigned int ns;
2621     unsigned int sec;
2622     int fd;
2623     struct itimerspec itval;
2624
2625     PRINT_FUNCTION_VERBOSE(verbose);
2626
2627     if (info==0)
2628     {
2629         dlt_log(LOG_ERR,"No data pointer passed!\n");
2630         return -1;
2631     }
2632
2633     /* Create the timer */
2634     fd = timerfd_create (CLOCK_MONOTONIC, 0);
2635
2636     info->wakeups_missed = 0;
2637     info->timer_fd = fd;
2638
2639     if (fd == -1)
2640     {
2641         dlt_log(LOG_ERR,"Can't create timer filedescriptor");
2642         return -1;
2643     }
2644
2645     /* Make the timer periodic */
2646     sec = period/1000000;
2647     ns = (period - (sec * 1000000)) * 1000;
2648     itval.it_interval.tv_sec = sec;
2649     itval.it_interval.tv_nsec = ns;
2650     itval.it_value.tv_sec = sec;
2651     itval.it_value.tv_nsec = ns;
2652
2653     ret = timerfd_settime (fd, 0, &itval, NULL);
2654
2655     return ret;
2656 }
2657
2658 void dlt_daemon_wait_period (DltDaemonPeriodicData *info, int verbose)
2659 {
2660     unsigned long long missed;
2661     int ret;
2662
2663     PRINT_FUNCTION_VERBOSE(verbose);
2664
2665     ret = read (info->timer_fd, &missed, sizeof (missed));
2666     if (0 > ret){
2667             dlt_log(LOG_ERR,"dlt_daemon_wait_period: Read failed");
2668     }
2669
2670     if (missed > 0)
2671     {
2672         info->wakeups_missed += (missed - 1);
2673     }
2674 }
2675
2676 int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, int* fd, const char* timer_name)
2677 {
2678     int local_fd;
2679     struct itimerspec l_timer_spec;
2680
2681     if(timer_name == NULL)
2682     {
2683         timer_name = "timer_not_named";
2684     }
2685
2686     if( fd == NULL )
2687     {
2688         snprintf(str, sizeof(str), "<%s> fd is NULL pointer\n", timer_name );
2689         dlt_log(DLT_LOG_ERROR, str);
2690         return -1;
2691     }
2692
2693     if( period_sec > 0 ) {
2694         local_fd = timerfd_create(CLOCK_MONOTONIC, 0);
2695         if( local_fd < 0)
2696         {
2697             snprintf(str, sizeof(str), "<%s> timerfd_create failed: %s\n", timer_name, strerror(errno));
2698             dlt_log(DLT_LOG_ERROR, str);
2699         }
2700
2701         l_timer_spec.it_interval.tv_sec = period_sec;
2702         l_timer_spec.it_interval.tv_nsec = 0;
2703         l_timer_spec.it_value.tv_sec = starts_in;
2704         l_timer_spec.it_value.tv_nsec = 0;
2705
2706         if( timerfd_settime( local_fd, 0, &l_timer_spec, NULL) < 0)
2707         {
2708             snprintf(str, sizeof(str), "<%s> timerfd_settime failed: %s\n", timer_name, strerror(errno));
2709             dlt_log(DLT_LOG_ERROR, str);
2710             local_fd = -1;
2711         }
2712     }
2713     else {
2714         // timer not activated via the service file
2715         snprintf(str, sizeof(str), "<%s> not set: period=0\n", timer_name);
2716         dlt_log(DLT_LOG_INFO, str);
2717         local_fd = -1;
2718     }
2719
2720     // If fd is fully initialized, let's add it to the fd sets
2721     if(local_fd>0)
2722     {
2723         snprintf(str, sizeof(str), "<%s> initialized with %ds timer\n", timer_name, period_sec);
2724         dlt_log(DLT_LOG_INFO, str);
2725
2726         FD_SET(local_fd, &(daemon_local->master));
2727         //FD_SET(local_fd, &(daemon_local->timer_fds));
2728         if (local_fd > daemon_local->fdmax)
2729         {
2730             daemon_local->fdmax = local_fd;
2731         }
2732     }
2733
2734     *fd = local_fd;
2735
2736     return local_fd;
2737 }
2738
2739 void dlt_daemon_send_timingpacket(DltDaemon *daemon, DltDaemonLocal *daemon_local)
2740 {
2741     int j;
2742
2743     if (daemon->timingpackets)
2744     {
2745         for (j = 0; j <= daemon_local->fdmax; j++)
2746         {
2747             /* send to everyone! */
2748             if (FD_ISSET(j, &(daemon_local->master)))
2749             {
2750                 /* except the listener and ourselves */
2751                 if ((j != daemon_local->fp) && (j != daemon_local->sock)
2752 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
2753                         && (j!=daemon_local->timer_wd)
2754 #endif
2755                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion) )
2756                 {
2757                     dlt_log(LOG_DEBUG, "timingpacket\n");
2758                     dlt_daemon_control_message_time(j, daemon, daemon_local->flags.vflag);
2759
2760                 }
2761             }
2762         }
2763     }
2764 }
2765
2766 void dlt_daemon_send_ecuversion(DltDaemon *daemon, DltDaemonLocal *daemon_local)
2767 {
2768     int j;
2769
2770     for (j = 0; j <= daemon_local->fdmax; j++)
2771     {
2772         /* send to everyone! */
2773         if (FD_ISSET(j, &(daemon_local->master)))
2774         {
2775             /* except the listener and ourselves */
2776             if ((j != daemon_local->fp) && (j != daemon_local->sock)
2777 #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
2778                         && (j!=daemon_local->timer_wd)
2779 #endif
2780                         && (j!=daemon_local->timer_timingpacket) && (j!=daemon_local->timer_ecuversion))
2781             {
2782                 dlt_log(LOG_DEBUG, "ecu_version\n");
2783                 if(daemon_local->flags.sendECUSoftwareVersion > 0)
2784                         dlt_daemon_control_get_software_version(j, daemon, daemon_local->flags.vflag);
2785
2786                 if(daemon_local->flags.sendTimezone > 0)
2787                 {
2788                                         // send timezone information
2789                                         time_t t = time(NULL);
2790                                         struct tm lt = {0};
2791                                         localtime_r(&t, &lt);
2792                                         dlt_daemon_control_message_timezone(j,daemon,(int32_t) lt.tm_gmtoff,(uint8_t) lt.tm_isdst,daemon_local->flags.vflag);
2793                 }
2794             }
2795         }
2796     }
2797 }
2798
2799 /* Close connection function */
2800 int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2801 {
2802         close(sock);
2803         FD_CLR(sock, &(daemon_local->master));
2804
2805         if (daemon_local->client_connections)
2806         {
2807                 daemon_local->client_connections--;
2808         }
2809
2810         if(daemon_local->client_connections==0)
2811         {
2812                 /* send new log state to all applications */
2813                 daemon->state = 0;
2814                 dlt_daemon_user_send_all_log_state(daemon,verbose);
2815         }
2816
2817         if (daemon_local->flags.vflag)
2818         {
2819                 sprintf(str, "Connection to client lost, #connections: %d\n",daemon_local->client_connections);
2820                 dlt_log(LOG_INFO, str);
2821         }
2822
2823         dlt_daemon_control_message_connection_info(DLT_DAEMON_STORE_TO_BUFFER,daemon,DLT_CONNECTION_STATUS_DISCONNECTED,"",verbose);
2824 }
2825
2826 /**
2827   \}
2828 */