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