]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/wpa/src/utils/eloop_none.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / wpa / src / utils / eloop_none.c
1 /*
2  * Event loop - empty template (basic structure, but no OS specific operations)
3  * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "eloop.h"
13
14
15 struct eloop_sock {
16         int sock;
17         void *eloop_data;
18         void *user_data;
19         void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
20 };
21
22 struct eloop_timeout {
23         struct os_time time;
24         void *eloop_data;
25         void *user_data;
26         void (*handler)(void *eloop_ctx, void *sock_ctx);
27         struct eloop_timeout *next;
28 };
29
30 struct eloop_signal {
31         int sig;
32         void *user_data;
33         void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
34         int signaled;
35 };
36
37 struct eloop_data {
38         int max_sock, reader_count;
39         struct eloop_sock *readers;
40
41         struct eloop_timeout *timeout;
42
43         int signal_count;
44         struct eloop_signal *signals;
45         int signaled;
46         int pending_terminate;
47
48         int terminate;
49         int reader_table_changed;
50 };
51
52 static struct eloop_data eloop;
53
54
55 int eloop_init(void)
56 {
57         memset(&eloop, 0, sizeof(eloop));
58         return 0;
59 }
60
61
62 int eloop_register_read_sock(int sock,
63                              void (*handler)(int sock, void *eloop_ctx,
64                                              void *sock_ctx),
65                              void *eloop_data, void *user_data)
66 {
67         struct eloop_sock *tmp;
68
69         tmp = (struct eloop_sock *)
70                 realloc(eloop.readers,
71                         (eloop.reader_count + 1) * sizeof(struct eloop_sock));
72         if (tmp == NULL)
73                 return -1;
74
75         tmp[eloop.reader_count].sock = sock;
76         tmp[eloop.reader_count].eloop_data = eloop_data;
77         tmp[eloop.reader_count].user_data = user_data;
78         tmp[eloop.reader_count].handler = handler;
79         eloop.reader_count++;
80         eloop.readers = tmp;
81         if (sock > eloop.max_sock)
82                 eloop.max_sock = sock;
83         eloop.reader_table_changed = 1;
84
85         return 0;
86 }
87
88
89 void eloop_unregister_read_sock(int sock)
90 {
91         int i;
92
93         if (eloop.readers == NULL || eloop.reader_count == 0)
94                 return;
95
96         for (i = 0; i < eloop.reader_count; i++) {
97                 if (eloop.readers[i].sock == sock)
98                         break;
99         }
100         if (i == eloop.reader_count)
101                 return;
102         if (i != eloop.reader_count - 1) {
103                 memmove(&eloop.readers[i], &eloop.readers[i + 1],
104                         (eloop.reader_count - i - 1) *
105                         sizeof(struct eloop_sock));
106         }
107         eloop.reader_count--;
108         eloop.reader_table_changed = 1;
109 }
110
111
112 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
113                            void (*handler)(void *eloop_ctx, void *timeout_ctx),
114                            void *eloop_data, void *user_data)
115 {
116         struct eloop_timeout *timeout, *tmp, *prev;
117
118         timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
119         if (timeout == NULL)
120                 return -1;
121         os_get_time(&timeout->time);
122         timeout->time.sec += secs;
123         timeout->time.usec += usecs;
124         while (timeout->time.usec >= 1000000) {
125                 timeout->time.sec++;
126                 timeout->time.usec -= 1000000;
127         }
128         timeout->eloop_data = eloop_data;
129         timeout->user_data = user_data;
130         timeout->handler = handler;
131         timeout->next = NULL;
132
133         if (eloop.timeout == NULL) {
134                 eloop.timeout = timeout;
135                 return 0;
136         }
137
138         prev = NULL;
139         tmp = eloop.timeout;
140         while (tmp != NULL) {
141                 if (os_time_before(&timeout->time, &tmp->time))
142                         break;
143                 prev = tmp;
144                 tmp = tmp->next;
145         }
146
147         if (prev == NULL) {
148                 timeout->next = eloop.timeout;
149                 eloop.timeout = timeout;
150         } else {
151                 timeout->next = prev->next;
152                 prev->next = timeout;
153         }
154
155         return 0;
156 }
157
158
159 int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
160                          void *eloop_data, void *user_data)
161 {
162         struct eloop_timeout *timeout, *prev, *next;
163         int removed = 0;
164
165         prev = NULL;
166         timeout = eloop.timeout;
167         while (timeout != NULL) {
168                 next = timeout->next;
169
170                 if (timeout->handler == handler &&
171                     (timeout->eloop_data == eloop_data ||
172                      eloop_data == ELOOP_ALL_CTX) &&
173                     (timeout->user_data == user_data ||
174                      user_data == ELOOP_ALL_CTX)) {
175                         if (prev == NULL)
176                                 eloop.timeout = next;
177                         else
178                                 prev->next = next;
179                         free(timeout);
180                         removed++;
181                 } else
182                         prev = timeout;
183
184                 timeout = next;
185         }
186
187         return removed;
188 }
189
190
191 int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
192                                                 void *timeout_ctx),
193                                 void *eloop_data, void *user_data)
194 {
195         struct eloop_timeout *tmp;
196
197         tmp = eloop.timeout;
198         while (tmp != NULL) {
199                 if (tmp->handler == handler &&
200                     tmp->eloop_data == eloop_data &&
201                     tmp->user_data == user_data)
202                         return 1;
203
204                 tmp = tmp->next;
205         }
206
207         return 0;
208 }
209
210
211 /* TODO: replace with suitable signal handler */
212 #if 0
213 static void eloop_handle_signal(int sig)
214 {
215         int i;
216
217         eloop.signaled++;
218         for (i = 0; i < eloop.signal_count; i++) {
219                 if (eloop.signals[i].sig == sig) {
220                         eloop.signals[i].signaled++;
221                         break;
222                 }
223         }
224 }
225 #endif
226
227
228 static void eloop_process_pending_signals(void)
229 {
230         int i;
231
232         if (eloop.signaled == 0)
233                 return;
234         eloop.signaled = 0;
235
236         if (eloop.pending_terminate) {
237                 eloop.pending_terminate = 0;
238         }
239
240         for (i = 0; i < eloop.signal_count; i++) {
241                 if (eloop.signals[i].signaled) {
242                         eloop.signals[i].signaled = 0;
243                         eloop.signals[i].handler(eloop.signals[i].sig,
244                                                  eloop.user_data,
245                                                  eloop.signals[i].user_data);
246                 }
247         }
248 }
249
250
251 int eloop_register_signal(int sig,
252                           void (*handler)(int sig, void *eloop_ctx,
253                                           void *signal_ctx),
254                           void *user_data)
255 {
256         struct eloop_signal *tmp;
257
258         tmp = (struct eloop_signal *)
259                 realloc(eloop.signals,
260                         (eloop.signal_count + 1) *
261                         sizeof(struct eloop_signal));
262         if (tmp == NULL)
263                 return -1;
264
265         tmp[eloop.signal_count].sig = sig;
266         tmp[eloop.signal_count].user_data = user_data;
267         tmp[eloop.signal_count].handler = handler;
268         tmp[eloop.signal_count].signaled = 0;
269         eloop.signal_count++;
270         eloop.signals = tmp;
271
272         /* TODO: register signal handler */
273
274         return 0;
275 }
276
277
278 int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx,
279                                                     void *signal_ctx),
280                                     void *user_data)
281 {
282 #if 0
283         /* TODO: for example */
284         int ret = eloop_register_signal(SIGINT, handler, user_data);
285         if (ret == 0)
286                 ret = eloop_register_signal(SIGTERM, handler, user_data);
287         return ret;
288 #endif
289         return 0;
290 }
291
292
293 int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx,
294                                                    void *signal_ctx),
295                                    void *user_data)
296 {
297 #if 0
298         /* TODO: for example */
299         return eloop_register_signal(SIGHUP, handler, user_data);
300 #endif
301         return 0;
302 }
303
304
305 void eloop_run(void)
306 {
307         int i;
308         struct os_time tv, now;
309
310         while (!eloop.terminate &&
311                 (eloop.timeout || eloop.reader_count > 0)) {
312                 if (eloop.timeout) {
313                         os_get_time(&now);
314                         if (os_time_before(&now, &eloop.timeout->time))
315                                 os_time_sub(&eloop.timeout->time, &now, &tv);
316                         else
317                                 tv.sec = tv.usec = 0;
318                 }
319
320                 /*
321                  * TODO: wait for any event (read socket ready, timeout (tv),
322                  * signal
323                  */
324                 os_sleep(1, 0); /* just a dummy wait for testing */
325
326                 eloop_process_pending_signals();
327
328                 /* check if some registered timeouts have occurred */
329                 if (eloop.timeout) {
330                         struct eloop_timeout *tmp;
331
332                         os_get_time(&now);
333                         if (!os_time_before(&now, &eloop.timeout->time)) {
334                                 tmp = eloop.timeout;
335                                 eloop.timeout = eloop.timeout->next;
336                                 tmp->handler(tmp->eloop_data,
337                                              tmp->user_data);
338                                 free(tmp);
339                         }
340
341                 }
342
343                 eloop.reader_table_changed = 0;
344                 for (i = 0; i < eloop.reader_count; i++) {
345                         /*
346                          * TODO: call each handler that has pending data to
347                          * read
348                          */
349                         if (0 /* TODO: eloop.readers[i].sock ready */) {
350                                 eloop.readers[i].handler(
351                                         eloop.readers[i].sock,
352                                         eloop.readers[i].eloop_data,
353                                         eloop.readers[i].user_data);
354                                 if (eloop.reader_table_changed)
355                                         break;
356                         }
357                 }
358         }
359 }
360
361
362 void eloop_terminate(void)
363 {
364         eloop.terminate = 1;
365 }
366
367
368 void eloop_destroy(void)
369 {
370         struct eloop_timeout *timeout, *prev;
371
372         timeout = eloop.timeout;
373         while (timeout != NULL) {
374                 prev = timeout;
375                 timeout = timeout->next;
376                 free(prev);
377         }
378         free(eloop.readers);
379         free(eloop.signals);
380 }
381
382
383 int eloop_terminated(void)
384 {
385         return eloop.terminate;
386 }
387
388
389 void eloop_wait_for_read_sock(int sock)
390 {
391         /*
392          * TODO: wait for the file descriptor to have something available for
393          * reading
394          */
395 }