diff options
Diffstat (limited to 'src/daemon')
-rw-r--r-- | src/daemon/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/daemon/dlt-daemon.c | 509 | ||||
-rw-r--r-- | src/daemon/dlt-daemon.h | 23 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_client.c | 374 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_client.h | 9 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_connection.c | 374 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_connection.h | 51 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_connection_types.h | 64 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_event_handler.c | 373 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_event_handler.h | 57 | ||||
-rw-r--r-- | src/daemon/dlt_daemon_event_handler_types.h | 59 |
11 files changed, 1550 insertions, 345 deletions
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index a3c7439..d7d0d3a 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -20,7 +20,7 @@ if(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) message( STATUS "Added ${systemd_SRCS} to dlt-daemon") endif(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) -set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_common.c dlt_daemon_socket.c dlt_daemon_serial.c dlt_daemon_client.c dlt_daemon_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c) +set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_common.c dlt_daemon_connection.c dlt_daemon_event_handler.c dlt_daemon_socket.c dlt_daemon_serial.c dlt_daemon_client.c dlt_daemon_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c) add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS}) target_link_libraries(dlt-daemon rt ${CMAKE_THREAD_LIBS_INIT}) diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index c733e91..fb9fe22 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -59,6 +59,8 @@ #include "dlt_daemon_serial.h" #include "dlt_daemon_client.h" +#include "dlt_daemon_connection.h" +#include "dlt_daemon_event_handler.h" #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) #include "sd-daemon.h" @@ -441,7 +443,7 @@ int main(int argc, char* argv[]) char version[DLT_DAEMON_TEXTBUFSIZE]; DltDaemonLocal daemon_local; DltDaemon daemon; - int i,back; + int back; /* Command line option handling */ if ((back = option_handling(&daemon_local,argc,argv))<0) @@ -490,6 +492,13 @@ int main(int argc, char* argv[]) } /* --- Daemon init phase 1 end --- */ + if (dlt_daemon_prepare_event_handling(&daemon_local.pEvent)) + { + /* TODO: Perform clean-up */ + dlt_log(LOG_CRIT,"Initialization of event handling failed!\n"); + return -1; + } + /* --- Daemon connection init begin */ if (dlt_daemon_local_connection_init(&daemon, &daemon_local, daemon_local.flags.vflag)==-1) { @@ -518,18 +527,37 @@ int main(int argc, char* argv[]) watchdogTimeoutSeconds = atoi(watchdogUSec)/2000000; } watchdog_trigger_interval = watchdogTimeoutSeconds; - create_timer_fd(&daemon_local, watchdogTimeoutSeconds, watchdogTimeoutSeconds, &daemon_local.timer_wd, "Systemd watchdog"); + create_timer_fd(&daemon_local, + watchdogTimeoutSeconds, + watchdogTimeoutSeconds, + &daemon_local.timer_wd.fd, + DLT_TIMER_SYSTEMD); } #endif // create fd for timer timing packets - create_timer_fd(&daemon_local, 1, 1, &daemon_local.timer_one_s, "Timing packet"); + create_timer_fd(&daemon_local, + 1, + 1, + &daemon_local.timer_one_s.fd, + DLT_TIMER_PACKET); // create fd for timer ecu version - if(daemon_local.flags.sendECUSoftwareVersion > 0 || daemon_local.flags.sendTimezone > 0) + if((daemon_local.flags.sendECUSoftwareVersion > 0) || + (daemon_local.flags.sendTimezone > 0)) + { + create_timer_fd(&daemon_local, + 60, + 60, + &daemon_local.timer_sixty_s.fd, + DLT_TIMER_ECU); + } + + if (dlt_connection_create_remaining(&daemon_local) == -1) { - //dlt_daemon_init_ecuversion(&daemon_local); - create_timer_fd(&daemon_local, 60, 60, &daemon_local.timer_sixty_s, "ECU version"); + /* TODO: Perform clean-up */ + dlt_log(LOG_CRIT,"Fail to create remaining connection handler!\n"); + return -1; } // For offline tracing we still can use the same states @@ -542,132 +570,14 @@ int main(int argc, char* argv[]) dlt_daemon_log_internal(&daemon, &daemon_local, "Daemon launched. Starting to output traces...", daemon_local.flags.vflag); - while (1) + /* Even handling loop. */ + while (back >= 0) { + back = dlt_daemon_handle_event(&daemon_local.pEvent, + &daemon, + &daemon_local); + } - /* wait for events from all FIFO and sockets */ - daemon_local.read_fds = daemon_local.master; - if (select(daemon_local.fdmax+1, &(daemon_local.read_fds), NULL, NULL, NULL) == -1) - { - int error = errno; - /* retry if SIGINT was received, else error out */ - if ( error != EINTR ) { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"select() failed: %s\n", strerror(error) ); - dlt_log(LOG_ERR, str); - return -1; - } - } /* if */ - - /* run through the existing FIFO and sockets to check for events */ - for (i = 0; i <= daemon_local.fdmax; i++) - { - if (FD_ISSET(i, &(daemon_local.read_fds))) - { - if (i == daemon_local.sock) - { - /* event from TCP server socket, new connection */ - if (dlt_daemon_process_client_connect(&daemon, &daemon_local, daemon_local.flags.vflag)==-1) - { - dlt_log(LOG_ERR,"Connect to dlt client failed!\n"); - return -1; - } - } - else if (i == daemon_local.fp) - { - /* event from the FIFO happened */ - if (dlt_daemon_process_user_messages(&daemon, &daemon_local, daemon_local.flags.vflag)==-1) - { - dlt_log(LOG_WARNING,"Processing of messages from user connection failed!\n"); - return -1; - } - } - else if ((i == daemon_local.fdserial) && (daemon_local.flags.yvalue[0])) - { - /* event from serial connection to client received */ - if (dlt_daemon_process_client_messages_serial(&daemon, &daemon_local, daemon_local.flags.vflag)==-1) - { - dlt_log(LOG_WARNING,"Processing of messages from serial connection failed!\n"); - return -1; - } - } -#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE - else if (i == daemon_local.timer_wd) - { - uint64_t expir=0; - ssize_t res = read(daemon_local.timer_wd, &expir, sizeof(expir)); - if(res < 0) { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"Failed to read timer_wd; %s\n", strerror(errno) ); - dlt_log(LOG_WARNING, str); - // Activity received on timer_wd, but unable to read the fd: - // let's go on sending notification - } - - dlt_log(LOG_DEBUG, "Timer watchdog\n"); - - if(sd_notify(0, "WATCHDOG=1") < 0) - { - dlt_log(LOG_WARNING, "Could not reset systemd watchdog\n"); - } - } -#endif - else if (i == daemon_local.timer_one_s) - { - uint64_t expir=0; - ssize_t res = read(daemon_local.timer_one_s, &expir, sizeof(expir)); - if(res < 0) { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"Failed to read timer_timingpacket; %s\n", strerror(errno) ); - dlt_log(LOG_WARNING, str); - // Activity received on timer_wd, but unable to read the fd: - // let's go on sending notification - } - if(daemon.state == DLT_DAEMON_STATE_SEND_BUFFER || daemon.state == DLT_DAEMON_STATE_BUFFER_FULL) - { - if (dlt_daemon_send_ringbuffer_to_client(&daemon, &daemon_local, daemon_local.flags.vflag)) - { - dlt_log(LOG_DEBUG,"Can't send contents of ringbuffer to clients\n"); - } - } - if (daemon.timingpackets && daemon.state == DLT_DAEMON_STATE_SEND_DIRECT) - { - dlt_daemon_control_message_time(DLT_DAEMON_SEND_TO_ALL, &daemon, &daemon_local, daemon_local.flags.vflag); - } - dlt_log(LOG_DEBUG, "Timer timingpacket\n"); - - } - - else if (i == daemon_local.timer_sixty_s) - { - uint64_t expir=0; - ssize_t res = read(daemon_local.timer_sixty_s, &expir, sizeof(expir)); - if(res < 0) { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"Failed to read timer_ecuversion; %s\n", strerror(errno) ); - dlt_log(LOG_WARNING, str); - // Activity received on timer_wd, but unable to read the fd: - // let's go on sending notification - } - if(daemon_local.flags.sendECUSoftwareVersion > 0) - dlt_daemon_control_get_software_version(DLT_DAEMON_SEND_TO_ALL, &daemon,&daemon_local, daemon_local.flags.vflag); - - if(daemon_local.flags.sendTimezone > 0) - { - dlt_daemon_control_message_timezone(DLT_DAEMON_SEND_TO_ALL,&daemon,&daemon_local,daemon_local.flags.vflag); - } - dlt_log(LOG_DEBUG, "Timer ecuversion\n"); - - } - else - { - /* event from tcp connection to client received */ - daemon_local.receiverSock.fd = i; - if (dlt_daemon_process_client_messages(&daemon, &daemon_local, daemon_local.flags.vflag)==-1) - { - dlt_log(LOG_WARNING,"Processing of messages from client connection failed!\n"); - return -1; - } - } /* else */ - } /* if */ - } /* for */ - } /* while */ dlt_daemon_log_internal(&daemon, &daemon_local, "Exiting Daemon...", daemon_local.flags.vflag); @@ -870,18 +780,81 @@ int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, in return 0; } -int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) +static int dlt_daemon_init_serial(DltDaemonLocal *daemon_local) { - int ret; + if (!daemon_local->flags.yvalue[0]) + { + /* Nothing to do here. */ + daemon_local->fdserial = -1; + return 0; + } - PRINT_FUNCTION_VERBOSE(verbose); + /* create and open serial connection from/to client */ + /* open serial connection */ + daemon_local->fdserial = open(daemon_local->flags.yvalue, O_RDWR); + if (daemon_local->fdserial < 0) + { + snprintf(str, + DLT_DAEMON_TEXTBUFSIZE, + "Failed to open serial device %s\n", + daemon_local->flags.yvalue); + dlt_log(LOG_ERR, str); - if ((daemon==0) || (daemon_local==0)) + daemon_local->flags.yvalue[0] = 0; + return -1; + } + + if (isatty(daemon_local->fdserial)) { - dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_connection_init()\n"); + int speed = DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE; + + if (daemon_local->flags.bvalue[0]) + { + speed = atoi(daemon_local->flags.bvalue); + } + + daemon_local->baudrate = dlt_convert_serial_speed(speed); + + if (dlt_setup_serial(daemon_local->fdserial, + daemon_local->baudrate) < 0) + { + close(daemon_local->fdserial); + daemon_local->flags.yvalue[0] = 0; + + snprintf(str, + DLT_DAEMON_TEXTBUFSIZE, + "Failed to configure serial device %s (%s) \n", + daemon_local->flags.yvalue, + strerror(errno)); + dlt_log(LOG_ERR, str); + + return -1; + } + + if (daemon_local->flags.vflag) + { + dlt_log(LOG_DEBUG, "Serial init done\n"); + } + } + else + { + close(daemon_local->fdserial); + fprintf(stderr, + "Device is not a serial device, device = %s (%s) \n", + daemon_local->flags.yvalue, + strerror(errno)); + daemon_local->flags.yvalue[0] = 0; return -1; } + return 0; +} + +static int dlt_daemon_init_fifo(DltDaemonLocal *daemon_local) +{ + int ret; + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + /* open named pipe(FIFO) to receive DLT messages from users */ umask(0); @@ -890,93 +863,77 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, DltDaemonLocal *daemon_l unlink(tmpFifo); ret=mkfifo(tmpFifo, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); - if (ret==-1) + if (ret == -1) { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"FIFO user %s cannot be created (%s)!\n",tmpFifo, strerror(errno)); - dlt_log(LOG_WARNING, str); + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "FIFO user %s cannot be created (%s)!\n", + tmpFifo, + strerror(errno)); + dlt_log(LOG_WARNING, local_str); return -1; } /* if */ daemon_local->fp = open(tmpFifo, O_RDWR); - if (daemon_local->fp==-1) + if (daemon_local->fp == -1) { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"FIFO user %s cannot be opened (%s)!\n",tmpFifo, strerror(errno)); - dlt_log(LOG_WARNING, str); + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "FIFO user %s cannot be opened (%s)!\n", + tmpFifo, + strerror(errno)); + dlt_log(LOG_WARNING, local_str); return -1; } /* if */ - /* create and open socket to receive incoming connections from client */ - if(dlt_daemon_socket_open(&(daemon_local->sock), daemon_local->flags.port)) - { - return -1; - } + /* Early init, to be able to catch client (app) connections + * as soon as possible. This registration is automatically ignored + * during next execution. + */ + return dlt_connection_create(daemon_local, + &daemon_local->pEvent, + daemon_local->fp, + EPOLLIN, + DLT_CONNECTION_APP_MSG); +} - /* prepare usage of select(), add FIFO and receiving socket */ - FD_ZERO(&(daemon_local->master)); - FD_ZERO(&(daemon_local->read_fds)); - FD_SET(daemon_local->sock, &(daemon_local->master)); +int dlt_daemon_local_connection_init(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int verbose) +{ + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + PRINT_FUNCTION_VERBOSE(verbose); - daemon_local->fdmax = daemon_local->sock; + if ((daemon == NULL) || (daemon_local == NULL)) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: Invalid function parameters\n", + __func__); - FD_SET(daemon_local->fp, &(daemon_local->master)); + dlt_log(LOG_ERR, local_str); + return -1; + } - if (daemon_local->fp > daemon_local->fdmax) + if (dlt_daemon_init_fifo(daemon_local)) { - daemon_local->fdmax = daemon_local->fp; + dlt_log(LOG_ERR, "Unable to initialize fifo.\n"); + return -1; } - if (daemon_local->flags.yvalue[0]) + /* create and open socket to receive incoming connections from client */ + daemon_local->client_connections = 0; + if(dlt_daemon_socket_open(&(daemon_local->sock),daemon_local->flags.port)) { - /* create and open serial connection from/to client */ - /* open serial connection */ - daemon_local->fdserial=open(daemon_local->flags.yvalue,O_RDWR); - if (daemon_local->fdserial<0) - { - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"Failed to open serial device %s\n", daemon_local->flags.yvalue); - daemon_local->flags.yvalue[0] = 0; - dlt_log(LOG_ERR, str); - return -1; - } - - if (isatty(daemon_local->fdserial)) - { - if (daemon_local->flags.bvalue[0]) - { - daemon_local->baudrate = dlt_convert_serial_speed(atoi(daemon_local->flags.bvalue)); - } - else - { - daemon_local->baudrate = dlt_convert_serial_speed(DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE); - } - - if (dlt_setup_serial(daemon_local->fdserial,daemon_local->baudrate) < DLT_RETURN_OK) - { - close(daemon_local->fdserial); - snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"Failed to configure serial device %s (%s) \n", daemon_local->flags.yvalue, strerror(errno)); - daemon_local->flags.yvalue[0] = 0; - dlt_log(LOG_ERR, str); - return -1; - } - - FD_SET(daemon_local->fdserial, &(daemon_local->master)); - - if (daemon_local->fdserial > daemon_local->fdmax) - { - daemon_local->fdmax = daemon_local->fdserial; - } + dlt_log(LOG_ERR,"Could not initialize main socket.\n"); + return -1; + } - if (daemon_local->flags.vflag) - { - dlt_log(LOG_DEBUG, "Serial init done\n"); - } - } - else - { - close(daemon_local->fdserial); - fprintf(stderr,"Device is not a serial device, device = %s (%s) \n", daemon_local->flags.yvalue, strerror(errno)); - daemon_local->flags.yvalue[0] = 0; - return -1; - } + /* Init serial */ + if (dlt_daemon_init_serial(daemon_local) < 0) + { + dlt_log(LOG_ERR,"Could not initialize daemon data\n"); + return -1; } return 0; @@ -1096,6 +1053,8 @@ void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, i /* Try to delete lock file, ignore result of unlink() */ unlink(DLT_DAEMON_LOCK_FILE); + + dlt_event_handler_cleanup_connections(&daemon_local->pEvent); } void dlt_daemon_signal_handler(int sig) @@ -1359,20 +1318,17 @@ int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_ if (setsockopt (in_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout_send, sizeof(timeout_send)) < 0) dlt_log(LOG_WARNING, "setsockopt failed\n"); - /* Set to non blocking mode */ - //flags = fcntl(in_sock, F_GETFL, 0); - //fcntl(in_sock, F_SETFL, flags | O_NONBLOCK); - - //snprintf(str,DLT_DAEMON_TEXTBUFSIZE,"Client Connection from %s\n", inet_ntoa(cli.sin_addr)); - //dlt_log(str); - FD_SET(in_sock, &(daemon_local->master)); /* add to master set */ - if (in_sock > daemon_local->fdmax) + if (dlt_connection_create(daemon_local, + &daemon_local->pEvent, + in_sock, + EPOLLIN, + DLT_CONNECTION_CLIENT_MSG_TCP)) { - /* keep track of the maximum */ - daemon_local->fdmax = in_sock; - } /* if */ + dlt_log(LOG_ERR, "Failed to register new client. \n"); + /* TODO: Perform clean-up */ + return -1; + } - daemon_local->client_connections++; if (daemon_local->flags.vflag) { snprintf(str,DLT_DAEMON_TEXTBUFSIZE, "New connection to client established, #connections: %d\n",daemon_local->client_connections); @@ -1429,9 +1385,15 @@ int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon if (dlt_receiver_receive_socket(&(daemon_local->receiverSock))<=0) { - dlt_daemon_close_socket(daemon_local->receiverSock.fd, daemon, daemon_local, verbose); + dlt_daemon_close_socket(daemon_local->receiverSock.fd, + daemon, + daemon_local, + verbose); daemon_local->receiverSock.fd = -1; - /* check: return 0; */ + /* FIXME: Why the hell do we need to close the socket + * on control message reception ?? + */ + //return 0; } /* Process all received messages */ @@ -2407,55 +2369,11 @@ int dlt_daemon_process_user_message_log_shm(DltDaemon *daemon, DltDaemonLocal *d } /* look if TCP connection to client is available */ - for (j = 0;((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) && (j <= daemon_local->fdmax); j++) + if((daemon->mode == DLT_USER_MODE_EXTERNAL) || + (daemon->mode == DLT_USER_MODE_BOTH)) { - /* send to everyone! */ - if (FD_ISSET(j, &(daemon_local->master))) - { - /* except the listener and ourselves */ - if (daemon_local->flags.yvalue[0]) - { - third_value = daemon_local->fdserial; - } - else - { - third_value = daemon_local->sock; - } - - if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != third_value)) - { - DLT_DAEMON_SEM_LOCK(); - - if (daemon_local->flags.lflag) - { - send(j,dltSerialHeader,sizeof(dltSerialHeader),0); - } - - send(j,daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),daemon_local->msg.headersize-sizeof(DltStorageHeader),0); - send(j,daemon_local->msg.databuffer,daemon_local->msg.datasize,0); - - DLT_DAEMON_SEM_FREE(); - - sent=1; - } /* if */ - else if ((j == daemon_local->fdserial) && (daemon_local->flags.yvalue[0])) - { - DLT_DAEMON_SEM_LOCK(); - - if (daemon_local->flags.lflag) - { - ret=write(j,dltSerialHeader,sizeof(dltSerialHeader)); - } - - ret=write(j,daemon_local->msg.headerbuffer+sizeof(DltStorageHeader),daemon_local->msg.headersize-sizeof(DltStorageHeader)); - ret=write(j,daemon_local->msg.databuffer,daemon_local->msg.datasize); - - DLT_DAEMON_SEM_FREE(); - - sent=1; - } - } /* if */ - } /* for */ + sent = dlt_daemon_client_send_all(daemon, daemon_local, verbose); + } /* Message was not sent to client, so store it in client ringbuffer */ if (sent==1 || (daemon->mode == DLT_USER_MODE_OFF)) @@ -2679,16 +2597,36 @@ int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daem return DLT_DAEMON_ERROR_OK; } -int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, int* fd, const char* timer_name) +static char dlt_timer_names[DLT_TIMER_UNKNOWN + 1][32] = { + [DLT_TIMER_PACKET] = "Timing packet", + [DLT_TIMER_ECU] = "ECU version", +#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE + [DLT_TIMER_SYSTEMD] = "Systemd watchdog", +#endif + [DLT_TIMER_UNKNOWN] = "Unknown timer" +}; + +int create_timer_fd(DltDaemonLocal *daemon_local, + int period_sec, + int starts_in, + int* fd, + DltTimers timer_id) { int local_fd = -1; struct itimerspec l_timer_spec; + char *timer_name = dlt_timer_names[timer_id]; if(timer_name == NULL) { timer_name = "timer_not_named"; } + if(daemon_local == NULL) + { + dlt_log(DLT_LOG_ERROR, "Daemaon local structure is NULL"); + return -1; + } + if( fd == NULL ) { snprintf(str, sizeof(str), "<%s> fd is NULL pointer\n", timer_name ); @@ -2725,18 +2663,17 @@ int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, local_fd = -1; } - // If fd is fully initialized, let's add it to the fd sets - if(local_fd>0) + /* If fully initialized we are done. + * Event handling registration is done later on with other connections. + */ + if(local_fd > 0) { - snprintf(str, sizeof(str), "<%s> initialized with %ds timer\n", timer_name, period_sec); + snprintf(str, + sizeof(str), + "<%s> initialized with %d timer\n", + timer_name, + period_sec); dlt_log(LOG_INFO, str); - - FD_SET(local_fd, &(daemon_local->master)); - //FD_SET(local_fd, &(daemon_local->timer_fds)); - if (local_fd > daemon_local->fdmax) - { - daemon_local->fdmax = local_fd; - } } *fd = local_fd; @@ -2747,16 +2684,22 @@ int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, /* Close connection function */ int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose) { - dlt_daemon_socket_close(sock); - - FD_CLR(sock, &(daemon_local->master)); + PRINT_FUNCTION_VERBOSE(verbose); - if (daemon_local->client_connections) + if((daemon_local == NULL)|| (daemon == NULL)) { - daemon_local->client_connections--; + dlt_log(LOG_ERR, "dlt_daemon_close_socket: Invalid input parmeters\n"); + return -1; } - if(daemon_local->client_connections==0) + /* Closure is done while unregistering has for any connection */ + dlt_event_handler_unregister_connection(&daemon_local->pEvent, + daemon_local, + sock, + DLT_CONNECTION_CLIENT_MSG_TCP); + + + if(daemon_local->client_connections==0) { /* send new log state to all applications */ daemon->connectionState = 0; diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h index 25431d8..0096ba6 100644 --- a/src/daemon/dlt-daemon.h +++ b/src/daemon/dlt-daemon.h @@ -74,7 +74,7 @@ #include "dlt_daemon_common.h" #include "dlt_user_shared.h" #include "dlt_user_shared_cfg.h" - +#include "dlt_daemon_event_handler_types.h" #include <dlt_offline_trace.h> #include <sys/time.h> @@ -126,11 +126,8 @@ typedef struct int fp; /**< handle for own fifo */ int sock; /**< handle for tcp connection to client */ int fdserial; /**< handle for serial connection */ - int fdmax; /**< highest number of used handles */ - fd_set master; /**< master set of handles */ - fd_set read_fds; /**< read set of handles */ DltFile file; /**< struct for file access */ - //int ohandle; /**< handle to output file */ + DltEventHandler pEvent; /**< struct for message producer event handling */ DltMessage msg; /**< one dlt message */ DltReceiver receiver; /**< receiver for fifo connection */ DltReceiver receiverSock; /**< receiver for socket connection */ @@ -141,15 +138,15 @@ typedef struct DltShm dlt_shm; /**< Shared memory handling */ #endif DltOfflineTrace offlineTrace; /**< Offline trace handling */ -#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) - int timer_wd; /** file descriptor for watchdog timer */ -#endif int timeoutOnSend; unsigned long RingbufferMinSize; unsigned long RingbufferMaxSize; unsigned long RingbufferStepSize; - int timer_one_s; - int timer_sixty_s; + DltReceiver timer_one_s; + DltReceiver timer_sixty_s; +#if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) + DltReceiver timer_wd; /**< file descriptor for watchdog timer */ +#endif } DltDaemonLocal; typedef struct @@ -181,11 +178,13 @@ int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_ void dlt_daemon_daemonize(int verbose); void dlt_daemon_signal_handler(int sig); - int dlt_daemon_process_client_connect(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_process_client_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_process_client_messages_serial(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_process_user_messages(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); +int dlt_daemon_process_one_s_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); +int dlt_daemon_process_sixty_s_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); +int dlt_daemon_process_systemd_timer(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_process_user_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); @@ -208,7 +207,7 @@ void dlt_daemon_ecu_version_thread(void *ptr); void dlt_daemon_systemd_watchdog_thread(void *ptr); #endif -int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, int* fd, const char* timer_name); +int create_timer_fd(DltDaemonLocal *daemon_local, int period_sec, int starts_in, int* fd, DltTimers timer); int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index e1cf841..89b5489 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -59,15 +59,153 @@ #include "dlt_daemon_serial.h" #include "dlt_daemon_client.h" +#include "dlt_daemon_connection.h" #include "dlt_daemon_offline_logstorage.h" /** Global text output buffer, mainly used for creation of error/warning strings */ static char str[DLT_DAEMON_TEXTBUFSIZE]; +/** @brief Sends up to 2 messages to all the clients. + * + * Runs through the client list and sends the messages to them. If the message + * transfer fails and the connection is a socket connection, the socket is closed. + * Takes and release dlt_daemon_mutex. + * + * @param daemon Daemon structure needed for socket closure. + * @param daemon_local Daemon local structure + * @param data1 The first message to be sent. + * @param size1 The size of the first message. + * @param data2 The second message to be send. + * @param size2 The second message size. + * @param verbose Needed for socket closure. + * + * @return The amount of data transfered. + */ +static int dlt_daemon_client_send_all_multiple(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + void* data1, + int size1, + void* data2, + int size2, + int verbose) +{ + int j, sent = 0; + DltConnection* temp = NULL; + int type_mask = + (DLT_CON_MASK_CLIENT_MSG_TCP | DLT_CON_MASK_CLIENT_MSG_SERIAL); + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + + if ((daemon == NULL) || (daemon_local == NULL)) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: Invalid parameters\n", + __func__); + dlt_log(LOG_ERR, local_str); + return 0; + } + + temp = daemon_local->pEvent.connections; + temp = dlt_connection_get_next(temp, type_mask); + + /* FIXME: the lock shall include the for loop as data + * can be affect between each iteration, but + * dlt_daemon_close_socket may call us too ... + */ + for (j = 0; ((j < daemon_local->client_connections) && (temp != NULL)); j++) + { + int ret = 0; + DLT_DAEMON_SEM_LOCK(); + ret = dlt_connection_send_multiple(temp, + data1, + size1, + data2, + size2, + daemon->sendserialheader); + DLT_DAEMON_SEM_FREE(); + + if((ret != DLT_DAEMON_ERROR_OK) && + DLT_CONNECTION_CLIENT_MSG_TCP == temp->type) + { + dlt_daemon_close_socket(temp->fd, + daemon, + daemon_local, + verbose); + } + + if (ret != DLT_DAEMON_ERROR_OK) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: send dlt message failed\n", + __func__); + dlt_log(LOG_WARNING, local_str); + } + else + { + /* If sent to at least one client, + * then do not store in ring buffer + */ + sent = 1; + } + + temp = dlt_connection_get_next(temp->next, type_mask); + } /* for */ + + return sent; +} + +/** @brief Send out message to all the clients. + * + * @param daemon pointer to dlt daemon structure + * @param daemon_local pointer to dlt daemon local structure + * @param verbose if set to true verbose information is printed out. + * + * @return 1 if transfer succeed, 0 otherwise. + */ +int dlt_daemon_client_send_all(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int verbose) +{ + void *msg1, *msg2; + int msg1_sz, msg2_sz; + int ret = 0; + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + + if ((daemon == NULL) || (daemon_local == NULL)) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: Invalid parameters\n", + __func__); + dlt_log(LOG_ERR, local_str); + return 0; + } + + /* FIXME: the lock shall include the for loop but + * dlt_daemon_close_socket may call us too ... + */ + DLT_DAEMON_SEM_LOCK(); + msg1 = daemon_local->msg.headerbuffer + sizeof(DltStorageHeader); + msg1_sz = daemon_local->msg.headersize - sizeof(DltStorageHeader); + msg2 = daemon_local->msg.databuffer; + msg2_sz = daemon_local->msg.datasize; + DLT_DAEMON_SEM_FREE(); + + ret = dlt_daemon_client_send_all_multiple(daemon, + daemon_local, + msg1, + msg1_sz, + msg2, + msg2_sz, + verbose); + + return ret; +} + int dlt_daemon_client_send(int sock,DltDaemon *daemon,DltDaemonLocal *daemon_local,void* storage_header,int storage_header_size,void* data1,int size1,void* data2,int size2,int verbose) { - int ret; - int j; + int sent,ret; if (sock!=DLT_DAEMON_SEND_TO_ALL && sock!=DLT_DAEMON_SEND_FORCE) { @@ -135,58 +273,20 @@ int dlt_daemon_client_send(int sock,DltDaemon *daemon,DltDaemonLocal *daemon_loc { if ((sock==DLT_DAEMON_SEND_FORCE) || (daemon->state == DLT_DAEMON_STATE_SEND_DIRECT)) { - int sent = 0; - /* look if TCP connection to client is available */ - for (j = 0; j <= daemon_local->fdmax; j++) - { - /* send to everyone! */ - if (FD_ISSET(j, &(daemon_local->master))) - { - if ((j != daemon_local->fp) && (j != daemon_local->sock) && (j != daemon_local->sock) - #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE - && (j!=daemon_local->timer_wd) - #endif - && (j!=daemon_local->timer_one_s) && (j!=daemon_local->timer_sixty_s)) - { - /* Send message */ - if (isatty(j)) - { - DLT_DAEMON_SEM_LOCK(); - - if((ret=dlt_daemon_serial_send(j,data1,size1,data2,size2,daemon->sendserialheader))) - { - DLT_DAEMON_SEM_FREE(); - dlt_log(LOG_WARNING,"dlt_daemon_client_send: serial send dlt message failed\n"); - return ret; - } - - DLT_DAEMON_SEM_FREE(); - } - else - { - DLT_DAEMON_SEM_LOCK(); - - if((ret=dlt_daemon_socket_send(j,data1,size1,data2,size2,daemon->sendserialheader))) - { - DLT_DAEMON_SEM_FREE(); - dlt_log(LOG_WARNING,"dlt_daemon_client_send: socket send dlt message failed\n"); - dlt_daemon_close_socket(j, daemon, daemon_local, verbose); - return ret; - } - - DLT_DAEMON_SEM_FREE(); - } - sent=1; - - } - } - } + sent = dlt_daemon_client_send_all_multiple(daemon, + daemon_local, + data1, + size1, + data2, + size2, + verbose); + if((sock==DLT_DAEMON_SEND_FORCE) && !sent) { return DLT_DAEMON_ERROR_SEND_FAILED; } } - } + } /* Message was not sent to client, so store it in client ringbuffer */ if ((sock!=DLT_DAEMON_SEND_FORCE) && (daemon->state == DLT_DAEMON_STATE_BUFFER || daemon->state == DLT_DAEMON_STATE_SEND_BUFFER || daemon->state == DLT_DAEMON_STATE_BUFFER_FULL)) @@ -1639,6 +1739,182 @@ void dlt_daemon_control_message_time(int sock, DltDaemon *daemon, DltDaemonLocal dlt_message_free(&msg,0); } +int dlt_daemon_process_one_s_timer(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int verbose) +{ + uint64_t expir = 0; + ssize_t res = 0; + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + + PRINT_FUNCTION_VERBOSE(verbose); + + if((daemon_local == NULL) || (daemon == NULL)) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: invalid parameters", + __func__); + dlt_log(LOG_ERR, local_str); + return -1; + } + + res = read(daemon_local->timer_one_s.fd, &expir, sizeof(expir)); + + if(res < 0) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: Fail to read timer (%s)\n", __func__, strerror(errno)); + dlt_log(LOG_WARNING, str); + /* Activity received on timer_wd, but unable to read the fd: + let's go on sending notification */ + } + + if((daemon->state == DLT_DAEMON_STATE_SEND_BUFFER) || + (daemon->state == DLT_DAEMON_STATE_BUFFER_FULL)) + { + if (dlt_daemon_send_ringbuffer_to_client(daemon, + daemon_local, + daemon_local->flags.vflag)) + { + dlt_log(LOG_DEBUG, + "Can't send contents of ring buffer to clients\n"); + } + } + + if((daemon->timingpackets) && + (daemon->state == DLT_DAEMON_STATE_SEND_DIRECT)) + { + dlt_daemon_control_message_time(DLT_DAEMON_SEND_TO_ALL, + daemon, + daemon_local, + daemon_local->flags.vflag); + } + + dlt_log(LOG_DEBUG, "Timer timingpacket\n"); + + return 0; +} + +int dlt_daemon_process_sixty_s_timer(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int verbose) +{ + uint64_t expir = 0; + ssize_t res = 0; + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + + PRINT_FUNCTION_VERBOSE(verbose); + + if((daemon_local == NULL) || (daemon == NULL)) + { + snprintf(str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: invalid parameters", + __func__); + dlt_log(LOG_ERR, str); + return -1; + } + + res = read(daemon_local->timer_sixty_s.fd, &expir, sizeof(expir)); + + if(res < 0) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: Fail to read timer (%s)\n", __func__, strerror(errno)); + dlt_log(LOG_WARNING, str); + /* Activity received on timer_wd, but unable to read the fd: + let's go on sending notification */ + } + + if(daemon_local->flags.sendECUSoftwareVersion > 0) + { + dlt_daemon_control_get_software_version(DLT_DAEMON_SEND_TO_ALL, + daemon, + daemon_local, + daemon_local->flags.vflag); + } + + if(daemon_local->flags.sendTimezone > 0) + { + // send timezone information + time_t t = time(NULL); + struct tm lt; + + /*Added memset to avoid compiler warning for near initialization */ + memset((void*)<, 0, sizeof(lt)); + localtime_r(&t, <); + + dlt_daemon_control_message_timezone(DLT_DAEMON_SEND_TO_ALL, + daemon, + daemon_local, + daemon_local->flags.vflag); + } + + dlt_log(LOG_DEBUG, "Timer ecuversion\n"); + + return 0; +} + +#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE +int dlt_daemon_process_systemd_timer(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int verbose) +{ + uint64_t expir = 0; + ssize_t res = -1; + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + + PRINT_FUNCTION_VERBOSE(verbose); + + if((daemon_local == NULL) || (daemon == NULL)) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "%s: invalid parameters", + __func__); + dlt_log(LOG_ERR, local_str); + return res; + } + + res = read(daemon_local->timer_wd.fd, &expir, sizeof(expir)); + + if(res < 0) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "Failed to read timer_wd; %s\n", + strerror(errno)); + dlt_log(LOG_WARNING, local_str); + /* Activity received on timer_wd, but unable to read the fd: + let's go on sending notification */ + } + + if(sd_notify(0, "WATCHDOG=1") < 0) + { + dlt_log(LOG_CRIT, "Could not reset systemd watchdog\n"); + } + + dlt_log(LOG_DEBUG, "Timer watchdog\n"); + + return 0; +} +#else +int dlt_daemon_process_systemd_timer(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int verbose) +{ + (void)daemon; + (void)daemon_local; + (void)verbose; + + dlt_log(LOG_DEBUG, "Timer watchdog not enabled\n"); + + return -1; +} +#endif void dlt_daemon_control_service_logstorage(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) { diff --git a/src/daemon/dlt_daemon_client.h b/src/daemon/dlt_daemon_client.h index c7ec9e9..4b5ebcb 100644 --- a/src/daemon/dlt_daemon_client.h +++ b/src/daemon/dlt_daemon_client.h @@ -67,6 +67,15 @@ #include <sys/time.h> /** + * Send out message to all the clients. + * @param daemon pointer to dlt daemon structure + * @param daemon_local pointer to dlt daemon local structure + * @param verbose if set to true verbose information is printed out. + * @return 1 if transfer succeed, 0 otherwise. + */ +int dlt_daemon_client_send_all(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose); + +/** * Send out message to client or store message in offline trace. * @param sock connection handle used for sending response * @param daemon pointer to dlt daemon structure diff --git a/src/daemon/dlt_daemon_connection.c b/src/daemon/dlt_daemon_connection.c new file mode 100644 index 0000000..0eee668 --- /dev/null +++ b/src/daemon/dlt_daemon_connection.c @@ -0,0 +1,374 @@ +/* + * @licence app begin@ + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * + * This Source Code Form is subject to the terms of the + * Mozilla Public License (MPL), v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/*! + * \author + * Frederic Berat <fberat@de.adit-jv.com> + * + * \copyright Copyright © 2015 Advanced Driver Information Technology. \n + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_connection.c + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/socket.h> +#include <sys/syslog.h> +#include <sys/types.h> + +#include "dlt_daemon_connection_types.h" +#include "dlt_daemon_connection.h" +#include "dlt_daemon_event_handler_types.h" +#include "dlt_daemon_event_handler.h" +#include "dlt-daemon.h" +#include "dlt-daemon_cfg.h" +#include "dlt_daemon_common.h" +#include "dlt_common.h" + +/** @brief Generic sending function. + * + * We manage different type of connection which have similar send/write + * functions. We can then abstract the data transfer using this function, + * moreover as we often transfer data to different kind of connection + * within the same loop. + * + * @param conn The connection structure. + * @param msg The message buffer to be sent + * @param msg_size The length of the message to be sent + * + * @return The amount of bytes send on success, -1 otherwise. + * errno is appropriately set. + */ +static int dlt_connection_send(DltConnection *conn, + void *msg, + size_t msg_size) +{ + DltConnectionType type = DLT_CONNECTION_TYPE_MAX; + + if (conn != NULL) + { + type = conn->type; + } + + switch (type) + { + case DLT_CONNECTION_CLIENT_MSG_SERIAL: + return write(conn->fd, msg, msg_size); + case DLT_CONNECTION_CLIENT_MSG_TCP: + return send(conn->fd, msg, msg_size, 0); + default: + return -1; + } +} + +/** @brief Send up to two messages through a connection. + * + * We often need to send 2 messages through a specific connection, plus + * the serial header. This function groups these different calls. + * + * @param con The connection to send the messages through. + * @param data1 The first message to be sent. + * @param size1 The size of the first message. + * @param data2 The second message to be send. + * @param size2 The second message size. + * @param sendserialheader Whether we need or not to send the serial header. + * + * @return DLT_DAEMON_ERROR_OK on success, -1 otherwise. errno is properly set. + */ +int dlt_connection_send_multiple(DltConnection *con, + void *data1, + int size1, + void *data2, + int size2, + int sendserialheader) +{ + int ret = 0; + + if (con == NULL) + { + return -1; + } + + if (sendserialheader) + { + ret = dlt_connection_send(con, + (void *)dltSerialHeader, + sizeof(dltSerialHeader)); + } + + if ((data1 != NULL) && (ret >= 0)) + { + ret = dlt_connection_send(con, data1, size1); + } + + if ((data2 != NULL) && (ret >= 0)) + { + ret = dlt_connection_send(con, data2, size2); + } + + if (ret >=0) + { + ret = DLT_DAEMON_ERROR_OK; + } + + return ret; +} + +/** @brief Get the next connection filtered with a type mask. + * + * In some cases we need the next connection available of a specific type or + * specific different types. This function returns the next available connection + * that is of one of the types included in the mask. The current connection can + * be returned. + * + * @param current The current connection pointer. + * @param type_mask A bit mask representing the connection types to be filtered. + * + * @return The next available connection of the considered types or NULL. + */ +DltConnection *dlt_connection_get_next(DltConnection *current, int type_mask) +{ + while (current && !((1 << current->type) & type_mask)) + { + current = current->next; + } + + return current; +} + +/** @brief Get the receiver structure associated to a connection. + * + * The receiver structure is sometimes needed while handling the event. + * This behavior is mainly due to the fact that it's not intended to modify + * the whole design of the daemon while implementing the new event handling. + * Based on the connection type provided, this function returns the pointer + * to the DltReceiver structure corresponding. + * + * @param dameon_local Structure where to take the DltReceiver pointer from. + * @param type Type of the connection. + * + * @return DltReceiver structure or NULL if none corresponds to the type. + */ +static DltReceiver *dlt_connection_get_receiver(DltDaemonLocal *daemon_local, + DltConnectionType type) +{ + DltReceiver *ret = NULL; + + switch (type) + { + case DLT_CONNECTION_CLIENT_CONNECT: + /* FALL THROUGH */ + /* There must be the same structure for this case */ + case DLT_CONNECTION_CLIENT_MSG_TCP: + ret = &daemon_local->receiverSock; + break; + case DLT_CONNECTION_CLIENT_MSG_SERIAL: + ret = &daemon_local->receiverSerial; + break; + case DLT_CONNECTION_APP_MSG: + ret = &daemon_local->receiver; + break; + case DLT_CONNECTION_ONE_S_TIMER: + ret = &daemon_local->timer_one_s; + break; + case DLT_CONNECTION_SIXTY_S_TIMER: + ret = &daemon_local->timer_sixty_s; + break; +#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE + case DLT_CONNECTION_SYSTEMD_TIMER: + ret = &daemon_local->timer_wd; + break; +#endif + default: + ret = NULL; + } + + return ret; +} + +/** @brief Get the callback from a specific connection. + * + * The callback retrieved that way is used to handle event for this connection. + * It as been chosen to proceed that way instead of having the callback directly + * in the structure in order to have some way to check that the structure is + * still valid, or at least gracefully handle errors instead of crashing. + * + * @param con The connection to retrieve the callback from. + * + * @return Function pointer or NULL. + */ +void *dlt_connection_get_callback(DltConnection *con) +{ + void *ret = NULL; + DltConnectionType type = DLT_CONNECTION_TYPE_MAX; + + if (con) + { + type = con->type; + } + + switch (type) + { + case DLT_CONNECTION_CLIENT_CONNECT: + ret = dlt_daemon_process_client_connect; + break; + case DLT_CONNECTION_CLIENT_MSG_TCP: + ret = dlt_daemon_process_client_messages; + break; + case DLT_CONNECTION_CLIENT_MSG_SERIAL: + ret = dlt_daemon_process_client_messages_serial; + break; + case DLT_CONNECTION_APP_MSG: + ret = dlt_daemon_process_user_messages; + break; + case DLT_CONNECTION_ONE_S_TIMER: + ret = dlt_daemon_process_one_s_timer; + break; + case DLT_CONNECTION_SIXTY_S_TIMER: + ret = dlt_daemon_process_sixty_s_timer; + break; +#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE + case DLT_CONNECTION_SYSTEMD_TIMER: + ret = dlt_daemon_process_systemd_timer; + break; +#endif + default: + ret = NULL; + } + + return ret; +} + +/** @brief Destroys a connection. + * + * This function closes and frees the corresponding connection. This is expected + * to be called by the connection owner: the DltEventHandler. + * Ownership of the connection is given during the registration to + * the DltEventHandler. + * + * @param to_destroy Connection to be destroyed. + */ +void dlt_connection_destroy(DltConnection *to_destroy) +{ + close(to_destroy->fd); + free(to_destroy); +} + +/** @brief Creates a connection and registers it to the DltEventHandler. + * + * The function will allocate memory for the connection, and give the pointer + * to the DltEventHandler in order to register it for incoming events. + * The connection is then destroyed later on, once it's not needed anymore or + * it the event handler is destroyed. + * + * @param daemon_local Structure were some needed information is. + * @param evh DltEventHandler to register the connection to. + * @param fd File descriptor of the connection. + * @param mask Event list bit mask. + * @param type Connection type. + * + * @return 0 On success, -1 otherwise. + */ +int dlt_connection_create(DltDaemonLocal *daemon_local, + DltEventHandler *evh, + int fd, + int mask, + DltConnectionType type) +{ + DltConnection *temp = NULL; + + if (dlt_event_handler_find_connection(evh, fd) != NULL) + { + /* No need for the same client to be registered twice + * for the same event. + * TODO: If another mask can be expected, + * we need it to update the epoll event here. + */ + return 0; + } + + temp = (DltConnection *)malloc(sizeof(DltConnection)); + + if (temp == NULL) + { + dlt_log(LOG_CRIT, "Allocation of client handle failed\n"); + return -1; + } + + memset(temp, 0, sizeof(DltConnection)); + + temp->fd = fd; + temp->type = type; + temp->receiver = dlt_connection_get_receiver(daemon_local, type); + + /* Now give the ownership of the newly created connection + * to the event handler, by registering for events. + */ + return dlt_event_handler_register_connection(evh, daemon_local, temp, mask); +} + +/** @brief Creates connection from all types. + * + * This functions run through all connection types and tries to register + * on the event handler the one that were not already registered. + * + * @param daemon_local Structure to retrieve information from. + * + * @return 0 on success, -1 if a failure occurs. + */ +int dlt_connection_create_remaining(DltDaemonLocal *daemon_local) +{ + DltConnectionType i = 0; + DltEventHandler *ev = &daemon_local->pEvent; + char local_str[DLT_DAEMON_TEXTBUFSIZE]; + + for (i = 0 ; i < DLT_CONNECTION_TYPE_MAX ; i++) + { + int fd = 0; + DltReceiver *rec = dlt_connection_get_receiver(daemon_local, i); + + if (rec == NULL) + { + /* We are not interested if there is no receiver available */ + continue; + } + + fd = rec->fd; + + /* Already created connections are ignored here */ + if ((fd > 0) && dlt_connection_create(daemon_local, ev, fd, EPOLLIN, i)) + { + snprintf(local_str, + DLT_DAEMON_TEXTBUFSIZE, + "Unable to register type %i event handler.\n", + i); + + dlt_log(LOG_ERR, local_str); + + return -1; + } + } + + return 0; +} diff --git a/src/daemon/dlt_daemon_connection.h b/src/daemon/dlt_daemon_connection.h new file mode 100644 index 0000000..aa21a11 --- /dev/null +++ b/src/daemon/dlt_daemon_connection.h @@ -0,0 +1,51 @@ +/* + * @licence app begin@ + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * + * This Source Code Form is subject to the terms of the + * Mozilla Public License (MPL), v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/*! + * \author + * Frederic Berat <fberat@de.adit-jv.com> + * + * \copyright Copyright © 2015 Advanced Driver Information Technology. \n + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_connection.h + */ + +#ifndef DLT_DAEMON_CONNECTION_H +#define DLT_DAEMON_CONNECTION_H + +#include "dlt_daemon_connection_types.h" +#include "dlt_daemon_event_handler_types.h" +#include "dlt-daemon.h" + +int dlt_connection_send_multiple(DltConnection *, void *, int, void *, int, int); + +DltConnection *dlt_connection_get_next(DltConnection *, int); +int dlt_connection_create_remaining(DltDaemonLocal *); + +int dlt_connection_create(DltDaemonLocal *, + DltEventHandler *, + int, + int, + DltConnectionType); +void dlt_connection_destroy(DltConnection *); + +void *dlt_connection_get_callback(DltConnection *); + +#endif /* DLT_DAEMON_CONNECTION_H */ diff --git a/src/daemon/dlt_daemon_connection_types.h b/src/daemon/dlt_daemon_connection_types.h new file mode 100644 index 0000000..4f4bb1c --- /dev/null +++ b/src/daemon/dlt_daemon_connection_types.h @@ -0,0 +1,64 @@ +/* + * @licence app begin@ + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * + * This Source Code Form is subject to the terms of the + * Mozilla Public License (MPL), v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/*! + * \author + * Frederic Berat <fberat@de.adit-jv.com> + * + * \copyright Copyright © 2015 Advanced Driver Information Technology. \n + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_connection_types.h + */ + +#ifndef DLT_DAEMON_CONNECTION_TYPES_H +#define DLT_DAEMON_CONNECTION_TYPES_H +#include "dlt_common.h" + +typedef enum { + DLT_CONNECTION_CLIENT_CONNECT = 0, + DLT_CONNECTION_CLIENT_MSG_TCP, + DLT_CONNECTION_CLIENT_MSG_SERIAL, + DLT_CONNECTION_APP_MSG, + DLT_CONNECTION_ONE_S_TIMER, + DLT_CONNECTION_SIXTY_S_TIMER, + DLT_CONNECTION_SYSTEMD_TIMER, + DLT_CONNECTION_TYPE_MAX +} DltConnectionType; + +#define DLT_CON_MASK_CLIENT_CONNECT (1 << DLT_CONNECTION_CLIENT_CONNECT) +#define DLT_CON_MASK_CLIENT_MSG_TCP (1 << DLT_CONNECTION_CLIENT_MSG_TCP) +#define DLT_CON_MASK_CLIENT_MSG_SERIAL (1 << DLT_CONNECTION_CLIENT_MSG_SERIAL) +#define DLT_CON_MASK_APP_MSG (1 << DLT_CONNECTION_APP_MSG) +#define DLT_CON_MASK_ONE_S_TIMER (1 << DLT_CONNECTION_ONE_S_TIMER) +#define DLT_CON_MASK_SIXTY_S_TIMER (1 << DLT_CONNECTION_SIXTY_S_TIMER) +#define DLT_CON_MASK_SYSTEMD_TIMER (1 << DLT_CONNECTION_SYSTEMD_TIMER) +#define DLT_CON_MASK_ALL (0xff) + +/* TODO: squash the DltReceiver structure in there + * and remove any other duplicates of FDs + */ +typedef struct DltConnection { + int fd; /**< File descriptor */ + DltConnectionType type; /**< Represents what type of handle is this (like FIFO, serial, client, server) */ + DltReceiver *receiver; /**< Pointer to the affected receiver structure */ + struct DltConnection *next; /**< For multiple client connection using linked list */ +} DltConnection; + +#endif /* DLT_DAEMON_CONNECTION_TYPES_H */ diff --git a/src/daemon/dlt_daemon_event_handler.c b/src/daemon/dlt_daemon_event_handler.c new file mode 100644 index 0000000..3762ca2 --- /dev/null +++ b/src/daemon/dlt_daemon_event_handler.c @@ -0,0 +1,373 @@ +/* + * @licence app begin@ + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * + * This Source Code Form is subject to the terms of the + * Mozilla Public License (MPL), v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/*! + * \author + * Frederic Berat <fberat@de.adit-jv.com> + * + * \copyright Copyright © 2015 Advanced Driver Information Technology. \n + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_event_handler.c + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <sys/epoll.h> +#include <sys/syslog.h> + +#include "dlt_common.h" + +#include "dlt-daemon.h" +#include "dlt-daemon_cfg.h" +#include "dlt_daemon_common.h" +#include "dlt_daemon_connection.h" +#include "dlt_daemon_connection_types.h" +#include "dlt_daemon_event_handler.h" +#include "dlt_daemon_event_handler_types.h" + +/** + * \def DLT_EPOLL_TIMEOUT_MSEC + * The maximum amount of time to wait for an epoll event. + * Set to 1 second to avoid unnecessary wake ups. + */ +#define DLT_EPOLL_TIMEOUT_MSEC 1000 + +/** @brief Prepare the event handler + * + * This will create the epoll file descriptor. + * + * @param ev The event handler to prepare. + * + * @return 0 on success, -1 otherwise. + */ +int dlt_daemon_prepare_event_handling(DltEventHandler *ev) +{ + ev->epfd = epoll_create(DLT_EPOLL_MAX_EVENTS); + + if (ev->epfd < 0) + { + dlt_log(LOG_CRIT, "Creation of epoll instance failed!\n"); + return -1; + } + + return 0; +} + +/** @brief Catch and process incoming events. + * + * This function waits for events on all connections. Once an event raise, + * the callback for the specific connection is called, or the connection is + * destroyed if a hangup occurs. + * + * @param daemon Structure to be passed to the callback. + * @param daemon_local Structure containing needed information. + * @param pEvent Event handler structure. + * + * @return 0 on success, -1 otherwise. May be interrupted. + */ +int dlt_daemon_handle_event(DltEventHandler *pEvent, + DltDaemon *daemon, + DltDaemonLocal *daemon_local) +{ + int nfds = 0; + int i = 0; + char str[DLT_DAEMON_TEXTBUFSIZE]; + int (*callback)(DltDaemon *, DltDaemonLocal *, int) = NULL; + + /*CM Change begin*/ + nfds = epoll_wait(pEvent->epfd, + pEvent->events, + DLT_EPOLL_MAX_EVENTS, + DLT_EPOLL_TIMEOUT_MSEC); + + if (nfds < 0) + { + /* We are not interested in EINTR has it comes + * either from timeout or signal. + */ + if (errno != EINTR) + { + snprintf(str, + DLT_DAEMON_TEXTBUFSIZE, + "epoll_wait() failed: %s\n", + strerror(errno)); + dlt_log(LOG_CRIT, str); + return -1; + } + + return 0; + } + + for (i = 0 ; i < nfds ; i++) + { + struct epoll_event *ev = &pEvent->events[i]; + int fd = 0; + DltConnectionType type = DLT_CONNECTION_TYPE_MAX; + + if ((DltConnection *)ev->data.ptr) + { + type = ((DltConnection *)ev->data.ptr)->type; + fd = ((DltConnection *)ev->data.ptr)->fd; + } + + /* First of all handle epoll error events + * We only expect EPOLLIN or EPOLLOUT + */ + if ((ev->events != EPOLLIN) && (ev->events != EPOLLOUT)) + { + /* epoll reports an error, we need to clean-up the concerned event + */ + dlt_event_handler_unregister_connection(pEvent, + daemon_local, + fd, + type); + continue; + } + + /* Get the function to be used to handle the event */ + callback = dlt_connection_get_callback((DltConnection *)ev->data.ptr); + + if (!callback) + { + snprintf(str, + DLT_DAEMON_TEXTBUFSIZE, + "Unable to find function for %d handle type.\n", + type); + dlt_log(LOG_CRIT, str); + return -1; + } + + /* TODO: Review the design to clean-up this line. + * fd are currently wrongly duplicated which may lead to errors. */ + ((DltConnection *)ev->data.ptr)->receiver->fd = fd; + + /* From now on, callback is correct */ + if (callback(daemon, daemon_local, daemon_local->flags.vflag) == -1) + { + snprintf(str, + DLT_DAEMON_TEXTBUFSIZE, + "Processing from %d handle type failed!\n", + type ); + dlt_log(LOG_CRIT, str); + return -1; + } + } + + return 0; +} + +/** @brief Find connection with a specific \a fd in the connection list. + * + * There can be only one event per \a fd. We can then find a specific connection + * based on this \a fd. That allows to check if a specific \a fd has already been + * registered. + * + * @param ev The event handler structure where the list of connection is. + * @param fd The file descriptor of the connection to be found. + * + * @return The found connection pointer, NULL otherwise. + */ +DltConnection *dlt_event_handler_find_connection(DltEventHandler *ev, + int fd) +{ + DltConnection *temp = ev->connections; + + while ((temp != NULL) && (temp->fd != fd)) + { + temp = temp->next; + } + + return temp; +} + +/** @brief Remove a connection from the list and destroy it. + * + * This function will first look for the connection in the event handler list, + * remove it from the list and then destroy it. + * + * @param ev The event handler structure where the list of connection is. + * @param to_remove The connection to remove from the list. + * + * @return 0 on success, -1 if the connection is not found. + */ +static int dlt_daemon_remove_connection(DltEventHandler *ev, + DltConnection *to_remove) +{ + DltConnection **curr = &ev->connections; + + /* Find the address where to_remove value is registered */ + while (*curr && (*curr != to_remove)) + { + curr = &(*curr)->next; + } + + if (!*curr) + { + /* Must not be possible as we check for existence before */ + dlt_log(LOG_CRIT, "Connection not found for removal.\n"); + return -1; + } + + /* Replace the content of the address by the next value */ + *curr = (*curr)->next; + + /* Now we can destroy our pointer */ + dlt_connection_destroy(to_remove); + + return 0; +} + +/** @brief Destroy the connection list. + * + * This function runs through the connection list and destroy them one by one. + * + * @param ev Pointer to the event handler structure. + */ +void dlt_event_handler_cleanup_connections(DltEventHandler *ev) +{ + if (ev == NULL) + { + /* Nothing to do. */ + return; + } + + while (ev->connections != NULL) + { + /* We don really care on failure */ + (void)dlt_daemon_remove_connection(ev, ev->connections); + } +} + +/** @brief Add a new connection to the list. + * + * The connection is added at the tail of the list. + * + * @param ev The event handler structure where the connection list is. + * @param connection The connection to be added. + */ +static void dlt_daemon_add_connection(DltEventHandler *ev, + DltConnection *connection) +{ + DltConnection **temp = &ev->connections; + + while (*temp != NULL) + { + temp = &(*temp)->next; + } + + *temp = connection; +} + +/** @brief Registers a connection for event handling and takes its ownership. + * + * As we add the connection to the list of connection, we take its ownership. + * That's the only place where the connection pointer is stored. + * The connection is then used to create a new event trigger. + * If the connection is of type DLT_CONNECTION_CLIENT_MSG_TCP, we increase + * the daemon_local->client_connections counter. TODO: Move this counter inside + * the event handler structure. + * + * @param evhdl The event handler structure where the connection list is. + * @param daemon_local Structure containing needed information. + * @param connection The connection to be registered. + * @param mask The bit mask of event to be registered. + * + * @return 0 on success, -1 otherwise. + */ +int dlt_event_handler_register_connection(DltEventHandler *evhdl, + DltDaemonLocal *daemon_local, + DltConnection *connection, + int mask) +{ + struct epoll_event ev; /* Content will be copied by the kernel */ + + dlt_daemon_add_connection(evhdl, connection); + + ev.events = mask; + ev.data.ptr = (void *)connection; + + if (epoll_ctl(evhdl->epfd, EPOLL_CTL_ADD, connection->fd, &ev) == -1) + { + dlt_log(LOG_ERR, "epoll_ctl() failed!\n"); + dlt_daemon_remove_connection(evhdl, connection); + return -1; + } + + if (connection->type == DLT_CONNECTION_CLIENT_MSG_TCP) + { + daemon_local->client_connections++; + } + + return 0; +} + +/** @brief Unregisters a connection from the event handler and destroys it. + * + * We first look for the connection to be unregistered, delete the event + * corresponding and then destroy the connection. + * If the connection is of type DLT_CONNECTION_CLIENT_MSG_TCP, we decrease + * the daemon_local->client_connections counter. TODO: Move this counter inside + * the event handler structure. + * + * @param evhdl The event handler structure where the connection list is. + * @param daemon_local Structure containing needed information. + * @param fd The file descriptor of the connection to be unregistered. + * @param type the connection type. + * + * @return 0 on success, -1 otherwise. + */ +int dlt_event_handler_unregister_connection(DltEventHandler *evhdl, + DltDaemonLocal *daemon_local, + int fd, + DltConnectionType type) +{ + /* Look for the pointer in the client list. + * There shall be only one event handler with the same fd. + */ + DltConnection *temp = dlt_event_handler_find_connection(evhdl, fd); + + if (!temp) + { + dlt_log(LOG_ERR, "Connection not found for unregistration.\n"); + return -1; + } + + if (epoll_ctl(evhdl->epfd, EPOLL_CTL_DEL, fd, NULL) < 0) + { + dlt_log(LOG_ERR, "Unable to unregister event.\n"); + return -1; + } + + if (type == DLT_CONNECTION_CLIENT_MSG_TCP) + { + daemon_local->client_connections--; + + if (daemon_local->client_connections < 0) + { + daemon_local->client_connections = 0; + dlt_log(LOG_CRIT, "Unregistering more client than registered!\n"); + } + } + + /* Cannot fail as far as dlt_daemon_find_connection succeed */ + return dlt_daemon_remove_connection(evhdl, temp); +} diff --git a/src/daemon/dlt_daemon_event_handler.h b/src/daemon/dlt_daemon_event_handler.h new file mode 100644 index 0000000..cd5d8ca --- /dev/null +++ b/src/daemon/dlt_daemon_event_handler.h @@ -0,0 +1,57 @@ +/* + * @licence app begin@ + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * + * This Source Code Form is subject to the terms of the + * Mozilla Public License (MPL), v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/*! + * \author + * Frederic Berat <fberat@de.adit-jv.com> + * + * \copyright Copyright © 2015 Advanced Driver Information Technology. \n + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_event_handler.h + */ + +#include <sys/epoll.h> + +#include "dlt_daemon_connection_types.h" +#include "dlt_daemon_event_handler_types.h" +#include "dlt-daemon.h" + +#ifndef DLT_DAEMON_EVENT_HANDLER_H +# define DLT_DAEMON_EVENT_HANDLER_H + +int dlt_daemon_prepare_event_handling(DltEventHandler *); +int dlt_daemon_handle_event(DltEventHandler *, DltDaemon *, DltDaemonLocal *); + +DltConnection *dlt_event_handler_find_connection(DltEventHandler *, + int); + +void dlt_event_handler_cleanup_connections(DltEventHandler *); + +int dlt_event_handler_register_connection(DltEventHandler *, + DltDaemonLocal *, + DltConnection *, + int); + +int dlt_event_handler_unregister_connection(DltEventHandler *, + DltDaemonLocal *, + int, + DltConnectionType); + +#endif /* DLT_DAEMON_EVENT_HANDLER_H */ diff --git a/src/daemon/dlt_daemon_event_handler_types.h b/src/daemon/dlt_daemon_event_handler_types.h new file mode 100644 index 0000000..080c331 --- /dev/null +++ b/src/daemon/dlt_daemon_event_handler_types.h @@ -0,0 +1,59 @@ +/* + * @licence app begin@ + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * + * This Source Code Form is subject to the terms of the + * Mozilla Public License (MPL), v. 2.0. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/*! + * \author + * Frederic Berat <fberat@de.adit-jv.com> + * + * \copyright Copyright © 2015 Advanced Driver Information Technology. \n + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_event_handler_types.h + */ + +#include <sys/epoll.h> + +#include "dlt_daemon_connection_types.h" + +#ifndef DLT_DAEMON_EVENT_HANDLER_TYPES_H +#define DLT_DAEMON_EVENT_HANDLER_TYPES_H + +/* FIXME: Remove the need for DltDaemonLocal everywhere in the code + * These typedefs are needed by DltDaemonLocal which is + * itself needed for functions used by the event handler + * (as this structure is used everywhere in the code ...) + */ + +typedef enum { + DLT_TIMER_PACKET = 0, + DLT_TIMER_ECU, +#ifdef DLT_SYSTEMD_WATCHDOG_ENABLE + DLT_TIMER_SYSTEMD, +#endif + DLT_TIMER_UNKNOWN +} DltTimers; + +#define DLT_EPOLL_MAX_EVENTS 10 +typedef struct { + int epfd; + struct epoll_event events[DLT_EPOLL_MAX_EVENTS]; + DltConnection *connections; +} DltEventHandler; + +#endif /* DLT_DAEMON_EVENT_HANDLER_TYPES_H */ |