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
12
* See README and COPYING for more details.
26
eloop_sock_handler handler;
33
eloop_event_handler handler;
37
struct eloop_timeout {
41
eloop_timeout_handler handler;
42
struct eloop_timeout *next;
48
eloop_signal_handler handler;
57
struct eloop_sock *readers;
60
struct eloop_event *events;
62
struct eloop_timeout *timeout;
65
struct eloop_signal *signals;
67
int pending_terminate;
70
int reader_table_changed;
72
struct eloop_signal term_signal;
79
static struct eloop_data eloop;
82
int eloop_init(void *user_data)
84
os_memset(&eloop, 0, sizeof(eloop));
85
eloop.user_data = user_data;
86
eloop.num_handles = 1;
87
eloop.handles = os_malloc(eloop.num_handles *
88
sizeof(eloop.handles[0]));
89
if (eloop.handles == NULL)
92
eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
93
if (eloop.term_event == NULL) {
94
printf("CreateEvent() failed: %d\n",
95
(int) GetLastError());
96
os_free(eloop.handles);
104
static int eloop_prepare_handles(void)
108
if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
110
n = os_realloc(eloop.handles,
111
eloop.num_handles * 2 * sizeof(eloop.handles[0]));
115
eloop.num_handles *= 2;
120
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
121
void *eloop_data, void *user_data)
124
struct eloop_sock *tmp;
126
if (eloop_prepare_handles())
129
event = WSACreateEvent();
130
if (event == WSA_INVALID_EVENT) {
131
printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
135
if (WSAEventSelect(sock, event, FD_READ)) {
136
printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
137
WSACloseEvent(event);
140
tmp = os_realloc(eloop.readers,
141
(eloop.reader_count + 1) * sizeof(struct eloop_sock));
143
WSAEventSelect(sock, event, 0);
144
WSACloseEvent(event);
148
tmp[eloop.reader_count].sock = sock;
149
tmp[eloop.reader_count].eloop_data = eloop_data;
150
tmp[eloop.reader_count].user_data = user_data;
151
tmp[eloop.reader_count].handler = handler;
152
tmp[eloop.reader_count].event = event;
153
eloop.reader_count++;
155
if (sock > eloop.max_sock)
156
eloop.max_sock = sock;
157
eloop.reader_table_changed = 1;
163
void eloop_unregister_read_sock(int sock)
167
if (eloop.readers == NULL || eloop.reader_count == 0)
170
for (i = 0; i < eloop.reader_count; i++) {
171
if (eloop.readers[i].sock == sock)
174
if (i == eloop.reader_count)
177
WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
178
WSACloseEvent(eloop.readers[i].event);
180
if (i != eloop.reader_count - 1) {
181
os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
182
(eloop.reader_count - i - 1) *
183
sizeof(struct eloop_sock));
185
eloop.reader_count--;
186
eloop.reader_table_changed = 1;
190
int eloop_register_event(void *event, size_t event_size,
191
eloop_event_handler handler,
192
void *eloop_data, void *user_data)
194
struct eloop_event *tmp;
197
if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
200
if (eloop_prepare_handles())
203
tmp = os_realloc(eloop.events,
204
(eloop.event_count + 1) * sizeof(struct eloop_event));
208
tmp[eloop.event_count].eloop_data = eloop_data;
209
tmp[eloop.event_count].user_data = user_data;
210
tmp[eloop.event_count].handler = handler;
211
tmp[eloop.event_count].event = h;
219
void eloop_unregister_event(void *event, size_t event_size)
224
if (eloop.events == NULL || eloop.event_count == 0 ||
225
event_size != sizeof(HANDLE))
228
for (i = 0; i < eloop.event_count; i++) {
229
if (eloop.events[i].event == h)
232
if (i == eloop.event_count)
235
if (i != eloop.event_count - 1) {
236
os_memmove(&eloop.events[i], &eloop.events[i + 1],
237
(eloop.event_count - i - 1) *
238
sizeof(struct eloop_event));
244
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
245
eloop_timeout_handler handler,
246
void *eloop_data, void *user_data)
248
struct eloop_timeout *timeout, *tmp, *prev;
250
timeout = os_malloc(sizeof(*timeout));
253
os_get_time(&timeout->time);
254
timeout->time.sec += secs;
255
timeout->time.usec += usecs;
256
while (timeout->time.usec >= 1000000) {
258
timeout->time.usec -= 1000000;
260
timeout->eloop_data = eloop_data;
261
timeout->user_data = user_data;
262
timeout->handler = handler;
263
timeout->next = NULL;
265
if (eloop.timeout == NULL) {
266
eloop.timeout = timeout;
272
while (tmp != NULL) {
273
if (os_time_before(&timeout->time, &tmp->time))
280
timeout->next = eloop.timeout;
281
eloop.timeout = timeout;
283
timeout->next = prev->next;
284
prev->next = timeout;
291
int eloop_cancel_timeout(eloop_timeout_handler handler,
292
void *eloop_data, void *user_data)
294
struct eloop_timeout *timeout, *prev, *next;
298
timeout = eloop.timeout;
299
while (timeout != NULL) {
300
next = timeout->next;
302
if (timeout->handler == handler &&
303
(timeout->eloop_data == eloop_data ||
304
eloop_data == ELOOP_ALL_CTX) &&
305
(timeout->user_data == user_data ||
306
user_data == ELOOP_ALL_CTX)) {
308
eloop.timeout = next;
323
/* TODO: replace with suitable signal handler */
325
static void eloop_handle_signal(int sig)
330
for (i = 0; i < eloop.signal_count; i++) {
331
if (eloop.signals[i].sig == sig) {
332
eloop.signals[i].signaled++;
340
static void eloop_process_pending_signals(void)
344
if (eloop.signaled == 0)
348
if (eloop.pending_terminate) {
349
eloop.pending_terminate = 0;
352
for (i = 0; i < eloop.signal_count; i++) {
353
if (eloop.signals[i].signaled) {
354
eloop.signals[i].signaled = 0;
355
eloop.signals[i].handler(eloop.signals[i].sig,
357
eloop.signals[i].user_data);
361
if (eloop.term_signal.signaled) {
362
eloop.term_signal.signaled = 0;
363
eloop.term_signal.handler(eloop.term_signal.sig,
365
eloop.term_signal.user_data);
370
int eloop_register_signal(int sig, eloop_signal_handler handler,
373
struct eloop_signal *tmp;
375
tmp = os_realloc(eloop.signals,
376
(eloop.signal_count + 1) *
377
sizeof(struct eloop_signal));
381
tmp[eloop.signal_count].sig = sig;
382
tmp[eloop.signal_count].user_data = user_data;
383
tmp[eloop.signal_count].handler = handler;
384
tmp[eloop.signal_count].signaled = 0;
385
eloop.signal_count++;
388
/* TODO: register signal handler */
395
static BOOL eloop_handle_console_ctrl(DWORD type)
399
case CTRL_BREAK_EVENT:
401
eloop.term_signal.signaled++;
402
SetEvent(eloop.term_event);
408
#endif /* _WIN32_WCE */
411
int eloop_register_signal_terminate(eloop_signal_handler handler,
415
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
417
printf("SetConsoleCtrlHandler() failed: %d\n",
418
(int) GetLastError());
421
#endif /* _WIN32_WCE */
423
eloop.term_signal.handler = handler;
424
eloop.term_signal.user_data = user_data;
430
int eloop_register_signal_reconfig(eloop_signal_handler handler,
440
struct os_time tv, now;
441
DWORD count, ret, timeout, err;
444
while (!eloop.terminate &&
445
(eloop.timeout || eloop.reader_count > 0 ||
446
eloop.event_count > 0)) {
449
if (os_time_before(&now, &eloop.timeout->time))
450
os_time_sub(&eloop.timeout->time, &now, &tv);
452
tv.sec = tv.usec = 0;
456
for (i = 0; i < eloop.event_count; i++)
457
eloop.handles[count++] = eloop.events[i].event;
459
for (i = 0; i < eloop.reader_count; i++)
460
eloop.handles[count++] = eloop.readers[i].event;
462
if (eloop.term_event)
463
eloop.handles[count++] = eloop.term_event;
466
timeout = tv.sec * 1000 + tv.usec / 1000;
470
if (count > MAXIMUM_WAIT_OBJECTS) {
471
printf("WaitForMultipleObjects: Too many events: "
472
"%d > %d (ignoring extra events)\n",
473
(int) count, MAXIMUM_WAIT_OBJECTS);
474
count = MAXIMUM_WAIT_OBJECTS;
477
ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
479
#else /* _WIN32_WCE */
480
ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
482
#endif /* _WIN32_WCE */
483
err = GetLastError();
485
eloop_process_pending_signals();
487
/* check if some registered timeouts have occurred */
489
struct eloop_timeout *tmp;
492
if (!os_time_before(&now, &eloop.timeout->time)) {
494
eloop.timeout = eloop.timeout->next;
495
tmp->handler(tmp->eloop_data,
502
if (ret == WAIT_FAILED) {
503
printf("WaitForMultipleObjects(count=%d) failed: %d\n",
504
(int) count, (int) err);
510
if (ret == WAIT_IO_COMPLETION)
512
#endif /* _WIN32_WCE */
514
if (ret == WAIT_TIMEOUT)
517
while (ret >= WAIT_OBJECT_0 &&
518
ret < WAIT_OBJECT_0 + eloop.event_count) {
519
eloop.events[ret].handler(
520
eloop.events[ret].eloop_data,
521
eloop.events[ret].user_data);
522
ret = WaitForMultipleObjects(eloop.event_count,
523
eloop.handles, FALSE, 0);
526
eloop.reader_table_changed = 0;
527
for (i = 0; i < eloop.reader_count; i++) {
528
WSANETWORKEVENTS events;
529
if (WSAEnumNetworkEvents(eloop.readers[i].sock,
530
eloop.readers[i].event,
532
(events.lNetworkEvents & FD_READ)) {
533
eloop.readers[i].handler(
534
eloop.readers[i].sock,
535
eloop.readers[i].eloop_data,
536
eloop.readers[i].user_data);
537
if (eloop.reader_table_changed)
545
void eloop_terminate(void)
548
SetEvent(eloop.term_event);
552
void eloop_destroy(void)
554
struct eloop_timeout *timeout, *prev;
556
timeout = eloop.timeout;
557
while (timeout != NULL) {
559
timeout = timeout->next;
562
os_free(eloop.readers);
563
os_free(eloop.signals);
564
if (eloop.term_event)
565
CloseHandle(eloop.term_event);
566
os_free(eloop.handles);
567
eloop.handles = NULL;
568
os_free(eloop.events);
573
int eloop_terminated(void)
575
return eloop.terminate;
579
void eloop_wait_for_read_sock(int sock)
583
event = WSACreateEvent();
584
if (event == WSA_INVALID_EVENT) {
585
printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
589
if (WSAEventSelect(sock, event, FD_READ)) {
590
printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
591
WSACloseEvent(event);
595
WaitForSingleObject(event, INFINITE);
596
WSAEventSelect(sock, event, 0);
597
WSACloseEvent(event);
601
void * eloop_get_user_data(void)
603
return eloop.user_data;