nl80211: Fix a typo
[hostap-gosc2009.git] / src / utils / eloop_win.c
blob94cc72d04c6b6fc06662221b0b82707f80b6b574
1 /*
2 * Event loop based on Windows events and WaitForMultipleObjects
3 * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
16 #include <winsock2.h>
18 #include "common.h"
19 #include "eloop.h"
22 struct eloop_sock {
23 int sock;
24 void *eloop_data;
25 void *user_data;
26 eloop_sock_handler handler;
27 WSAEVENT event;
30 struct eloop_event {
31 void *eloop_data;
32 void *user_data;
33 eloop_event_handler handler;
34 HANDLE event;
37 struct eloop_timeout {
38 struct os_time time;
39 void *eloop_data;
40 void *user_data;
41 eloop_timeout_handler handler;
42 struct eloop_timeout *next;
45 struct eloop_signal {
46 int sig;
47 void *user_data;
48 eloop_signal_handler handler;
49 int signaled;
52 struct eloop_data {
53 int max_sock;
54 size_t reader_count;
55 struct eloop_sock *readers;
57 size_t event_count;
58 struct eloop_event *events;
60 struct eloop_timeout *timeout;
62 int signal_count;
63 struct eloop_signal *signals;
64 int signaled;
65 int pending_terminate;
67 int terminate;
68 int reader_table_changed;
70 struct eloop_signal term_signal;
71 HANDLE term_event;
73 HANDLE *handles;
74 size_t num_handles;
77 static struct eloop_data eloop;
80 int eloop_init(void)
82 os_memset(&eloop, 0, sizeof(eloop));
83 eloop.num_handles = 1;
84 eloop.handles = os_malloc(eloop.num_handles *
85 sizeof(eloop.handles[0]));
86 if (eloop.handles == NULL)
87 return -1;
89 eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
90 if (eloop.term_event == NULL) {
91 printf("CreateEvent() failed: %d\n",
92 (int) GetLastError());
93 os_free(eloop.handles);
94 return -1;
97 return 0;
101 static int eloop_prepare_handles(void)
103 HANDLE *n;
105 if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
106 return 0;
107 n = os_realloc(eloop.handles,
108 eloop.num_handles * 2 * sizeof(eloop.handles[0]));
109 if (n == NULL)
110 return -1;
111 eloop.handles = n;
112 eloop.num_handles *= 2;
113 return 0;
117 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
118 void *eloop_data, void *user_data)
120 WSAEVENT event;
121 struct eloop_sock *tmp;
123 if (eloop_prepare_handles())
124 return -1;
126 event = WSACreateEvent();
127 if (event == WSA_INVALID_EVENT) {
128 printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
129 return -1;
132 if (WSAEventSelect(sock, event, FD_READ)) {
133 printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
134 WSACloseEvent(event);
135 return -1;
137 tmp = os_realloc(eloop.readers,
138 (eloop.reader_count + 1) * sizeof(struct eloop_sock));
139 if (tmp == NULL) {
140 WSAEventSelect(sock, event, 0);
141 WSACloseEvent(event);
142 return -1;
145 tmp[eloop.reader_count].sock = sock;
146 tmp[eloop.reader_count].eloop_data = eloop_data;
147 tmp[eloop.reader_count].user_data = user_data;
148 tmp[eloop.reader_count].handler = handler;
149 tmp[eloop.reader_count].event = event;
150 eloop.reader_count++;
151 eloop.readers = tmp;
152 if (sock > eloop.max_sock)
153 eloop.max_sock = sock;
154 eloop.reader_table_changed = 1;
156 return 0;
160 void eloop_unregister_read_sock(int sock)
162 size_t i;
164 if (eloop.readers == NULL || eloop.reader_count == 0)
165 return;
167 for (i = 0; i < eloop.reader_count; i++) {
168 if (eloop.readers[i].sock == sock)
169 break;
171 if (i == eloop.reader_count)
172 return;
174 WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
175 WSACloseEvent(eloop.readers[i].event);
177 if (i != eloop.reader_count - 1) {
178 os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
179 (eloop.reader_count - i - 1) *
180 sizeof(struct eloop_sock));
182 eloop.reader_count--;
183 eloop.reader_table_changed = 1;
187 int eloop_register_event(void *event, size_t event_size,
188 eloop_event_handler handler,
189 void *eloop_data, void *user_data)
191 struct eloop_event *tmp;
192 HANDLE h = event;
194 if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
195 return -1;
197 if (eloop_prepare_handles())
198 return -1;
200 tmp = os_realloc(eloop.events,
201 (eloop.event_count + 1) * sizeof(struct eloop_event));
202 if (tmp == NULL)
203 return -1;
205 tmp[eloop.event_count].eloop_data = eloop_data;
206 tmp[eloop.event_count].user_data = user_data;
207 tmp[eloop.event_count].handler = handler;
208 tmp[eloop.event_count].event = h;
209 eloop.event_count++;
210 eloop.events = tmp;
212 return 0;
216 void eloop_unregister_event(void *event, size_t event_size)
218 size_t i;
219 HANDLE h = event;
221 if (eloop.events == NULL || eloop.event_count == 0 ||
222 event_size != sizeof(HANDLE))
223 return;
225 for (i = 0; i < eloop.event_count; i++) {
226 if (eloop.events[i].event == h)
227 break;
229 if (i == eloop.event_count)
230 return;
232 if (i != eloop.event_count - 1) {
233 os_memmove(&eloop.events[i], &eloop.events[i + 1],
234 (eloop.event_count - i - 1) *
235 sizeof(struct eloop_event));
237 eloop.event_count--;
241 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
242 eloop_timeout_handler handler,
243 void *eloop_data, void *user_data)
245 struct eloop_timeout *timeout, *tmp, *prev;
247 timeout = os_malloc(sizeof(*timeout));
248 if (timeout == NULL)
249 return -1;
250 os_get_time(&timeout->time);
251 timeout->time.sec += secs;
252 timeout->time.usec += usecs;
253 while (timeout->time.usec >= 1000000) {
254 timeout->time.sec++;
255 timeout->time.usec -= 1000000;
257 timeout->eloop_data = eloop_data;
258 timeout->user_data = user_data;
259 timeout->handler = handler;
260 timeout->next = NULL;
262 if (eloop.timeout == NULL) {
263 eloop.timeout = timeout;
264 return 0;
267 prev = NULL;
268 tmp = eloop.timeout;
269 while (tmp != NULL) {
270 if (os_time_before(&timeout->time, &tmp->time))
271 break;
272 prev = tmp;
273 tmp = tmp->next;
276 if (prev == NULL) {
277 timeout->next = eloop.timeout;
278 eloop.timeout = timeout;
279 } else {
280 timeout->next = prev->next;
281 prev->next = timeout;
284 return 0;
288 int eloop_cancel_timeout(eloop_timeout_handler handler,
289 void *eloop_data, void *user_data)
291 struct eloop_timeout *timeout, *prev, *next;
292 int removed = 0;
294 prev = NULL;
295 timeout = eloop.timeout;
296 while (timeout != NULL) {
297 next = timeout->next;
299 if (timeout->handler == handler &&
300 (timeout->eloop_data == eloop_data ||
301 eloop_data == ELOOP_ALL_CTX) &&
302 (timeout->user_data == user_data ||
303 user_data == ELOOP_ALL_CTX)) {
304 if (prev == NULL)
305 eloop.timeout = next;
306 else
307 prev->next = next;
308 os_free(timeout);
309 removed++;
310 } else
311 prev = timeout;
313 timeout = next;
316 return removed;
320 int eloop_is_timeout_registered(eloop_timeout_handler handler,
321 void *eloop_data, void *user_data)
323 struct eloop_timeout *tmp;
325 tmp = eloop.timeout;
326 while (tmp != NULL) {
327 if (tmp->handler == handler &&
328 tmp->eloop_data == eloop_data &&
329 tmp->user_data == user_data)
330 return 1;
332 tmp = tmp->next;
335 return 0;
339 /* TODO: replace with suitable signal handler */
340 #if 0
341 static void eloop_handle_signal(int sig)
343 int i;
345 eloop.signaled++;
346 for (i = 0; i < eloop.signal_count; i++) {
347 if (eloop.signals[i].sig == sig) {
348 eloop.signals[i].signaled++;
349 break;
353 #endif
356 static void eloop_process_pending_signals(void)
358 int i;
360 if (eloop.signaled == 0)
361 return;
362 eloop.signaled = 0;
364 if (eloop.pending_terminate) {
365 eloop.pending_terminate = 0;
368 for (i = 0; i < eloop.signal_count; i++) {
369 if (eloop.signals[i].signaled) {
370 eloop.signals[i].signaled = 0;
371 eloop.signals[i].handler(eloop.signals[i].sig,
372 eloop.signals[i].user_data);
376 if (eloop.term_signal.signaled) {
377 eloop.term_signal.signaled = 0;
378 eloop.term_signal.handler(eloop.term_signal.sig,
379 eloop.term_signal.user_data);
384 int eloop_register_signal(int sig, eloop_signal_handler handler,
385 void *user_data)
387 struct eloop_signal *tmp;
389 tmp = os_realloc(eloop.signals,
390 (eloop.signal_count + 1) *
391 sizeof(struct eloop_signal));
392 if (tmp == NULL)
393 return -1;
395 tmp[eloop.signal_count].sig = sig;
396 tmp[eloop.signal_count].user_data = user_data;
397 tmp[eloop.signal_count].handler = handler;
398 tmp[eloop.signal_count].signaled = 0;
399 eloop.signal_count++;
400 eloop.signals = tmp;
402 /* TODO: register signal handler */
404 return 0;
408 #ifndef _WIN32_WCE
409 static BOOL eloop_handle_console_ctrl(DWORD type)
411 switch (type) {
412 case CTRL_C_EVENT:
413 case CTRL_BREAK_EVENT:
414 eloop.signaled++;
415 eloop.term_signal.signaled++;
416 SetEvent(eloop.term_event);
417 return TRUE;
418 default:
419 return FALSE;
422 #endif /* _WIN32_WCE */
425 int eloop_register_signal_terminate(eloop_signal_handler handler,
426 void *user_data)
428 #ifndef _WIN32_WCE
429 if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
430 TRUE) == 0) {
431 printf("SetConsoleCtrlHandler() failed: %d\n",
432 (int) GetLastError());
433 return -1;
435 #endif /* _WIN32_WCE */
437 eloop.term_signal.handler = handler;
438 eloop.term_signal.user_data = user_data;
440 return 0;
444 int eloop_register_signal_reconfig(eloop_signal_handler handler,
445 void *user_data)
447 /* TODO */
448 return 0;
452 void eloop_run(void)
454 struct os_time tv, now;
455 DWORD count, ret, timeout, err;
456 size_t i;
458 while (!eloop.terminate &&
459 (eloop.timeout || eloop.reader_count > 0 ||
460 eloop.event_count > 0)) {
461 tv.sec = tv.usec = 0;
462 if (eloop.timeout) {
463 os_get_time(&now);
464 if (os_time_before(&now, &eloop.timeout->time))
465 os_time_sub(&eloop.timeout->time, &now, &tv);
468 count = 0;
469 for (i = 0; i < eloop.event_count; i++)
470 eloop.handles[count++] = eloop.events[i].event;
472 for (i = 0; i < eloop.reader_count; i++)
473 eloop.handles[count++] = eloop.readers[i].event;
475 if (eloop.term_event)
476 eloop.handles[count++] = eloop.term_event;
478 if (eloop.timeout)
479 timeout = tv.sec * 1000 + tv.usec / 1000;
480 else
481 timeout = INFINITE;
483 if (count > MAXIMUM_WAIT_OBJECTS) {
484 printf("WaitForMultipleObjects: Too many events: "
485 "%d > %d (ignoring extra events)\n",
486 (int) count, MAXIMUM_WAIT_OBJECTS);
487 count = MAXIMUM_WAIT_OBJECTS;
489 #ifdef _WIN32_WCE
490 ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
491 timeout);
492 #else /* _WIN32_WCE */
493 ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
494 timeout, TRUE);
495 #endif /* _WIN32_WCE */
496 err = GetLastError();
498 eloop_process_pending_signals();
500 /* check if some registered timeouts have occurred */
501 if (eloop.timeout) {
502 struct eloop_timeout *tmp;
504 os_get_time(&now);
505 if (!os_time_before(&now, &eloop.timeout->time)) {
506 tmp = eloop.timeout;
507 eloop.timeout = eloop.timeout->next;
508 tmp->handler(tmp->eloop_data,
509 tmp->user_data);
510 os_free(tmp);
515 if (ret == WAIT_FAILED) {
516 printf("WaitForMultipleObjects(count=%d) failed: %d\n",
517 (int) count, (int) err);
518 os_sleep(1, 0);
519 continue;
522 #ifndef _WIN32_WCE
523 if (ret == WAIT_IO_COMPLETION)
524 continue;
525 #endif /* _WIN32_WCE */
527 if (ret == WAIT_TIMEOUT)
528 continue;
530 while (ret >= WAIT_OBJECT_0 &&
531 ret < WAIT_OBJECT_0 + eloop.event_count) {
532 eloop.events[ret].handler(
533 eloop.events[ret].eloop_data,
534 eloop.events[ret].user_data);
535 ret = WaitForMultipleObjects(eloop.event_count,
536 eloop.handles, FALSE, 0);
539 eloop.reader_table_changed = 0;
540 for (i = 0; i < eloop.reader_count; i++) {
541 WSANETWORKEVENTS events;
542 if (WSAEnumNetworkEvents(eloop.readers[i].sock,
543 eloop.readers[i].event,
544 &events) == 0 &&
545 (events.lNetworkEvents & FD_READ)) {
546 eloop.readers[i].handler(
547 eloop.readers[i].sock,
548 eloop.readers[i].eloop_data,
549 eloop.readers[i].user_data);
550 if (eloop.reader_table_changed)
551 break;
558 void eloop_terminate(void)
560 eloop.terminate = 1;
561 SetEvent(eloop.term_event);
565 void eloop_destroy(void)
567 struct eloop_timeout *timeout, *prev;
569 timeout = eloop.timeout;
570 while (timeout != NULL) {
571 prev = timeout;
572 timeout = timeout->next;
573 os_free(prev);
575 os_free(eloop.readers);
576 os_free(eloop.signals);
577 if (eloop.term_event)
578 CloseHandle(eloop.term_event);
579 os_free(eloop.handles);
580 eloop.handles = NULL;
581 os_free(eloop.events);
582 eloop.events = NULL;
586 int eloop_terminated(void)
588 return eloop.terminate;
592 void eloop_wait_for_read_sock(int sock)
594 WSAEVENT event;
596 event = WSACreateEvent();
597 if (event == WSA_INVALID_EVENT) {
598 printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
599 return;
602 if (WSAEventSelect(sock, event, FD_READ)) {
603 printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
604 WSACloseEvent(event);
605 return ;
608 WaitForSingleObject(event, INFINITE);
609 WSAEventSelect(sock, event, 0);
610 WSACloseEvent(event);