summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemon/CMakeLists.txt2
-rw-r--r--src/daemon/dlt-daemon.c509
-rw-r--r--src/daemon/dlt-daemon.h23
-rw-r--r--src/daemon/dlt_daemon_client.c374
-rw-r--r--src/daemon/dlt_daemon_client.h9
-rw-r--r--src/daemon/dlt_daemon_connection.c374
-rw-r--r--src/daemon/dlt_daemon_connection.h51
-rw-r--r--src/daemon/dlt_daemon_connection_types.h64
-rw-r--r--src/daemon/dlt_daemon_event_handler.c373
-rw-r--r--src/daemon/dlt_daemon_event_handler.h57
-rw-r--r--src/daemon/dlt_daemon_event_handler_types.h59
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*)&lt, 0, sizeof(lt));
+ localtime_r(&t, &lt);
+
+ 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 */