eloop_win.c revision 209139
1209139Srpaulo/*
2209139Srpaulo * Event loop based on Windows events and WaitForMultipleObjects
3209139Srpaulo * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
4209139Srpaulo *
5209139Srpaulo * This program is free software; you can redistribute it and/or modify
6209139Srpaulo * it under the terms of the GNU General Public License version 2 as
7209139Srpaulo * published by the Free Software Foundation.
8209139Srpaulo *
9209139Srpaulo * Alternatively, this software may be distributed under the terms of BSD
10209139Srpaulo * license.
11209139Srpaulo *
12209139Srpaulo * See README and COPYING for more details.
13209139Srpaulo */
14209139Srpaulo
15209139Srpaulo#include "includes.h"
16209139Srpaulo#include <winsock2.h>
17209139Srpaulo
18209139Srpaulo#include "common.h"
19209139Srpaulo#include "eloop.h"
20209139Srpaulo
21209139Srpaulo
22209139Srpaulostruct eloop_sock {
23209139Srpaulo	int sock;
24209139Srpaulo	void *eloop_data;
25209139Srpaulo	void *user_data;
26209139Srpaulo	eloop_sock_handler handler;
27209139Srpaulo	WSAEVENT event;
28209139Srpaulo};
29209139Srpaulo
30209139Srpaulostruct eloop_event {
31209139Srpaulo	void *eloop_data;
32209139Srpaulo	void *user_data;
33209139Srpaulo	eloop_event_handler handler;
34209139Srpaulo	HANDLE event;
35209139Srpaulo};
36209139Srpaulo
37209139Srpaulostruct eloop_timeout {
38209139Srpaulo	struct os_time time;
39209139Srpaulo	void *eloop_data;
40209139Srpaulo	void *user_data;
41209139Srpaulo	eloop_timeout_handler handler;
42209139Srpaulo	struct eloop_timeout *next;
43209139Srpaulo};
44209139Srpaulo
45209139Srpaulostruct eloop_signal {
46209139Srpaulo	int sig;
47209139Srpaulo	void *user_data;
48209139Srpaulo	eloop_signal_handler handler;
49209139Srpaulo	int signaled;
50209139Srpaulo};
51209139Srpaulo
52209139Srpaulostruct eloop_data {
53209139Srpaulo	void *user_data;
54209139Srpaulo
55209139Srpaulo	int max_sock;
56209139Srpaulo	size_t reader_count;
57209139Srpaulo	struct eloop_sock *readers;
58209139Srpaulo
59209139Srpaulo	size_t event_count;
60209139Srpaulo	struct eloop_event *events;
61209139Srpaulo
62209139Srpaulo	struct eloop_timeout *timeout;
63209139Srpaulo
64209139Srpaulo	int signal_count;
65209139Srpaulo	struct eloop_signal *signals;
66209139Srpaulo	int signaled;
67209139Srpaulo	int pending_terminate;
68209139Srpaulo
69209139Srpaulo	int terminate;
70209139Srpaulo	int reader_table_changed;
71209139Srpaulo
72209139Srpaulo	struct eloop_signal term_signal;
73209139Srpaulo	HANDLE term_event;
74209139Srpaulo
75209139Srpaulo	HANDLE *handles;
76209139Srpaulo	size_t num_handles;
77209139Srpaulo};
78209139Srpaulo
79209139Srpaulostatic struct eloop_data eloop;
80209139Srpaulo
81209139Srpaulo
82209139Srpauloint eloop_init(void *user_data)
83209139Srpaulo{
84209139Srpaulo	os_memset(&eloop, 0, sizeof(eloop));
85209139Srpaulo	eloop.user_data = user_data;
86209139Srpaulo	eloop.num_handles = 1;
87209139Srpaulo	eloop.handles = os_malloc(eloop.num_handles *
88209139Srpaulo				  sizeof(eloop.handles[0]));
89209139Srpaulo	if (eloop.handles == NULL)
90209139Srpaulo		return -1;
91209139Srpaulo
92209139Srpaulo	eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
93209139Srpaulo	if (eloop.term_event == NULL) {
94209139Srpaulo		printf("CreateEvent() failed: %d\n",
95209139Srpaulo		       (int) GetLastError());
96209139Srpaulo		os_free(eloop.handles);
97209139Srpaulo		return -1;
98209139Srpaulo	}
99209139Srpaulo
100209139Srpaulo	return 0;
101209139Srpaulo}
102209139Srpaulo
103209139Srpaulo
104209139Srpaulostatic int eloop_prepare_handles(void)
105209139Srpaulo{
106209139Srpaulo	HANDLE *n;
107209139Srpaulo
108209139Srpaulo	if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
109209139Srpaulo		return 0;
110209139Srpaulo	n = os_realloc(eloop.handles,
111209139Srpaulo		       eloop.num_handles * 2 * sizeof(eloop.handles[0]));
112209139Srpaulo	if (n == NULL)
113209139Srpaulo		return -1;
114209139Srpaulo	eloop.handles = n;
115209139Srpaulo	eloop.num_handles *= 2;
116209139Srpaulo	return 0;
117209139Srpaulo}
118209139Srpaulo
119209139Srpaulo
120209139Srpauloint eloop_register_read_sock(int sock, eloop_sock_handler handler,
121209139Srpaulo			     void *eloop_data, void *user_data)
122209139Srpaulo{
123209139Srpaulo	WSAEVENT event;
124209139Srpaulo	struct eloop_sock *tmp;
125209139Srpaulo
126209139Srpaulo	if (eloop_prepare_handles())
127209139Srpaulo		return -1;
128209139Srpaulo
129209139Srpaulo	event = WSACreateEvent();
130209139Srpaulo	if (event == WSA_INVALID_EVENT) {
131209139Srpaulo		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
132209139Srpaulo		return -1;
133209139Srpaulo	}
134209139Srpaulo
135209139Srpaulo	if (WSAEventSelect(sock, event, FD_READ)) {
136209139Srpaulo		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
137209139Srpaulo		WSACloseEvent(event);
138209139Srpaulo		return -1;
139209139Srpaulo	}
140209139Srpaulo	tmp = os_realloc(eloop.readers,
141209139Srpaulo			 (eloop.reader_count + 1) * sizeof(struct eloop_sock));
142209139Srpaulo	if (tmp == NULL) {
143209139Srpaulo		WSAEventSelect(sock, event, 0);
144209139Srpaulo		WSACloseEvent(event);
145209139Srpaulo		return -1;
146209139Srpaulo	}
147209139Srpaulo
148209139Srpaulo	tmp[eloop.reader_count].sock = sock;
149209139Srpaulo	tmp[eloop.reader_count].eloop_data = eloop_data;
150209139Srpaulo	tmp[eloop.reader_count].user_data = user_data;
151209139Srpaulo	tmp[eloop.reader_count].handler = handler;
152209139Srpaulo	tmp[eloop.reader_count].event = event;
153209139Srpaulo	eloop.reader_count++;
154209139Srpaulo	eloop.readers = tmp;
155209139Srpaulo	if (sock > eloop.max_sock)
156209139Srpaulo		eloop.max_sock = sock;
157209139Srpaulo	eloop.reader_table_changed = 1;
158209139Srpaulo
159209139Srpaulo	return 0;
160209139Srpaulo}
161209139Srpaulo
162209139Srpaulo
163209139Srpaulovoid eloop_unregister_read_sock(int sock)
164209139Srpaulo{
165209139Srpaulo	size_t i;
166209139Srpaulo
167209139Srpaulo	if (eloop.readers == NULL || eloop.reader_count == 0)
168209139Srpaulo		return;
169209139Srpaulo
170209139Srpaulo	for (i = 0; i < eloop.reader_count; i++) {
171209139Srpaulo		if (eloop.readers[i].sock == sock)
172209139Srpaulo			break;
173209139Srpaulo	}
174209139Srpaulo	if (i == eloop.reader_count)
175209139Srpaulo		return;
176209139Srpaulo
177209139Srpaulo	WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
178209139Srpaulo	WSACloseEvent(eloop.readers[i].event);
179209139Srpaulo
180209139Srpaulo	if (i != eloop.reader_count - 1) {
181209139Srpaulo		os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
182209139Srpaulo			   (eloop.reader_count - i - 1) *
183209139Srpaulo			   sizeof(struct eloop_sock));
184209139Srpaulo	}
185209139Srpaulo	eloop.reader_count--;
186209139Srpaulo	eloop.reader_table_changed = 1;
187209139Srpaulo}
188209139Srpaulo
189209139Srpaulo
190209139Srpauloint eloop_register_event(void *event, size_t event_size,
191209139Srpaulo			 eloop_event_handler handler,
192209139Srpaulo			 void *eloop_data, void *user_data)
193209139Srpaulo{
194209139Srpaulo	struct eloop_event *tmp;
195209139Srpaulo	HANDLE h = event;
196209139Srpaulo
197209139Srpaulo	if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
198209139Srpaulo		return -1;
199209139Srpaulo
200209139Srpaulo	if (eloop_prepare_handles())
201209139Srpaulo		return -1;
202209139Srpaulo
203209139Srpaulo	tmp = os_realloc(eloop.events,
204209139Srpaulo			 (eloop.event_count + 1) * sizeof(struct eloop_event));
205209139Srpaulo	if (tmp == NULL)
206209139Srpaulo		return -1;
207209139Srpaulo
208209139Srpaulo	tmp[eloop.event_count].eloop_data = eloop_data;
209209139Srpaulo	tmp[eloop.event_count].user_data = user_data;
210209139Srpaulo	tmp[eloop.event_count].handler = handler;
211209139Srpaulo	tmp[eloop.event_count].event = h;
212209139Srpaulo	eloop.event_count++;
213209139Srpaulo	eloop.events = tmp;
214209139Srpaulo
215209139Srpaulo	return 0;
216209139Srpaulo}
217209139Srpaulo
218209139Srpaulo
219209139Srpaulovoid eloop_unregister_event(void *event, size_t event_size)
220209139Srpaulo{
221209139Srpaulo	size_t i;
222209139Srpaulo	HANDLE h = event;
223209139Srpaulo
224209139Srpaulo	if (eloop.events == NULL || eloop.event_count == 0 ||
225209139Srpaulo	    event_size != sizeof(HANDLE))
226209139Srpaulo		return;
227209139Srpaulo
228209139Srpaulo	for (i = 0; i < eloop.event_count; i++) {
229209139Srpaulo		if (eloop.events[i].event == h)
230209139Srpaulo			break;
231209139Srpaulo	}
232209139Srpaulo	if (i == eloop.event_count)
233209139Srpaulo		return;
234209139Srpaulo
235209139Srpaulo	if (i != eloop.event_count - 1) {
236209139Srpaulo		os_memmove(&eloop.events[i], &eloop.events[i + 1],
237209139Srpaulo			   (eloop.event_count - i - 1) *
238209139Srpaulo			   sizeof(struct eloop_event));
239209139Srpaulo	}
240209139Srpaulo	eloop.event_count--;
241209139Srpaulo}
242209139Srpaulo
243209139Srpaulo
244209139Srpauloint eloop_register_timeout(unsigned int secs, unsigned int usecs,
245209139Srpaulo			   eloop_timeout_handler handler,
246209139Srpaulo			   void *eloop_data, void *user_data)
247209139Srpaulo{
248209139Srpaulo	struct eloop_timeout *timeout, *tmp, *prev;
249209139Srpaulo
250209139Srpaulo	timeout = os_malloc(sizeof(*timeout));
251209139Srpaulo	if (timeout == NULL)
252209139Srpaulo		return -1;
253209139Srpaulo	os_get_time(&timeout->time);
254209139Srpaulo	timeout->time.sec += secs;
255209139Srpaulo	timeout->time.usec += usecs;
256209139Srpaulo	while (timeout->time.usec >= 1000000) {
257209139Srpaulo		timeout->time.sec++;
258209139Srpaulo		timeout->time.usec -= 1000000;
259209139Srpaulo	}
260209139Srpaulo	timeout->eloop_data = eloop_data;
261209139Srpaulo	timeout->user_data = user_data;
262209139Srpaulo	timeout->handler = handler;
263209139Srpaulo	timeout->next = NULL;
264209139Srpaulo
265209139Srpaulo	if (eloop.timeout == NULL) {
266209139Srpaulo		eloop.timeout = timeout;
267209139Srpaulo		return 0;
268209139Srpaulo	}
269209139Srpaulo
270209139Srpaulo	prev = NULL;
271209139Srpaulo	tmp = eloop.timeout;
272209139Srpaulo	while (tmp != NULL) {
273209139Srpaulo		if (os_time_before(&timeout->time, &tmp->time))
274209139Srpaulo			break;
275209139Srpaulo		prev = tmp;
276209139Srpaulo		tmp = tmp->next;
277209139Srpaulo	}
278209139Srpaulo
279209139Srpaulo	if (prev == NULL) {
280209139Srpaulo		timeout->next = eloop.timeout;
281209139Srpaulo		eloop.timeout = timeout;
282209139Srpaulo	} else {
283209139Srpaulo		timeout->next = prev->next;
284209139Srpaulo		prev->next = timeout;
285209139Srpaulo	}
286209139Srpaulo
287209139Srpaulo	return 0;
288209139Srpaulo}
289209139Srpaulo
290209139Srpaulo
291209139Srpauloint eloop_cancel_timeout(eloop_timeout_handler handler,
292209139Srpaulo			 void *eloop_data, void *user_data)
293209139Srpaulo{
294209139Srpaulo	struct eloop_timeout *timeout, *prev, *next;
295209139Srpaulo	int removed = 0;
296209139Srpaulo
297209139Srpaulo	prev = NULL;
298209139Srpaulo	timeout = eloop.timeout;
299209139Srpaulo	while (timeout != NULL) {
300209139Srpaulo		next = timeout->next;
301209139Srpaulo
302209139Srpaulo		if (timeout->handler == handler &&
303209139Srpaulo		    (timeout->eloop_data == eloop_data ||
304209139Srpaulo		     eloop_data == ELOOP_ALL_CTX) &&
305209139Srpaulo		    (timeout->user_data == user_data ||
306209139Srpaulo		     user_data == ELOOP_ALL_CTX)) {
307209139Srpaulo			if (prev == NULL)
308209139Srpaulo				eloop.timeout = next;
309209139Srpaulo			else
310209139Srpaulo				prev->next = next;
311209139Srpaulo			os_free(timeout);
312209139Srpaulo			removed++;
313209139Srpaulo		} else
314209139Srpaulo			prev = timeout;
315209139Srpaulo
316209139Srpaulo		timeout = next;
317209139Srpaulo	}
318209139Srpaulo
319209139Srpaulo	return removed;
320209139Srpaulo}
321209139Srpaulo
322209139Srpaulo
323209139Srpauloint eloop_is_timeout_registered(eloop_timeout_handler handler,
324209139Srpaulo				void *eloop_data, void *user_data)
325209139Srpaulo{
326209139Srpaulo	struct eloop_timeout *tmp;
327209139Srpaulo
328209139Srpaulo	tmp = eloop.timeout;
329209139Srpaulo	while (tmp != NULL) {
330209139Srpaulo		if (tmp->handler == handler &&
331209139Srpaulo		    tmp->eloop_data == eloop_data &&
332209139Srpaulo		    tmp->user_data == user_data)
333209139Srpaulo			return 1;
334209139Srpaulo
335209139Srpaulo		tmp = tmp->next;
336209139Srpaulo	}
337209139Srpaulo
338209139Srpaulo	return 0;
339209139Srpaulo}
340209139Srpaulo
341209139Srpaulo
342209139Srpaulo/* TODO: replace with suitable signal handler */
343209139Srpaulo#if 0
344209139Srpaulostatic void eloop_handle_signal(int sig)
345209139Srpaulo{
346209139Srpaulo	int i;
347209139Srpaulo
348209139Srpaulo	eloop.signaled++;
349209139Srpaulo	for (i = 0; i < eloop.signal_count; i++) {
350209139Srpaulo		if (eloop.signals[i].sig == sig) {
351209139Srpaulo			eloop.signals[i].signaled++;
352209139Srpaulo			break;
353209139Srpaulo		}
354209139Srpaulo	}
355209139Srpaulo}
356209139Srpaulo#endif
357209139Srpaulo
358209139Srpaulo
359209139Srpaulostatic void eloop_process_pending_signals(void)
360209139Srpaulo{
361209139Srpaulo	int i;
362209139Srpaulo
363209139Srpaulo	if (eloop.signaled == 0)
364209139Srpaulo		return;
365209139Srpaulo	eloop.signaled = 0;
366209139Srpaulo
367209139Srpaulo	if (eloop.pending_terminate) {
368209139Srpaulo		eloop.pending_terminate = 0;
369209139Srpaulo	}
370209139Srpaulo
371209139Srpaulo	for (i = 0; i < eloop.signal_count; i++) {
372209139Srpaulo		if (eloop.signals[i].signaled) {
373209139Srpaulo			eloop.signals[i].signaled = 0;
374209139Srpaulo			eloop.signals[i].handler(eloop.signals[i].sig,
375209139Srpaulo						 eloop.user_data,
376209139Srpaulo						 eloop.signals[i].user_data);
377209139Srpaulo		}
378209139Srpaulo	}
379209139Srpaulo
380209139Srpaulo	if (eloop.term_signal.signaled) {
381209139Srpaulo		eloop.term_signal.signaled = 0;
382209139Srpaulo		eloop.term_signal.handler(eloop.term_signal.sig,
383209139Srpaulo					  eloop.user_data,
384209139Srpaulo					  eloop.term_signal.user_data);
385209139Srpaulo	}
386209139Srpaulo}
387209139Srpaulo
388209139Srpaulo
389209139Srpauloint eloop_register_signal(int sig, eloop_signal_handler handler,
390209139Srpaulo			  void *user_data)
391209139Srpaulo{
392209139Srpaulo	struct eloop_signal *tmp;
393209139Srpaulo
394209139Srpaulo	tmp = os_realloc(eloop.signals,
395209139Srpaulo			 (eloop.signal_count + 1) *
396209139Srpaulo			 sizeof(struct eloop_signal));
397209139Srpaulo	if (tmp == NULL)
398209139Srpaulo		return -1;
399209139Srpaulo
400209139Srpaulo	tmp[eloop.signal_count].sig = sig;
401209139Srpaulo	tmp[eloop.signal_count].user_data = user_data;
402209139Srpaulo	tmp[eloop.signal_count].handler = handler;
403209139Srpaulo	tmp[eloop.signal_count].signaled = 0;
404209139Srpaulo	eloop.signal_count++;
405209139Srpaulo	eloop.signals = tmp;
406209139Srpaulo
407209139Srpaulo	/* TODO: register signal handler */
408209139Srpaulo
409209139Srpaulo	return 0;
410209139Srpaulo}
411209139Srpaulo
412209139Srpaulo
413209139Srpaulo#ifndef _WIN32_WCE
414209139Srpaulostatic BOOL eloop_handle_console_ctrl(DWORD type)
415209139Srpaulo{
416209139Srpaulo	switch (type) {
417209139Srpaulo	case CTRL_C_EVENT:
418209139Srpaulo	case CTRL_BREAK_EVENT:
419209139Srpaulo		eloop.signaled++;
420209139Srpaulo		eloop.term_signal.signaled++;
421209139Srpaulo		SetEvent(eloop.term_event);
422209139Srpaulo		return TRUE;
423209139Srpaulo	default:
424209139Srpaulo		return FALSE;
425209139Srpaulo	}
426209139Srpaulo}
427209139Srpaulo#endif /* _WIN32_WCE */
428209139Srpaulo
429209139Srpaulo
430209139Srpauloint eloop_register_signal_terminate(eloop_signal_handler handler,
431209139Srpaulo				    void *user_data)
432209139Srpaulo{
433209139Srpaulo#ifndef _WIN32_WCE
434209139Srpaulo	if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
435209139Srpaulo				  TRUE) == 0) {
436209139Srpaulo		printf("SetConsoleCtrlHandler() failed: %d\n",
437209139Srpaulo		       (int) GetLastError());
438209139Srpaulo		return -1;
439209139Srpaulo	}
440209139Srpaulo#endif /* _WIN32_WCE */
441209139Srpaulo
442209139Srpaulo	eloop.term_signal.handler = handler;
443209139Srpaulo	eloop.term_signal.user_data = user_data;
444209139Srpaulo
445209139Srpaulo	return 0;
446209139Srpaulo}
447209139Srpaulo
448209139Srpaulo
449209139Srpauloint eloop_register_signal_reconfig(eloop_signal_handler handler,
450209139Srpaulo				   void *user_data)
451209139Srpaulo{
452209139Srpaulo	/* TODO */
453209139Srpaulo	return 0;
454209139Srpaulo}
455209139Srpaulo
456209139Srpaulo
457209139Srpaulovoid eloop_run(void)
458209139Srpaulo{
459209139Srpaulo	struct os_time tv, now;
460209139Srpaulo	DWORD count, ret, timeout, err;
461209139Srpaulo	size_t i;
462209139Srpaulo
463209139Srpaulo	while (!eloop.terminate &&
464209139Srpaulo	       (eloop.timeout || eloop.reader_count > 0 ||
465209139Srpaulo		eloop.event_count > 0)) {
466209139Srpaulo		tv.sec = tv.usec = 0;
467209139Srpaulo		if (eloop.timeout) {
468209139Srpaulo			os_get_time(&now);
469209139Srpaulo			if (os_time_before(&now, &eloop.timeout->time))
470209139Srpaulo				os_time_sub(&eloop.timeout->time, &now, &tv);
471209139Srpaulo		}
472209139Srpaulo
473209139Srpaulo		count = 0;
474209139Srpaulo		for (i = 0; i < eloop.event_count; i++)
475209139Srpaulo			eloop.handles[count++] = eloop.events[i].event;
476209139Srpaulo
477209139Srpaulo		for (i = 0; i < eloop.reader_count; i++)
478209139Srpaulo			eloop.handles[count++] = eloop.readers[i].event;
479209139Srpaulo
480209139Srpaulo		if (eloop.term_event)
481209139Srpaulo			eloop.handles[count++] = eloop.term_event;
482209139Srpaulo
483209139Srpaulo		if (eloop.timeout)
484209139Srpaulo			timeout = tv.sec * 1000 + tv.usec / 1000;
485209139Srpaulo		else
486209139Srpaulo			timeout = INFINITE;
487209139Srpaulo
488209139Srpaulo		if (count > MAXIMUM_WAIT_OBJECTS) {
489209139Srpaulo			printf("WaitForMultipleObjects: Too many events: "
490209139Srpaulo			       "%d > %d (ignoring extra events)\n",
491209139Srpaulo			       (int) count, MAXIMUM_WAIT_OBJECTS);
492209139Srpaulo			count = MAXIMUM_WAIT_OBJECTS;
493209139Srpaulo		}
494209139Srpaulo#ifdef _WIN32_WCE
495209139Srpaulo		ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
496209139Srpaulo					     timeout);
497209139Srpaulo#else /* _WIN32_WCE */
498209139Srpaulo		ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
499209139Srpaulo					       timeout, TRUE);
500209139Srpaulo#endif /* _WIN32_WCE */
501209139Srpaulo		err = GetLastError();
502209139Srpaulo
503209139Srpaulo		eloop_process_pending_signals();
504209139Srpaulo
505209139Srpaulo		/* check if some registered timeouts have occurred */
506209139Srpaulo		if (eloop.timeout) {
507209139Srpaulo			struct eloop_timeout *tmp;
508209139Srpaulo
509209139Srpaulo			os_get_time(&now);
510209139Srpaulo			if (!os_time_before(&now, &eloop.timeout->time)) {
511209139Srpaulo				tmp = eloop.timeout;
512209139Srpaulo				eloop.timeout = eloop.timeout->next;
513209139Srpaulo				tmp->handler(tmp->eloop_data,
514209139Srpaulo					     tmp->user_data);
515209139Srpaulo				os_free(tmp);
516209139Srpaulo			}
517209139Srpaulo
518209139Srpaulo		}
519209139Srpaulo
520209139Srpaulo		if (ret == WAIT_FAILED) {
521209139Srpaulo			printf("WaitForMultipleObjects(count=%d) failed: %d\n",
522209139Srpaulo			       (int) count, (int) err);
523209139Srpaulo			os_sleep(1, 0);
524209139Srpaulo			continue;
525209139Srpaulo		}
526209139Srpaulo
527209139Srpaulo#ifndef _WIN32_WCE
528209139Srpaulo		if (ret == WAIT_IO_COMPLETION)
529209139Srpaulo			continue;
530209139Srpaulo#endif /* _WIN32_WCE */
531209139Srpaulo
532209139Srpaulo		if (ret == WAIT_TIMEOUT)
533209139Srpaulo			continue;
534209139Srpaulo
535209139Srpaulo		while (ret >= WAIT_OBJECT_0 &&
536209139Srpaulo		       ret < WAIT_OBJECT_0 + eloop.event_count) {
537209139Srpaulo			eloop.events[ret].handler(
538209139Srpaulo				eloop.events[ret].eloop_data,
539209139Srpaulo				eloop.events[ret].user_data);
540209139Srpaulo			ret = WaitForMultipleObjects(eloop.event_count,
541209139Srpaulo						     eloop.handles, FALSE, 0);
542209139Srpaulo		}
543209139Srpaulo
544209139Srpaulo		eloop.reader_table_changed = 0;
545209139Srpaulo		for (i = 0; i < eloop.reader_count; i++) {
546209139Srpaulo			WSANETWORKEVENTS events;
547209139Srpaulo			if (WSAEnumNetworkEvents(eloop.readers[i].sock,
548209139Srpaulo						 eloop.readers[i].event,
549209139Srpaulo						 &events) == 0 &&
550209139Srpaulo			    (events.lNetworkEvents & FD_READ)) {
551209139Srpaulo				eloop.readers[i].handler(
552209139Srpaulo					eloop.readers[i].sock,
553209139Srpaulo					eloop.readers[i].eloop_data,
554209139Srpaulo					eloop.readers[i].user_data);
555209139Srpaulo				if (eloop.reader_table_changed)
556209139Srpaulo					break;
557209139Srpaulo			}
558209139Srpaulo		}
559209139Srpaulo	}
560209139Srpaulo}
561209139Srpaulo
562209139Srpaulo
563209139Srpaulovoid eloop_terminate(void)
564209139Srpaulo{
565209139Srpaulo	eloop.terminate = 1;
566209139Srpaulo	SetEvent(eloop.term_event);
567209139Srpaulo}
568209139Srpaulo
569209139Srpaulo
570209139Srpaulovoid eloop_destroy(void)
571209139Srpaulo{
572209139Srpaulo	struct eloop_timeout *timeout, *prev;
573209139Srpaulo
574209139Srpaulo	timeout = eloop.timeout;
575209139Srpaulo	while (timeout != NULL) {
576209139Srpaulo		prev = timeout;
577209139Srpaulo		timeout = timeout->next;
578209139Srpaulo		os_free(prev);
579209139Srpaulo	}
580209139Srpaulo	os_free(eloop.readers);
581209139Srpaulo	os_free(eloop.signals);
582209139Srpaulo	if (eloop.term_event)
583209139Srpaulo		CloseHandle(eloop.term_event);
584209139Srpaulo	os_free(eloop.handles);
585209139Srpaulo	eloop.handles = NULL;
586209139Srpaulo	os_free(eloop.events);
587209139Srpaulo	eloop.events = NULL;
588209139Srpaulo}
589209139Srpaulo
590209139Srpaulo
591209139Srpauloint eloop_terminated(void)
592209139Srpaulo{
593209139Srpaulo	return eloop.terminate;
594209139Srpaulo}
595209139Srpaulo
596209139Srpaulo
597209139Srpaulovoid eloop_wait_for_read_sock(int sock)
598209139Srpaulo{
599209139Srpaulo	WSAEVENT event;
600209139Srpaulo
601209139Srpaulo	event = WSACreateEvent();
602209139Srpaulo	if (event == WSA_INVALID_EVENT) {
603209139Srpaulo		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
604209139Srpaulo		return;
605209139Srpaulo	}
606209139Srpaulo
607209139Srpaulo	if (WSAEventSelect(sock, event, FD_READ)) {
608209139Srpaulo		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
609209139Srpaulo		WSACloseEvent(event);
610209139Srpaulo		return ;
611209139Srpaulo	}
612209139Srpaulo
613209139Srpaulo	WaitForSingleObject(event, INFINITE);
614209139Srpaulo	WSAEventSelect(sock, event, 0);
615209139Srpaulo	WSACloseEvent(event);
616209139Srpaulo}
617209139Srpaulo
618209139Srpaulo
619209139Srpaulovoid * eloop_get_user_data(void)
620209139Srpaulo{
621209139Srpaulo	return eloop.user_data;
622209139Srpaulo}
623