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