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