1209139Srpaulo/*
2209139Srpaulo * Event loop based on Windows events and WaitForMultipleObjects
3209139Srpaulo * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
4209139Srpaulo *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7209139Srpaulo */
8209139Srpaulo
9209139Srpaulo#include "includes.h"
10209139Srpaulo#include <winsock2.h>
11209139Srpaulo
12209139Srpaulo#include "common.h"
13209139Srpaulo#include "eloop.h"
14209139Srpaulo
15209139Srpaulo
16209139Srpaulostruct eloop_sock {
17209139Srpaulo	int sock;
18209139Srpaulo	void *eloop_data;
19209139Srpaulo	void *user_data;
20209139Srpaulo	eloop_sock_handler handler;
21209139Srpaulo	WSAEVENT event;
22209139Srpaulo};
23209139Srpaulo
24209139Srpaulostruct eloop_event {
25209139Srpaulo	void *eloop_data;
26209139Srpaulo	void *user_data;
27209139Srpaulo	eloop_event_handler handler;
28209139Srpaulo	HANDLE event;
29209139Srpaulo};
30209139Srpaulo
31209139Srpaulostruct eloop_timeout {
32209139Srpaulo	struct os_time time;
33209139Srpaulo	void *eloop_data;
34209139Srpaulo	void *user_data;
35209139Srpaulo	eloop_timeout_handler handler;
36209139Srpaulo	struct eloop_timeout *next;
37209139Srpaulo};
38209139Srpaulo
39209139Srpaulostruct eloop_signal {
40209139Srpaulo	int sig;
41209139Srpaulo	void *user_data;
42209139Srpaulo	eloop_signal_handler handler;
43209139Srpaulo	int signaled;
44209139Srpaulo};
45209139Srpaulo
46209139Srpaulostruct eloop_data {
47209139Srpaulo	int max_sock;
48209139Srpaulo	size_t reader_count;
49209139Srpaulo	struct eloop_sock *readers;
50209139Srpaulo
51209139Srpaulo	size_t event_count;
52209139Srpaulo	struct eloop_event *events;
53209139Srpaulo
54209139Srpaulo	struct eloop_timeout *timeout;
55209139Srpaulo
56209139Srpaulo	int signal_count;
57209139Srpaulo	struct eloop_signal *signals;
58209139Srpaulo	int signaled;
59209139Srpaulo	int pending_terminate;
60209139Srpaulo
61209139Srpaulo	int terminate;
62209139Srpaulo	int reader_table_changed;
63209139Srpaulo
64209139Srpaulo	struct eloop_signal term_signal;
65209139Srpaulo	HANDLE term_event;
66209139Srpaulo
67209139Srpaulo	HANDLE *handles;
68209139Srpaulo	size_t num_handles;
69209139Srpaulo};
70209139Srpaulo
71209139Srpaulostatic struct eloop_data eloop;
72209139Srpaulo
73209139Srpaulo
74214734Srpauloint eloop_init(void)
75209139Srpaulo{
76209139Srpaulo	os_memset(&eloop, 0, sizeof(eloop));
77209139Srpaulo	eloop.num_handles = 1;
78209139Srpaulo	eloop.handles = os_malloc(eloop.num_handles *
79209139Srpaulo				  sizeof(eloop.handles[0]));
80209139Srpaulo	if (eloop.handles == NULL)
81209139Srpaulo		return -1;
82209139Srpaulo
83209139Srpaulo	eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
84209139Srpaulo	if (eloop.term_event == NULL) {
85209139Srpaulo		printf("CreateEvent() failed: %d\n",
86209139Srpaulo		       (int) GetLastError());
87209139Srpaulo		os_free(eloop.handles);
88209139Srpaulo		return -1;
89209139Srpaulo	}
90209139Srpaulo
91209139Srpaulo	return 0;
92209139Srpaulo}
93209139Srpaulo
94209139Srpaulo
95209139Srpaulostatic int eloop_prepare_handles(void)
96209139Srpaulo{
97209139Srpaulo	HANDLE *n;
98209139Srpaulo
99209139Srpaulo	if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
100209139Srpaulo		return 0;
101252726Srpaulo	n = os_realloc_array(eloop.handles, eloop.num_handles * 2,
102252726Srpaulo			     sizeof(eloop.handles[0]));
103209139Srpaulo	if (n == NULL)
104209139Srpaulo		return -1;
105209139Srpaulo	eloop.handles = n;
106209139Srpaulo	eloop.num_handles *= 2;
107209139Srpaulo	return 0;
108209139Srpaulo}
109209139Srpaulo
110209139Srpaulo
111209139Srpauloint eloop_register_read_sock(int sock, eloop_sock_handler handler,
112209139Srpaulo			     void *eloop_data, void *user_data)
113209139Srpaulo{
114209139Srpaulo	WSAEVENT event;
115209139Srpaulo	struct eloop_sock *tmp;
116209139Srpaulo
117209139Srpaulo	if (eloop_prepare_handles())
118209139Srpaulo		return -1;
119209139Srpaulo
120209139Srpaulo	event = WSACreateEvent();
121209139Srpaulo	if (event == WSA_INVALID_EVENT) {
122209139Srpaulo		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
123209139Srpaulo		return -1;
124209139Srpaulo	}
125209139Srpaulo
126209139Srpaulo	if (WSAEventSelect(sock, event, FD_READ)) {
127209139Srpaulo		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
128209139Srpaulo		WSACloseEvent(event);
129209139Srpaulo		return -1;
130209139Srpaulo	}
131252726Srpaulo	tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1,
132252726Srpaulo			       sizeof(struct eloop_sock));
133209139Srpaulo	if (tmp == NULL) {
134209139Srpaulo		WSAEventSelect(sock, event, 0);
135209139Srpaulo		WSACloseEvent(event);
136209139Srpaulo		return -1;
137209139Srpaulo	}
138209139Srpaulo
139209139Srpaulo	tmp[eloop.reader_count].sock = sock;
140209139Srpaulo	tmp[eloop.reader_count].eloop_data = eloop_data;
141209139Srpaulo	tmp[eloop.reader_count].user_data = user_data;
142209139Srpaulo	tmp[eloop.reader_count].handler = handler;
143209139Srpaulo	tmp[eloop.reader_count].event = event;
144209139Srpaulo	eloop.reader_count++;
145209139Srpaulo	eloop.readers = tmp;
146209139Srpaulo	if (sock > eloop.max_sock)
147209139Srpaulo		eloop.max_sock = sock;
148209139Srpaulo	eloop.reader_table_changed = 1;
149209139Srpaulo
150209139Srpaulo	return 0;
151209139Srpaulo}
152209139Srpaulo
153209139Srpaulo
154209139Srpaulovoid eloop_unregister_read_sock(int sock)
155209139Srpaulo{
156209139Srpaulo	size_t i;
157209139Srpaulo
158209139Srpaulo	if (eloop.readers == NULL || eloop.reader_count == 0)
159209139Srpaulo		return;
160209139Srpaulo
161209139Srpaulo	for (i = 0; i < eloop.reader_count; i++) {
162209139Srpaulo		if (eloop.readers[i].sock == sock)
163209139Srpaulo			break;
164209139Srpaulo	}
165209139Srpaulo	if (i == eloop.reader_count)
166209139Srpaulo		return;
167209139Srpaulo
168209139Srpaulo	WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
169209139Srpaulo	WSACloseEvent(eloop.readers[i].event);
170209139Srpaulo
171209139Srpaulo	if (i != eloop.reader_count - 1) {
172209139Srpaulo		os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
173209139Srpaulo			   (eloop.reader_count - i - 1) *
174209139Srpaulo			   sizeof(struct eloop_sock));
175209139Srpaulo	}
176209139Srpaulo	eloop.reader_count--;
177209139Srpaulo	eloop.reader_table_changed = 1;
178209139Srpaulo}
179209139Srpaulo
180209139Srpaulo
181209139Srpauloint eloop_register_event(void *event, size_t event_size,
182209139Srpaulo			 eloop_event_handler handler,
183209139Srpaulo			 void *eloop_data, void *user_data)
184209139Srpaulo{
185209139Srpaulo	struct eloop_event *tmp;
186209139Srpaulo	HANDLE h = event;
187209139Srpaulo
188209139Srpaulo	if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
189209139Srpaulo		return -1;
190209139Srpaulo
191209139Srpaulo	if (eloop_prepare_handles())
192209139Srpaulo		return -1;
193209139Srpaulo
194252726Srpaulo	tmp = os_realloc_array(eloop.events, eloop.event_count + 1,
195252726Srpaulo			       sizeof(struct eloop_event));
196209139Srpaulo	if (tmp == NULL)
197209139Srpaulo		return -1;
198209139Srpaulo
199209139Srpaulo	tmp[eloop.event_count].eloop_data = eloop_data;
200209139Srpaulo	tmp[eloop.event_count].user_data = user_data;
201209139Srpaulo	tmp[eloop.event_count].handler = handler;
202209139Srpaulo	tmp[eloop.event_count].event = h;
203209139Srpaulo	eloop.event_count++;
204209139Srpaulo	eloop.events = tmp;
205209139Srpaulo
206209139Srpaulo	return 0;
207209139Srpaulo}
208209139Srpaulo
209209139Srpaulo
210209139Srpaulovoid eloop_unregister_event(void *event, size_t event_size)
211209139Srpaulo{
212209139Srpaulo	size_t i;
213209139Srpaulo	HANDLE h = event;
214209139Srpaulo
215209139Srpaulo	if (eloop.events == NULL || eloop.event_count == 0 ||
216209139Srpaulo	    event_size != sizeof(HANDLE))
217209139Srpaulo		return;
218209139Srpaulo
219209139Srpaulo	for (i = 0; i < eloop.event_count; i++) {
220209139Srpaulo		if (eloop.events[i].event == h)
221209139Srpaulo			break;
222209139Srpaulo	}
223209139Srpaulo	if (i == eloop.event_count)
224209139Srpaulo		return;
225209139Srpaulo
226209139Srpaulo	if (i != eloop.event_count - 1) {
227209139Srpaulo		os_memmove(&eloop.events[i], &eloop.events[i + 1],
228209139Srpaulo			   (eloop.event_count - i - 1) *
229209139Srpaulo			   sizeof(struct eloop_event));
230209139Srpaulo	}
231209139Srpaulo	eloop.event_count--;
232209139Srpaulo}
233209139Srpaulo
234209139Srpaulo
235209139Srpauloint eloop_register_timeout(unsigned int secs, unsigned int usecs,
236209139Srpaulo			   eloop_timeout_handler handler,
237209139Srpaulo			   void *eloop_data, void *user_data)
238209139Srpaulo{
239209139Srpaulo	struct eloop_timeout *timeout, *tmp, *prev;
240252726Srpaulo	os_time_t now_sec;
241209139Srpaulo
242209139Srpaulo	timeout = os_malloc(sizeof(*timeout));
243209139Srpaulo	if (timeout == NULL)
244209139Srpaulo		return -1;
245209139Srpaulo	os_get_time(&timeout->time);
246252726Srpaulo	now_sec = timeout->time.sec;
247209139Srpaulo	timeout->time.sec += secs;
248252726Srpaulo	if (timeout->time.sec < now_sec) {
249252726Srpaulo		/*
250252726Srpaulo		 * Integer overflow - assume long enough timeout to be assumed
251252726Srpaulo		 * to be infinite, i.e., the timeout would never happen.
252252726Srpaulo		 */
253252726Srpaulo		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
254252726Srpaulo			   "ever happen - ignore it", secs);
255252726Srpaulo		os_free(timeout);
256252726Srpaulo		return 0;
257252726Srpaulo	}
258209139Srpaulo	timeout->time.usec += usecs;
259209139Srpaulo	while (timeout->time.usec >= 1000000) {
260209139Srpaulo		timeout->time.sec++;
261209139Srpaulo		timeout->time.usec -= 1000000;
262209139Srpaulo	}
263209139Srpaulo	timeout->eloop_data = eloop_data;
264209139Srpaulo	timeout->user_data = user_data;
265209139Srpaulo	timeout->handler = handler;
266209139Srpaulo	timeout->next = NULL;
267209139Srpaulo
268209139Srpaulo	if (eloop.timeout == NULL) {
269209139Srpaulo		eloop.timeout = timeout;
270209139Srpaulo		return 0;
271209139Srpaulo	}
272209139Srpaulo
273209139Srpaulo	prev = NULL;
274209139Srpaulo	tmp = eloop.timeout;
275209139Srpaulo	while (tmp != NULL) {
276209139Srpaulo		if (os_time_before(&timeout->time, &tmp->time))
277209139Srpaulo			break;
278209139Srpaulo		prev = tmp;
279209139Srpaulo		tmp = tmp->next;
280209139Srpaulo	}
281209139Srpaulo
282209139Srpaulo	if (prev == NULL) {
283209139Srpaulo		timeout->next = eloop.timeout;
284209139Srpaulo		eloop.timeout = timeout;
285209139Srpaulo	} else {
286209139Srpaulo		timeout->next = prev->next;
287209139Srpaulo		prev->next = timeout;
288209139Srpaulo	}
289209139Srpaulo
290209139Srpaulo	return 0;
291209139Srpaulo}
292209139Srpaulo
293209139Srpaulo
294209139Srpauloint eloop_cancel_timeout(eloop_timeout_handler handler,
295209139Srpaulo			 void *eloop_data, void *user_data)
296209139Srpaulo{
297209139Srpaulo	struct eloop_timeout *timeout, *prev, *next;
298209139Srpaulo	int removed = 0;
299209139Srpaulo
300209139Srpaulo	prev = NULL;
301209139Srpaulo	timeout = eloop.timeout;
302209139Srpaulo	while (timeout != NULL) {
303209139Srpaulo		next = timeout->next;
304209139Srpaulo
305209139Srpaulo		if (timeout->handler == handler &&
306209139Srpaulo		    (timeout->eloop_data == eloop_data ||
307209139Srpaulo		     eloop_data == ELOOP_ALL_CTX) &&
308209139Srpaulo		    (timeout->user_data == user_data ||
309209139Srpaulo		     user_data == ELOOP_ALL_CTX)) {
310209139Srpaulo			if (prev == NULL)
311209139Srpaulo				eloop.timeout = next;
312209139Srpaulo			else
313209139Srpaulo				prev->next = next;
314209139Srpaulo			os_free(timeout);
315209139Srpaulo			removed++;
316209139Srpaulo		} else
317209139Srpaulo			prev = timeout;
318209139Srpaulo
319209139Srpaulo		timeout = next;
320209139Srpaulo	}
321209139Srpaulo
322209139Srpaulo	return removed;
323209139Srpaulo}
324209139Srpaulo
325209139Srpaulo
326209139Srpauloint eloop_is_timeout_registered(eloop_timeout_handler handler,
327209139Srpaulo				void *eloop_data, void *user_data)
328209139Srpaulo{
329209139Srpaulo	struct eloop_timeout *tmp;
330209139Srpaulo
331209139Srpaulo	tmp = eloop.timeout;
332209139Srpaulo	while (tmp != NULL) {
333209139Srpaulo		if (tmp->handler == handler &&
334209139Srpaulo		    tmp->eloop_data == eloop_data &&
335209139Srpaulo		    tmp->user_data == user_data)
336209139Srpaulo			return 1;
337209139Srpaulo
338209139Srpaulo		tmp = tmp->next;
339209139Srpaulo	}
340209139Srpaulo
341209139Srpaulo	return 0;
342209139Srpaulo}
343209139Srpaulo
344209139Srpaulo
345209139Srpaulo/* TODO: replace with suitable signal handler */
346209139Srpaulo#if 0
347209139Srpaulostatic void eloop_handle_signal(int sig)
348209139Srpaulo{
349209139Srpaulo	int i;
350209139Srpaulo
351209139Srpaulo	eloop.signaled++;
352209139Srpaulo	for (i = 0; i < eloop.signal_count; i++) {
353209139Srpaulo		if (eloop.signals[i].sig == sig) {
354209139Srpaulo			eloop.signals[i].signaled++;
355209139Srpaulo			break;
356209139Srpaulo		}
357209139Srpaulo	}
358209139Srpaulo}
359209139Srpaulo#endif
360209139Srpaulo
361209139Srpaulo
362209139Srpaulostatic void eloop_process_pending_signals(void)
363209139Srpaulo{
364209139Srpaulo	int i;
365209139Srpaulo
366209139Srpaulo	if (eloop.signaled == 0)
367209139Srpaulo		return;
368209139Srpaulo	eloop.signaled = 0;
369209139Srpaulo
370209139Srpaulo	if (eloop.pending_terminate) {
371209139Srpaulo		eloop.pending_terminate = 0;
372209139Srpaulo	}
373209139Srpaulo
374209139Srpaulo	for (i = 0; i < eloop.signal_count; i++) {
375209139Srpaulo		if (eloop.signals[i].signaled) {
376209139Srpaulo			eloop.signals[i].signaled = 0;
377209139Srpaulo			eloop.signals[i].handler(eloop.signals[i].sig,
378209139Srpaulo						 eloop.signals[i].user_data);
379209139Srpaulo		}
380209139Srpaulo	}
381209139Srpaulo
382209139Srpaulo	if (eloop.term_signal.signaled) {
383209139Srpaulo		eloop.term_signal.signaled = 0;
384209139Srpaulo		eloop.term_signal.handler(eloop.term_signal.sig,
385209139Srpaulo					  eloop.term_signal.user_data);
386209139Srpaulo	}
387209139Srpaulo}
388209139Srpaulo
389209139Srpaulo
390209139Srpauloint eloop_register_signal(int sig, eloop_signal_handler handler,
391209139Srpaulo			  void *user_data)
392209139Srpaulo{
393209139Srpaulo	struct eloop_signal *tmp;
394209139Srpaulo
395252726Srpaulo	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
396252726Srpaulo			       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}
617