automotive-dlt
dlt_daemon_event_handler.c
Go to the documentation of this file.
1 /*
2  * @licence app begin@
3  * SPDX license identifier: MPL-2.0
4  *
5  * Copyright (C) 2015 Advanced Driver Information Technology.
6  * This code is developed by Advanced Driver Information Technology.
7  * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
8  *
9  * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
10  *
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License (MPL), v. 2.0.
13  * If a copy of the MPL was not distributed with this file,
14  * You can obtain one at http://mozilla.org/MPL/2.0/.
15  *
16  * For further information see http://www.genivi.org/.
17  * @licence end@
18  */
19 
30 #include <stdio.h>
31 #include <string.h>
32 #include <errno.h>
33 
34 #include <sys/epoll.h>
35 #include <sys/syslog.h>
36 
37 #include "dlt_common.h"
38 
39 #include "dlt-daemon.h"
40 #include "dlt-daemon_cfg.h"
41 #include "dlt_daemon_common.h"
42 #include "dlt_daemon_connection.h"
46 
52 #define DLT_EPOLL_TIMEOUT_MSEC 1000
53 
63 {
64  if (ev == NULL)
65  {
66  return DLT_RETURN_ERROR;
67  }
68  ev->epfd = epoll_create(DLT_EPOLL_MAX_EVENTS);
69 
70  if (ev->epfd < 0)
71  {
72  dlt_log(LOG_CRIT, "Creation of epoll instance failed!\n");
73  return -1;
74  }
75 
76  return 0;
77 }
78 
92  DltDaemon *daemon,
93  DltDaemonLocal *daemon_local)
94 {
95  if ((pEvent == NULL) || (daemon == NULL) || (daemon_local == NULL))
96  {
97  return DLT_RETURN_ERROR;
98  }
99  int nfds = 0;
100  int i = 0;
102  int (*callback)(DltDaemon *, DltDaemonLocal *, DltReceiver *, int) = NULL;
103 
104  /*CM Change begin*/
105  nfds = epoll_wait(pEvent->epfd,
106  pEvent->events,
109 
110  if (nfds < 0)
111  {
112  /* We are not interested in EINTR has it comes
113  * either from timeout or signal.
114  */
115  if (errno != EINTR)
116  {
117  snprintf(str,
119  "epoll_wait() failed: %s\n",
120  strerror(errno));
121  dlt_log(LOG_CRIT, str);
122  return -1;
123  }
124 
125  return 0;
126  }
127 
128  for (i = 0 ; i < nfds ; i++)
129  {
130  struct epoll_event *ev = &pEvent->events[i];
131  DltConnectionId id = (DltConnectionId)ev->data.ptr;
133  id);
134  int fd = 0;
136 
137  if (con && con->receiver)
138  {
139  type = con->type;
140  fd = con->receiver->fd;
141  }
142  else /* connection might have been destroyed in the meanwhile */
143  {
144  continue;
145  }
146 
147  /* First of all handle epoll error events
148  * We only expect EPOLLIN or EPOLLOUT
149  */
150  if ((ev->events != EPOLLIN) && (ev->events != EPOLLOUT))
151  {
152  /* epoll reports an error, we need to clean-up the concerned event
153  */
155  daemon_local,
156  fd);
157  continue;
158  }
159 
160  /* Get the function to be used to handle the event */
161  callback = dlt_connection_get_callback(con);
162 
163  if (!callback)
164  {
165  snprintf(str,
167  "Unable to find function for %d handle type.\n",
168  type);
169  dlt_log(LOG_CRIT, str);
170  return -1;
171  }
172 
173  /* From now on, callback is correct */
174  if (callback(daemon,
175  daemon_local,
176  con->receiver,
177  daemon_local->flags.vflag) == -1)
178  {
179  snprintf(str,
181  "Processing from %d handle type failed!\n",
182  type );
183  dlt_log(LOG_CRIT, str);
184  return -1;
185  }
186  }
187  return 0;
188 }
189 
202  int fd)
203 {
204 
205  DltConnection *temp = ev->connections;
206 
207  while ((temp != NULL) && (temp->receiver->fd != fd))
208  {
209  temp = temp->next;
210  }
211 
212  return temp;
213 }
214 
227  DltConnectionId id)
228 {
229 
230  DltConnection *temp = ev->connections;
231 
232  while ((temp != NULL) && (temp->id != id))
233  {
234  temp = temp->next;
235  }
236 
237  return temp;
238 }
239 
251  DltConnection *to_remove)
252 {
253  if (ev == NULL || to_remove == NULL)
254  {
255  return DLT_RETURN_ERROR;
256  }
257  DltConnection **curr = &ev->connections;
258 
259  /* Find the address where to_remove value is registered */
260  while (*curr && (*curr != to_remove))
261  {
262  curr = &(*curr)->next;
263  }
264 
265  if (!*curr)
266  {
267  /* Must not be possible as we check for existence before */
268  dlt_log(LOG_CRIT, "Connection not found for removal.\n");
269  return -1;
270  }
271 
272  /* Replace the content of the address by the next value */
273  *curr = (*curr)->next;
274 
275  /* Now we can destroy our pointer */
276  dlt_connection_destroy(to_remove);
277 
278  return 0;
279 }
280 
288 {
289  if (ev == NULL)
290  {
291  /* Nothing to do. */
292  return;
293  }
294 
295  while (ev->connections != NULL)
296  {
297  /* We don really care on failure */
299  }
300 }
301 
310  DltConnection *connection)
311 {
312 
313  DltConnection **temp = &ev->connections;
314 
315  while (*temp != NULL)
316  {
317  temp = &(*temp)->next;
318  }
319  *temp = connection;
320 }
321 
336  DltConnection *con,
337  int activation_type)
338 {
339  char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
340 
341  if (!evhdl || !con || !con->receiver)
342  {
343  snprintf(local_str,
345  "%s: wrong parameters (%p %p).\n",
346  __func__,
347  evhdl,
348  con);
349  dlt_log(LOG_ERR, local_str);
350  return -1;
351  }
352 
353  switch (con->status)
354  {
355  case ACTIVE:
356  if (activation_type == DEACTIVATE)
357  {
358  snprintf(local_str,
360  "Deactivate connection type: %d\n",
361  con->type);
362  dlt_log(LOG_INFO, local_str);
363 
364  if (epoll_ctl(evhdl->epfd,
365  EPOLL_CTL_DEL,
366  con->receiver->fd,
367  NULL) == -1)
368  {
369  dlt_log(LOG_ERR, "epoll_ctl() in deactivate failed!\n");
370  return -1;
371  }
372 
373  con->status = INACTIVE;
374  }
375  break;
376  case INACTIVE:
377  if (activation_type == ACTIVATE)
378  {
379  struct epoll_event ev; /* Content will be copied by the kernel */
380  ev.events = con->ev_mask;
381  ev.data.ptr = (void *)con->id;
382 
383  snprintf(local_str,
385  "Activate connection type: %d\n",
386  con->type);
387  dlt_log(LOG_INFO, local_str);
388 
389 
390  if (epoll_ctl(evhdl->epfd,
391  EPOLL_CTL_ADD,
392  con->receiver->fd,
393  &ev) == -1)
394  {
395  dlt_log(LOG_ERR, "epoll_ctl() in activate failed!\n");
396  return -1;
397  }
398  con->status = ACTIVE;
399  }
400  break;
401  default:
402  snprintf(local_str,
404  "Unknown connection status: %d\n",
405  con->status);
406  dlt_log(LOG_ERR, local_str);
407  return -1;
408  }
409 
410  return 0;
411 }
412 
430  DltDaemonLocal *daemon_local,
431  DltConnection *connection,
432  int mask)
433 {
434  if (!evhdl || !connection || !connection->receiver) {
435  dlt_log(LOG_ERR, "Wrong parameters when registering connection.\n");
436  return -1;
437  }
438 
439  dlt_daemon_add_connection(evhdl, connection);
440 
441  if ((connection->type == DLT_CONNECTION_CLIENT_MSG_TCP) ||
442  (connection->type == DLT_CONNECTION_CLIENT_MSG_SERIAL))
443  {
444  daemon_local->client_connections++;
445  }
446 
447  /* On creation the connection is not active by default */
448  connection->status = INACTIVE;
449 
450  connection->next = NULL;
451  connection->ev_mask = mask;
452 
453  return dlt_connection_check_activate(evhdl,
454  connection,
455  ACTIVATE);
456 }
457 
473  DltDaemonLocal *daemon_local,
474  int fd)
475 {
476  if (evhdl == NULL || daemon_local == NULL)
477  {
478  return DLT_RETURN_ERROR;
479  }
480 
481  /* Look for the pointer in the client list.
482  * There shall be only one event handler with the same fd.
483  */
485 
486  if (!temp)
487  {
488  dlt_log(LOG_ERR, "Connection not found for unregistration.\n");
489  return -1;
490  }
491 
492  if ((temp->type == DLT_CONNECTION_CLIENT_MSG_TCP) ||
494  {
495  daemon_local->client_connections--;
496 
497  if (daemon_local->client_connections < 0)
498  {
499  daemon_local->client_connections = 0;
500  dlt_log(LOG_CRIT, "Unregistering more client than registered!\n");
501  }
502  }
503 
505  temp,
506  DEACTIVATE) < 0)
507  {
508  dlt_log(LOG_ERR, "Unable to unregister event.\n");
509  }
510 
511  /* Cannot fail as far as dlt_daemon_find_connection succeed */
512  return dlt_daemon_remove_connection(evhdl, temp);
513 }
DltConnection * dlt_event_handler_find_connection(DltEventHandler *ev, int fd)
Find connection with a specific fd in the connection list.
struct epoll_event events[DLT_EPOLL_MAX_EVENTS]
int dlt_event_handler_unregister_connection(DltEventHandler *evhdl, DltDaemonLocal *daemon_local, int fd)
Unregisters a connection from the event handler and destroys it.
struct DltConnection * next
DltConnectionStatus status
int client_connections
Definition: dlt-daemon.h:143
void dlt_event_handler_cleanup_connections(DltEventHandler *ev)
Destroy the connection list.
DltReturnValue dlt_log(int prio, char *s)
Definition: dlt_common.c:2029
uintptr_t DltConnectionId
DltDaemonFlags flags
Definition: dlt-daemon.h:138
#define DLT_EPOLL_MAX_EVENTS
void * dlt_connection_get_callback(DltConnection *con)
Get the callback from a specific connection.
void dlt_connection_destroy(DltConnection *to_destroy)
Destroys a connection.
int dlt_event_handler_register_connection(DltEventHandler *evhdl, DltDaemonLocal *daemon_local, DltConnection *connection, int mask)
Registers a connection for event handling and takes its ownership.
int dlt_connection_check_activate(DltEventHandler *evhdl, DltConnection *con, int activation_type)
Check for connection activation.
#define DLT_EPOLL_TIMEOUT_MSEC
STATIC void dlt_daemon_add_connection(DltEventHandler *ev, DltConnection *connection)
Add a new connection to the list.
static char str[DLT_DAEMON_TEXTBUFSIZE]
Definition: dlt-daemon.c:80
DltConnection * dlt_event_handler_find_connection_by_id(DltEventHandler *ev, DltConnectionId id)
Find connection with a specific id in the connection list.
#define STATIC
Definition: dlt_common.h:343
STATIC int dlt_daemon_remove_connection(DltEventHandler *ev, DltConnection *to_remove)
Remove a connection from the list and destroy it.
int dlt_daemon_prepare_event_handling(DltEventHandler *ev)
Prepare the event handler.
DltConnectionType type
#define DLT_DAEMON_TEXTBUFSIZE
#define NULL
Definition: dlt_common.h:232
int dlt_daemon_handle_event(DltEventHandler *pEvent, DltDaemon *daemon, DltDaemonLocal *daemon_local)
Catch and process incoming events.