• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Event loop based on select() loop
3  * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 #include <assert.h>
11 
12 #include "common.h"
13 #include "trace.h"
14 #include "list.h"
15 #include "eloop.h"
16 
17 #if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL)
18 #error Do not define both of poll and epoll
19 #endif
20 
21 #if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
22 #define CONFIG_ELOOP_SELECT
23 #endif
24 
25 #ifdef CONFIG_ELOOP_POLL
26 #include <poll.h>
27 #endif /* CONFIG_ELOOP_POLL */
28 
29 #ifdef CONFIG_ELOOP_EPOLL
30 #include <sys/epoll.h>
31 #endif /* CONFIG_ELOOP_EPOLL */
32 
33 struct eloop_sock {
34 	int sock;
35 	void *eloop_data;
36 	void *user_data;
37 	eloop_sock_handler handler;
38 	WPA_TRACE_REF(eloop);
39 	WPA_TRACE_REF(user);
40 	WPA_TRACE_INFO
41 };
42 
43 struct eloop_timeout {
44 	struct dl_list list;
45 	struct os_reltime time;
46 	void *eloop_data;
47 	void *user_data;
48 	eloop_timeout_handler handler;
49 	WPA_TRACE_REF(eloop);
50 	WPA_TRACE_REF(user);
51 	WPA_TRACE_INFO
52 };
53 
54 struct eloop_signal {
55 	int sig;
56 	void *user_data;
57 	eloop_signal_handler handler;
58 	int signaled;
59 };
60 
61 struct eloop_sock_table {
62 	int count;
63 	struct eloop_sock *table;
64 #ifdef CONFIG_ELOOP_EPOLL
65 	eloop_event_type type;
66 #else /* CONFIG_ELOOP_EPOLL */
67 	int changed;
68 #endif /* CONFIG_ELOOP_EPOLL */
69 };
70 
71 struct eloop_data {
72 	int max_sock;
73 
74 	int count; /* sum of all table counts */
75 #ifdef CONFIG_ELOOP_POLL
76 	int max_pollfd_map; /* number of pollfds_map currently allocated */
77 	int max_poll_fds; /* number of pollfds currently allocated */
78 	struct pollfd *pollfds;
79 	struct pollfd **pollfds_map;
80 #endif /* CONFIG_ELOOP_POLL */
81 #ifdef CONFIG_ELOOP_EPOLL
82 	int epollfd;
83 	int epoll_max_event_num;
84 	int epoll_max_fd;
85 	struct eloop_sock *epoll_table;
86 	struct epoll_event *epoll_events;
87 #endif /* CONFIG_ELOOP_EPOLL */
88 	struct eloop_sock_table readers;
89 	struct eloop_sock_table writers;
90 	struct eloop_sock_table exceptions;
91 
92 	struct dl_list timeout;
93 
94 	int signal_count;
95 	struct eloop_signal *signals;
96 	int signaled;
97 	int pending_terminate;
98 
99 	int terminate;
100 };
101 
102 static struct eloop_data eloop;
103 
104 
105 #ifdef WPA_TRACE
106 
eloop_sigsegv_handler(int sig)107 static void eloop_sigsegv_handler(int sig)
108 {
109 	wpa_trace_show("eloop SIGSEGV");
110 	abort();
111 }
112 
eloop_trace_sock_add_ref(struct eloop_sock_table * table)113 static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
114 {
115 	int i;
116 	if (table == NULL || table->table == NULL)
117 		return;
118 	for (i = 0; i < table->count; i++) {
119 		wpa_trace_add_ref(&table->table[i], eloop,
120 				  table->table[i].eloop_data);
121 		wpa_trace_add_ref(&table->table[i], user,
122 				  table->table[i].user_data);
123 	}
124 }
125 
126 
eloop_trace_sock_remove_ref(struct eloop_sock_table * table)127 static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
128 {
129 	int i;
130 	if (table == NULL || table->table == NULL)
131 		return;
132 	for (i = 0; i < table->count; i++) {
133 		wpa_trace_remove_ref(&table->table[i], eloop,
134 				     table->table[i].eloop_data);
135 		wpa_trace_remove_ref(&table->table[i], user,
136 				     table->table[i].user_data);
137 	}
138 }
139 
140 #else /* WPA_TRACE */
141 
142 #define eloop_trace_sock_add_ref(table) do { } while (0)
143 #define eloop_trace_sock_remove_ref(table) do { } while (0)
144 
145 #endif /* WPA_TRACE */
146 
147 
eloop_init(void)148 int eloop_init(void)
149 {
150 	os_memset(&eloop, 0, sizeof(eloop));
151 	dl_list_init(&eloop.timeout);
152 #ifdef CONFIG_ELOOP_EPOLL
153 	eloop.epollfd = epoll_create1(0);
154 	if (eloop.epollfd < 0) {
155 		wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
156 			   __func__, strerror(errno));
157 		return -1;
158 	}
159 	eloop.readers.type = EVENT_TYPE_READ;
160 	eloop.writers.type = EVENT_TYPE_WRITE;
161 	eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
162 #endif /* CONFIG_ELOOP_EPOLL */
163 #ifdef WPA_TRACE
164 	signal(SIGSEGV, eloop_sigsegv_handler);
165 #endif /* WPA_TRACE */
166 	return 0;
167 }
168 
169 
eloop_sock_table_add_sock(struct eloop_sock_table * table,int sock,eloop_sock_handler handler,void * eloop_data,void * user_data)170 static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
171                                      int sock, eloop_sock_handler handler,
172                                      void *eloop_data, void *user_data)
173 {
174 #ifdef CONFIG_ELOOP_EPOLL
175 	struct eloop_sock *temp_table;
176 	struct epoll_event ev, *temp_events;
177 	int next;
178 #endif /* CONFIG_ELOOP_EPOLL */
179 	struct eloop_sock *tmp;
180 	int new_max_sock;
181 
182 	if (sock > eloop.max_sock)
183 		new_max_sock = sock;
184 	else
185 		new_max_sock = eloop.max_sock;
186 
187 	if (table == NULL)
188 		return -1;
189 
190 #ifdef CONFIG_ELOOP_POLL
191 	if (new_max_sock >= eloop.max_pollfd_map) {
192 		struct pollfd **nmap;
193 		nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
194 					sizeof(struct pollfd *));
195 		if (nmap == NULL)
196 			return -1;
197 
198 		eloop.max_pollfd_map = new_max_sock + 50;
199 		eloop.pollfds_map = nmap;
200 	}
201 
202 	if (eloop.count + 1 > eloop.max_poll_fds) {
203 		struct pollfd *n;
204 		int nmax = eloop.count + 1 + 50;
205 		n = os_realloc_array(eloop.pollfds, nmax,
206 				     sizeof(struct pollfd));
207 		if (n == NULL)
208 			return -1;
209 
210 		eloop.max_poll_fds = nmax;
211 		eloop.pollfds = n;
212 	}
213 #endif /* CONFIG_ELOOP_POLL */
214 #ifdef CONFIG_ELOOP_EPOLL
215 	if (new_max_sock >= eloop.epoll_max_fd) {
216 		next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
217 		temp_table = os_realloc_array(eloop.epoll_table, next,
218 					      sizeof(struct eloop_sock));
219 		if (temp_table == NULL)
220 			return -1;
221 
222 		eloop.epoll_max_fd = next;
223 		eloop.epoll_table = temp_table;
224 	}
225 
226 	if (eloop.count + 1 > eloop.epoll_max_event_num) {
227 		next = eloop.epoll_max_event_num == 0 ? 8 :
228 			eloop.epoll_max_event_num * 2;
229 		temp_events = os_realloc_array(eloop.epoll_events, next,
230 					       sizeof(struct epoll_event));
231 		if (temp_events == NULL) {
232 			wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
233 				   "%s\n", __func__, strerror(errno));
234 			return -1;
235 		}
236 
237 		eloop.epoll_max_event_num = next;
238 		eloop.epoll_events = temp_events;
239 	}
240 #endif /* CONFIG_ELOOP_EPOLL */
241 
242 	eloop_trace_sock_remove_ref(table);
243 	tmp = os_realloc_array(table->table, table->count + 1,
244 			       sizeof(struct eloop_sock));
245 	if (tmp == NULL)
246 		return -1;
247 
248 	tmp[table->count].sock = sock;
249 	tmp[table->count].eloop_data = eloop_data;
250 	tmp[table->count].user_data = user_data;
251 	tmp[table->count].handler = handler;
252 	wpa_trace_record(&tmp[table->count]);
253 	table->count++;
254 	table->table = tmp;
255 	eloop.max_sock = new_max_sock;
256 	eloop.count++;
257 #ifndef CONFIG_ELOOP_EPOLL
258 	table->changed = 1;
259 #endif /* CONFIG_ELOOP_EPOLL */
260 	eloop_trace_sock_add_ref(table);
261 
262 #ifdef CONFIG_ELOOP_EPOLL
263 	os_memset(&ev, 0, sizeof(ev));
264 	switch (table->type) {
265 	case EVENT_TYPE_READ:
266 		ev.events = EPOLLIN;
267 		break;
268 	case EVENT_TYPE_WRITE:
269 		ev.events = EPOLLOUT;
270 		break;
271 	/*
272 	 * Exceptions are always checked when using epoll, but I suppose it's
273 	 * possible that someone registered a socket *only* for exception
274 	 * handling.
275 	 */
276 	case EVENT_TYPE_EXCEPTION:
277 		ev.events = EPOLLERR | EPOLLHUP;
278 		break;
279 	}
280 	ev.data.fd = sock;
281 	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
282 		wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
283 			   "failed. %s\n", __func__, sock, strerror(errno));
284 		return -1;
285 	}
286 	os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
287 		  sizeof(struct eloop_sock));
288 #endif /* CONFIG_ELOOP_EPOLL */
289 	return 0;
290 }
291 
292 
eloop_sock_table_remove_sock(struct eloop_sock_table * table,int sock)293 static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
294                                          int sock)
295 {
296 	int i;
297 
298 	if (table == NULL || table->table == NULL || table->count == 0)
299 		return;
300 
301 	for (i = 0; i < table->count; i++) {
302 		if (table->table[i].sock == sock)
303 			break;
304 	}
305 	if (i == table->count)
306 		return;
307 	eloop_trace_sock_remove_ref(table);
308 	if (i != table->count - 1) {
309 		os_memmove(&table->table[i], &table->table[i + 1],
310 			   (table->count - i - 1) *
311 			   sizeof(struct eloop_sock));
312 	}
313 	table->count--;
314 	eloop.count--;
315 #ifndef CONFIG_ELOOP_EPOLL
316 	table->changed = 1;
317 #endif /* CONFIG_ELOOP_EPOLL */
318 	eloop_trace_sock_add_ref(table);
319 #ifdef CONFIG_ELOOP_EPOLL
320 	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
321 		wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
322 			   "failed. %s\n", __func__, sock, strerror(errno));
323 		return;
324 	}
325 	os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
326 #endif /* CONFIG_ELOOP_EPOLL */
327 }
328 
329 
330 #ifdef CONFIG_ELOOP_POLL
331 
find_pollfd(struct pollfd ** pollfds_map,int fd,int mx)332 static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx)
333 {
334 	if (fd < mx && fd >= 0)
335 		return pollfds_map[fd];
336 	return NULL;
337 }
338 
339 
eloop_sock_table_set_fds(struct eloop_sock_table * readers,struct eloop_sock_table * writers,struct eloop_sock_table * exceptions,struct pollfd * pollfds,struct pollfd ** pollfds_map,int max_pollfd_map)340 static int eloop_sock_table_set_fds(struct eloop_sock_table *readers,
341 				    struct eloop_sock_table *writers,
342 				    struct eloop_sock_table *exceptions,
343 				    struct pollfd *pollfds,
344 				    struct pollfd **pollfds_map,
345 				    int max_pollfd_map)
346 {
347 	int i;
348 	int nxt = 0;
349 	int fd;
350 	struct pollfd *pfd;
351 
352 	/* Clear pollfd lookup map. It will be re-populated below. */
353 	os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map);
354 
355 	if (readers && readers->table) {
356 		for (i = 0; i < readers->count; i++) {
357 			fd = readers->table[i].sock;
358 			assert(fd >= 0 && fd < max_pollfd_map);
359 			pollfds[nxt].fd = fd;
360 			pollfds[nxt].events = POLLIN;
361 			pollfds[nxt].revents = 0;
362 			pollfds_map[fd] = &(pollfds[nxt]);
363 			nxt++;
364 		}
365 	}
366 
367 	if (writers && writers->table) {
368 		for (i = 0; i < writers->count; i++) {
369 			/*
370 			 * See if we already added this descriptor, update it
371 			 * if so.
372 			 */
373 			fd = writers->table[i].sock;
374 			assert(fd >= 0 && fd < max_pollfd_map);
375 			pfd = pollfds_map[fd];
376 			if (!pfd) {
377 				pfd = &(pollfds[nxt]);
378 				pfd->events = 0;
379 				pfd->fd = fd;
380 				pollfds[i].revents = 0;
381 				pollfds_map[fd] = pfd;
382 				nxt++;
383 			}
384 			pfd->events |= POLLOUT;
385 		}
386 	}
387 
388 	/*
389 	 * Exceptions are always checked when using poll, but I suppose it's
390 	 * possible that someone registered a socket *only* for exception
391 	 * handling. Set the POLLIN bit in this case.
392 	 */
393 	if (exceptions && exceptions->table) {
394 		for (i = 0; i < exceptions->count; i++) {
395 			/*
396 			 * See if we already added this descriptor, just use it
397 			 * if so.
398 			 */
399 			fd = exceptions->table[i].sock;
400 			assert(fd >= 0 && fd < max_pollfd_map);
401 			pfd = pollfds_map[fd];
402 			if (!pfd) {
403 				pfd = &(pollfds[nxt]);
404 				pfd->events = POLLIN;
405 				pfd->fd = fd;
406 				pollfds[i].revents = 0;
407 				pollfds_map[fd] = pfd;
408 				nxt++;
409 			}
410 		}
411 	}
412 
413 	return nxt;
414 }
415 
416 
eloop_sock_table_dispatch_table(struct eloop_sock_table * table,struct pollfd ** pollfds_map,int max_pollfd_map,short int revents)417 static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table,
418 					   struct pollfd **pollfds_map,
419 					   int max_pollfd_map,
420 					   short int revents)
421 {
422 	int i;
423 	struct pollfd *pfd;
424 
425 	if (!table || !table->table)
426 		return 0;
427 
428 	table->changed = 0;
429 	for (i = 0; i < table->count; i++) {
430 		pfd = find_pollfd(pollfds_map, table->table[i].sock,
431 				  max_pollfd_map);
432 		if (!pfd)
433 			continue;
434 
435 		if (!(pfd->revents & revents))
436 			continue;
437 
438 		table->table[i].handler(table->table[i].sock,
439 					table->table[i].eloop_data,
440 					table->table[i].user_data);
441 		if (table->changed)
442 			return 1;
443 	}
444 
445 	return 0;
446 }
447 
448 
eloop_sock_table_dispatch(struct eloop_sock_table * readers,struct eloop_sock_table * writers,struct eloop_sock_table * exceptions,struct pollfd ** pollfds_map,int max_pollfd_map)449 static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
450 				      struct eloop_sock_table *writers,
451 				      struct eloop_sock_table *exceptions,
452 				      struct pollfd **pollfds_map,
453 				      int max_pollfd_map)
454 {
455 	if (eloop_sock_table_dispatch_table(readers, pollfds_map,
456 					    max_pollfd_map, POLLIN | POLLERR |
457 					    POLLHUP))
458 		return; /* pollfds may be invalid at this point */
459 
460 	if (eloop_sock_table_dispatch_table(writers, pollfds_map,
461 					    max_pollfd_map, POLLOUT))
462 		return; /* pollfds may be invalid at this point */
463 
464 	eloop_sock_table_dispatch_table(exceptions, pollfds_map,
465 					max_pollfd_map, POLLERR | POLLHUP);
466 }
467 
468 #endif /* CONFIG_ELOOP_POLL */
469 
470 #ifdef CONFIG_ELOOP_SELECT
471 
eloop_sock_table_set_fds(struct eloop_sock_table * table,fd_set * fds)472 static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
473 				     fd_set *fds)
474 {
475 	int i;
476 
477 	FD_ZERO(fds);
478 
479 	if (table->table == NULL)
480 		return;
481 
482 	for (i = 0; i < table->count; i++) {
483 		assert(table->table[i].sock >= 0);
484 		FD_SET(table->table[i].sock, fds);
485 	}
486 }
487 
488 
eloop_sock_table_dispatch(struct eloop_sock_table * table,fd_set * fds)489 static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
490 				      fd_set *fds)
491 {
492 	int i;
493 
494 	if (table == NULL || table->table == NULL)
495 		return;
496 
497 	table->changed = 0;
498 	for (i = 0; i < table->count; i++) {
499 		if (FD_ISSET(table->table[i].sock, fds)) {
500 			table->table[i].handler(table->table[i].sock,
501 						table->table[i].eloop_data,
502 						table->table[i].user_data);
503 			if (table->changed)
504 				break;
505 		}
506 	}
507 }
508 
509 #endif /* CONFIG_ELOOP_SELECT */
510 
511 
512 #ifdef CONFIG_ELOOP_EPOLL
eloop_sock_table_dispatch(struct epoll_event * events,int nfds)513 static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
514 {
515 	struct eloop_sock *table;
516 	int i;
517 
518 	for (i = 0; i < nfds; i++) {
519 		table = &eloop.epoll_table[events[i].data.fd];
520 		if (table->handler == NULL)
521 			continue;
522 		table->handler(table->sock, table->eloop_data,
523 			       table->user_data);
524 	}
525 }
526 #endif /* CONFIG_ELOOP_EPOLL */
527 
528 
eloop_sock_table_destroy(struct eloop_sock_table * table)529 static void eloop_sock_table_destroy(struct eloop_sock_table *table)
530 {
531 	if (table) {
532 		int i;
533 		for (i = 0; i < table->count && table->table; i++) {
534 			wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
535 				   "sock=%d eloop_data=%p user_data=%p "
536 				   "handler=%p",
537 				   table->table[i].sock,
538 				   table->table[i].eloop_data,
539 				   table->table[i].user_data,
540 				   table->table[i].handler);
541 			wpa_trace_dump_funcname("eloop unregistered socket "
542 						"handler",
543 						table->table[i].handler);
544 			wpa_trace_dump("eloop sock", &table->table[i]);
545 		}
546 		os_free(table->table);
547 	}
548 }
549 
550 
eloop_register_read_sock(int sock,eloop_sock_handler handler,void * eloop_data,void * user_data)551 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
552 			     void *eloop_data, void *user_data)
553 {
554 	return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
555 				   eloop_data, user_data);
556 }
557 
558 
eloop_unregister_read_sock(int sock)559 void eloop_unregister_read_sock(int sock)
560 {
561 	eloop_unregister_sock(sock, EVENT_TYPE_READ);
562 }
563 
564 
eloop_get_sock_table(eloop_event_type type)565 static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
566 {
567 	switch (type) {
568 	case EVENT_TYPE_READ:
569 		return &eloop.readers;
570 	case EVENT_TYPE_WRITE:
571 		return &eloop.writers;
572 	case EVENT_TYPE_EXCEPTION:
573 		return &eloop.exceptions;
574 	}
575 
576 	return NULL;
577 }
578 
579 
eloop_register_sock(int sock,eloop_event_type type,eloop_sock_handler handler,void * eloop_data,void * user_data)580 int eloop_register_sock(int sock, eloop_event_type type,
581 			eloop_sock_handler handler,
582 			void *eloop_data, void *user_data)
583 {
584 	struct eloop_sock_table *table;
585 
586 	assert(sock >= 0);
587 	table = eloop_get_sock_table(type);
588 	return eloop_sock_table_add_sock(table, sock, handler,
589 					 eloop_data, user_data);
590 }
591 
592 
eloop_unregister_sock(int sock,eloop_event_type type)593 void eloop_unregister_sock(int sock, eloop_event_type type)
594 {
595 	struct eloop_sock_table *table;
596 
597 	table = eloop_get_sock_table(type);
598 	eloop_sock_table_remove_sock(table, sock);
599 }
600 
601 
eloop_register_timeout(unsigned int secs,unsigned int usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)602 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
603 			   eloop_timeout_handler handler,
604 			   void *eloop_data, void *user_data)
605 {
606 	struct eloop_timeout *timeout, *tmp;
607 	os_time_t now_sec;
608 
609 	timeout = os_zalloc(sizeof(*timeout));
610 	if (timeout == NULL)
611 		return -1;
612 	if (os_get_reltime(&timeout->time) < 0) {
613 		os_free(timeout);
614 		return -1;
615 	}
616 	now_sec = timeout->time.sec;
617 	timeout->time.sec += secs;
618 	if (timeout->time.sec < now_sec) {
619 		/*
620 		 * Integer overflow - assume long enough timeout to be assumed
621 		 * to be infinite, i.e., the timeout would never happen.
622 		 */
623 		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
624 			   "ever happen - ignore it", secs);
625 		os_free(timeout);
626 		return 0;
627 	}
628 	timeout->time.usec += usecs;
629 	while (timeout->time.usec >= 1000000) {
630 		timeout->time.sec++;
631 		timeout->time.usec -= 1000000;
632 	}
633 	timeout->eloop_data = eloop_data;
634 	timeout->user_data = user_data;
635 	timeout->handler = handler;
636 	wpa_trace_add_ref(timeout, eloop, eloop_data);
637 	wpa_trace_add_ref(timeout, user, user_data);
638 	wpa_trace_record(timeout);
639 
640 	/* Maintain timeouts in order of increasing time */
641 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
642 		if (os_reltime_before(&timeout->time, &tmp->time)) {
643 			dl_list_add(tmp->list.prev, &timeout->list);
644 			return 0;
645 		}
646 	}
647 	dl_list_add_tail(&eloop.timeout, &timeout->list);
648 
649 	return 0;
650 }
651 
652 
eloop_remove_timeout(struct eloop_timeout * timeout)653 static void eloop_remove_timeout(struct eloop_timeout *timeout)
654 {
655 	dl_list_del(&timeout->list);
656 	wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
657 	wpa_trace_remove_ref(timeout, user, timeout->user_data);
658 	os_free(timeout);
659 }
660 
661 
eloop_cancel_timeout(eloop_timeout_handler handler,void * eloop_data,void * user_data)662 int eloop_cancel_timeout(eloop_timeout_handler handler,
663 			 void *eloop_data, void *user_data)
664 {
665 	struct eloop_timeout *timeout, *prev;
666 	int removed = 0;
667 
668 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
669 			      struct eloop_timeout, list) {
670 		if (timeout->handler == handler &&
671 		    (timeout->eloop_data == eloop_data ||
672 		     eloop_data == ELOOP_ALL_CTX) &&
673 		    (timeout->user_data == user_data ||
674 		     user_data == ELOOP_ALL_CTX)) {
675 			eloop_remove_timeout(timeout);
676 			removed++;
677 		}
678 	}
679 
680 	return removed;
681 }
682 
683 
eloop_cancel_timeout_one(eloop_timeout_handler handler,void * eloop_data,void * user_data,struct os_reltime * remaining)684 int eloop_cancel_timeout_one(eloop_timeout_handler handler,
685 			     void *eloop_data, void *user_data,
686 			     struct os_reltime *remaining)
687 {
688 	struct eloop_timeout *timeout, *prev;
689 	int removed = 0;
690 	struct os_reltime now;
691 
692 	os_get_reltime(&now);
693 	remaining->sec = remaining->usec = 0;
694 
695 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
696 			      struct eloop_timeout, list) {
697 		if (timeout->handler == handler &&
698 		    (timeout->eloop_data == eloop_data) &&
699 		    (timeout->user_data == user_data)) {
700 			removed = 1;
701 			if (os_reltime_before(&now, &timeout->time))
702 				os_reltime_sub(&timeout->time, &now, remaining);
703 			eloop_remove_timeout(timeout);
704 			break;
705 		}
706 	}
707 	return removed;
708 }
709 
710 
eloop_is_timeout_registered(eloop_timeout_handler handler,void * eloop_data,void * user_data)711 int eloop_is_timeout_registered(eloop_timeout_handler handler,
712 				void *eloop_data, void *user_data)
713 {
714 	struct eloop_timeout *tmp;
715 
716 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
717 		if (tmp->handler == handler &&
718 		    tmp->eloop_data == eloop_data &&
719 		    tmp->user_data == user_data)
720 			return 1;
721 	}
722 
723 	return 0;
724 }
725 
726 
eloop_deplete_timeout(unsigned int req_secs,unsigned int req_usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)727 int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
728 			  eloop_timeout_handler handler, void *eloop_data,
729 			  void *user_data)
730 {
731 	struct os_reltime now, requested, remaining;
732 	struct eloop_timeout *tmp;
733 
734 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
735 		if (tmp->handler == handler &&
736 		    tmp->eloop_data == eloop_data &&
737 		    tmp->user_data == user_data) {
738 			requested.sec = req_secs;
739 			requested.usec = req_usecs;
740 			os_get_reltime(&now);
741 			os_reltime_sub(&tmp->time, &now, &remaining);
742 			if (os_reltime_before(&requested, &remaining)) {
743 				eloop_cancel_timeout(handler, eloop_data,
744 						     user_data);
745 				eloop_register_timeout(requested.sec,
746 						       requested.usec,
747 						       handler, eloop_data,
748 						       user_data);
749 				return 1;
750 			}
751 			return 0;
752 		}
753 	}
754 
755 	return -1;
756 }
757 
758 
eloop_replenish_timeout(unsigned int req_secs,unsigned int req_usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)759 int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
760 			    eloop_timeout_handler handler, void *eloop_data,
761 			    void *user_data)
762 {
763 	struct os_reltime now, requested, remaining;
764 	struct eloop_timeout *tmp;
765 
766 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
767 		if (tmp->handler == handler &&
768 		    tmp->eloop_data == eloop_data &&
769 		    tmp->user_data == user_data) {
770 			requested.sec = req_secs;
771 			requested.usec = req_usecs;
772 			os_get_reltime(&now);
773 			os_reltime_sub(&tmp->time, &now, &remaining);
774 			if (os_reltime_before(&remaining, &requested)) {
775 				eloop_cancel_timeout(handler, eloop_data,
776 						     user_data);
777 				eloop_register_timeout(requested.sec,
778 						       requested.usec,
779 						       handler, eloop_data,
780 						       user_data);
781 				return 1;
782 			}
783 			return 0;
784 		}
785 	}
786 
787 	return -1;
788 }
789 
790 
791 #ifndef CONFIG_NATIVE_WINDOWS
eloop_handle_alarm(int sig)792 static void eloop_handle_alarm(int sig)
793 {
794 	wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
795 		   "two seconds. Looks like there\n"
796 		   "is a bug that ends up in a busy loop that "
797 		   "prevents clean shutdown.\n"
798 		   "Killing program forcefully.\n");
799 	exit(1);
800 }
801 #endif /* CONFIG_NATIVE_WINDOWS */
802 
803 
eloop_handle_signal(int sig)804 static void eloop_handle_signal(int sig)
805 {
806 	int i;
807 
808 #ifndef CONFIG_NATIVE_WINDOWS
809 	if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
810 		/* Use SIGALRM to break out from potential busy loops that
811 		 * would not allow the program to be killed. */
812 		eloop.pending_terminate = 1;
813 		signal(SIGALRM, eloop_handle_alarm);
814 		alarm(2);
815 	}
816 #endif /* CONFIG_NATIVE_WINDOWS */
817 
818 	eloop.signaled++;
819 	for (i = 0; i < eloop.signal_count; i++) {
820 		if (eloop.signals[i].sig == sig) {
821 			eloop.signals[i].signaled++;
822 			break;
823 		}
824 	}
825 }
826 
827 
eloop_process_pending_signals(void)828 static void eloop_process_pending_signals(void)
829 {
830 	int i;
831 
832 	if (eloop.signaled == 0)
833 		return;
834 	eloop.signaled = 0;
835 
836 	if (eloop.pending_terminate) {
837 #ifndef CONFIG_NATIVE_WINDOWS
838 		alarm(0);
839 #endif /* CONFIG_NATIVE_WINDOWS */
840 		eloop.pending_terminate = 0;
841 	}
842 
843 	for (i = 0; i < eloop.signal_count; i++) {
844 		if (eloop.signals[i].signaled) {
845 			eloop.signals[i].signaled = 0;
846 			eloop.signals[i].handler(eloop.signals[i].sig,
847 						 eloop.signals[i].user_data);
848 		}
849 	}
850 }
851 
852 
eloop_register_signal(int sig,eloop_signal_handler handler,void * user_data)853 int eloop_register_signal(int sig, eloop_signal_handler handler,
854 			  void *user_data)
855 {
856 	struct eloop_signal *tmp;
857 
858 	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
859 			       sizeof(struct eloop_signal));
860 	if (tmp == NULL)
861 		return -1;
862 
863 	tmp[eloop.signal_count].sig = sig;
864 	tmp[eloop.signal_count].user_data = user_data;
865 	tmp[eloop.signal_count].handler = handler;
866 	tmp[eloop.signal_count].signaled = 0;
867 	eloop.signal_count++;
868 	eloop.signals = tmp;
869 	signal(sig, eloop_handle_signal);
870 
871 	return 0;
872 }
873 
874 
eloop_register_signal_terminate(eloop_signal_handler handler,void * user_data)875 int eloop_register_signal_terminate(eloop_signal_handler handler,
876 				    void *user_data)
877 {
878 	int ret = eloop_register_signal(SIGINT, handler, user_data);
879 	if (ret == 0)
880 		ret = eloop_register_signal(SIGTERM, handler, user_data);
881 	return ret;
882 }
883 
884 
eloop_register_signal_reconfig(eloop_signal_handler handler,void * user_data)885 int eloop_register_signal_reconfig(eloop_signal_handler handler,
886 				   void *user_data)
887 {
888 #ifdef CONFIG_NATIVE_WINDOWS
889 	return 0;
890 #else /* CONFIG_NATIVE_WINDOWS */
891 	return eloop_register_signal(SIGHUP, handler, user_data);
892 #endif /* CONFIG_NATIVE_WINDOWS */
893 }
894 
895 
eloop_run(void)896 void eloop_run(void)
897 {
898 #ifdef CONFIG_ELOOP_POLL
899 	int num_poll_fds;
900 	int timeout_ms = 0;
901 #endif /* CONFIG_ELOOP_POLL */
902 #ifdef CONFIG_ELOOP_SELECT
903 	fd_set *rfds, *wfds, *efds;
904 	struct timeval _tv;
905 #endif /* CONFIG_ELOOP_SELECT */
906 #ifdef CONFIG_ELOOP_EPOLL
907 	int timeout_ms = -1;
908 #endif /* CONFIG_ELOOP_EPOLL */
909 	int res;
910 	struct os_reltime tv, now;
911 
912 #ifdef CONFIG_ELOOP_SELECT
913 	rfds = os_malloc(sizeof(*rfds));
914 	wfds = os_malloc(sizeof(*wfds));
915 	efds = os_malloc(sizeof(*efds));
916 	if (rfds == NULL || wfds == NULL || efds == NULL)
917 		goto out;
918 #endif /* CONFIG_ELOOP_SELECT */
919 
920 	while (!eloop.terminate &&
921 	       (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
922 		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
923 		struct eloop_timeout *timeout;
924 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
925 					list);
926 		if (timeout) {
927 			os_get_reltime(&now);
928 			if (os_reltime_before(&now, &timeout->time))
929 				os_reltime_sub(&timeout->time, &now, &tv);
930 			else
931 				tv.sec = tv.usec = 0;
932 #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
933 			timeout_ms = tv.sec * 1000 + tv.usec / 1000;
934 #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
935 #ifdef CONFIG_ELOOP_SELECT
936 			_tv.tv_sec = tv.sec;
937 			_tv.tv_usec = tv.usec;
938 #endif /* CONFIG_ELOOP_SELECT */
939 		}
940 
941 #ifdef CONFIG_ELOOP_POLL
942 		num_poll_fds = eloop_sock_table_set_fds(
943 			&eloop.readers, &eloop.writers, &eloop.exceptions,
944 			eloop.pollfds, eloop.pollfds_map,
945 			eloop.max_pollfd_map);
946 		res = poll(eloop.pollfds, num_poll_fds,
947 			   timeout ? timeout_ms : -1);
948 #endif /* CONFIG_ELOOP_POLL */
949 #ifdef CONFIG_ELOOP_SELECT
950 		eloop_sock_table_set_fds(&eloop.readers, rfds);
951 		eloop_sock_table_set_fds(&eloop.writers, wfds);
952 		eloop_sock_table_set_fds(&eloop.exceptions, efds);
953 		res = select(eloop.max_sock + 1, rfds, wfds, efds,
954 			     timeout ? &_tv : NULL);
955 #endif /* CONFIG_ELOOP_SELECT */
956 #ifdef CONFIG_ELOOP_EPOLL
957 		if (eloop.count == 0) {
958 			res = 0;
959 		} else {
960 			res = epoll_wait(eloop.epollfd, eloop.epoll_events,
961 					 eloop.count, timeout_ms);
962 		}
963 #endif /* CONFIG_ELOOP_EPOLL */
964 		if (res < 0 && errno != EINTR && errno != 0) {
965 			wpa_printf(MSG_ERROR, "eloop: %s: %s",
966 #ifdef CONFIG_ELOOP_POLL
967 				   "poll"
968 #endif /* CONFIG_ELOOP_POLL */
969 #ifdef CONFIG_ELOOP_SELECT
970 				   "select"
971 #endif /* CONFIG_ELOOP_SELECT */
972 #ifdef CONFIG_ELOOP_EPOLL
973 				   "epoll"
974 #endif /* CONFIG_ELOOP_EPOLL */
975 				   , strerror(errno));
976 			goto out;
977 		}
978 		eloop_process_pending_signals();
979 
980 		/* check if some registered timeouts have occurred */
981 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
982 					list);
983 		if (timeout) {
984 			os_get_reltime(&now);
985 			if (!os_reltime_before(&now, &timeout->time)) {
986 				void *eloop_data = timeout->eloop_data;
987 				void *user_data = timeout->user_data;
988 				eloop_timeout_handler handler =
989 					timeout->handler;
990 				eloop_remove_timeout(timeout);
991 				handler(eloop_data, user_data);
992 			}
993 
994 		}
995 
996 		if (res <= 0)
997 			continue;
998 
999 #ifdef CONFIG_ELOOP_POLL
1000 		eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
1001 					  &eloop.exceptions, eloop.pollfds_map,
1002 					  eloop.max_pollfd_map);
1003 #endif /* CONFIG_ELOOP_POLL */
1004 #ifdef CONFIG_ELOOP_SELECT
1005 		eloop_sock_table_dispatch(&eloop.readers, rfds);
1006 		eloop_sock_table_dispatch(&eloop.writers, wfds);
1007 		eloop_sock_table_dispatch(&eloop.exceptions, efds);
1008 #endif /* CONFIG_ELOOP_SELECT */
1009 #ifdef CONFIG_ELOOP_EPOLL
1010 		eloop_sock_table_dispatch(eloop.epoll_events, res);
1011 #endif /* CONFIG_ELOOP_EPOLL */
1012 	}
1013 
1014 	eloop.terminate = 0;
1015 out:
1016 #ifdef CONFIG_ELOOP_SELECT
1017 	os_free(rfds);
1018 	os_free(wfds);
1019 	os_free(efds);
1020 #endif /* CONFIG_ELOOP_SELECT */
1021 	return;
1022 }
1023 
1024 
eloop_terminate(void)1025 void eloop_terminate(void)
1026 {
1027 	eloop.terminate = 1;
1028 }
1029 
1030 
eloop_destroy(void)1031 void eloop_destroy(void)
1032 {
1033 	struct eloop_timeout *timeout, *prev;
1034 	struct os_reltime now;
1035 
1036 	os_get_reltime(&now);
1037 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
1038 			      struct eloop_timeout, list) {
1039 		int sec, usec;
1040 		sec = timeout->time.sec - now.sec;
1041 		usec = timeout->time.usec - now.usec;
1042 		if (timeout->time.usec < now.usec) {
1043 			sec--;
1044 			usec += 1000000;
1045 		}
1046 		wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
1047 			   "eloop_data=%p user_data=%p handler=%p",
1048 			   sec, usec, timeout->eloop_data, timeout->user_data,
1049 			   timeout->handler);
1050 		wpa_trace_dump_funcname("eloop unregistered timeout handler",
1051 					timeout->handler);
1052 		wpa_trace_dump("eloop timeout", timeout);
1053 		eloop_remove_timeout(timeout);
1054 	}
1055 	eloop_sock_table_destroy(&eloop.readers);
1056 	eloop_sock_table_destroy(&eloop.writers);
1057 	eloop_sock_table_destroy(&eloop.exceptions);
1058 	os_free(eloop.signals);
1059 
1060 #ifdef CONFIG_ELOOP_POLL
1061 	os_free(eloop.pollfds);
1062 	os_free(eloop.pollfds_map);
1063 #endif /* CONFIG_ELOOP_POLL */
1064 #ifdef CONFIG_ELOOP_EPOLL
1065 	os_free(eloop.epoll_table);
1066 	os_free(eloop.epoll_events);
1067 	close(eloop.epollfd);
1068 #endif /* CONFIG_ELOOP_EPOLL */
1069 }
1070 
1071 
eloop_terminated(void)1072 int eloop_terminated(void)
1073 {
1074 	return eloop.terminate;
1075 }
1076 
1077 
eloop_wait_for_read_sock(int sock)1078 void eloop_wait_for_read_sock(int sock)
1079 {
1080 #ifdef CONFIG_ELOOP_POLL
1081 	struct pollfd pfd;
1082 
1083 	if (sock < 0)
1084 		return;
1085 
1086 	os_memset(&pfd, 0, sizeof(pfd));
1087 	pfd.fd = sock;
1088 	pfd.events = POLLIN;
1089 
1090 	poll(&pfd, 1, -1);
1091 #endif /* CONFIG_ELOOP_POLL */
1092 #if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
1093 	/*
1094 	 * We can use epoll() here. But epoll() requres 4 system calls.
1095 	 * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
1096 	 * epoll fd. So select() is better for performance here.
1097 	 */
1098 	fd_set rfds;
1099 
1100 	if (sock < 0)
1101 		return;
1102 
1103 	FD_ZERO(&rfds);
1104 	FD_SET(sock, &rfds);
1105 	select(sock + 1, &rfds, NULL, NULL, NULL);
1106 #endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
1107 }
1108 
1109 #ifdef CONFIG_ELOOP_SELECT
1110 #undef CONFIG_ELOOP_SELECT
1111 #endif /* CONFIG_ELOOP_SELECT */
1112