1209139Srpaulo/*
2209139Srpaulo * Event loop based on Windows events and WaitForMultipleObjects
3281806Srpaulo * Copyright (c) 2002-2009, 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"
13281806Srpaulo#include "list.h"
14209139Srpaulo#include "eloop.h"
15209139Srpaulo
16209139Srpaulo
17209139Srpaulostruct eloop_sock {
18209139Srpaulo	int sock;
19209139Srpaulo	void *eloop_data;
20209139Srpaulo	void *user_data;
21209139Srpaulo	eloop_sock_handler handler;
22209139Srpaulo	WSAEVENT event;
23209139Srpaulo};
24209139Srpaulo
25209139Srpaulostruct eloop_event {
26209139Srpaulo	void *eloop_data;
27209139Srpaulo	void *user_data;
28209139Srpaulo	eloop_event_handler handler;
29209139Srpaulo	HANDLE event;
30209139Srpaulo};
31209139Srpaulo
32209139Srpaulostruct eloop_timeout {
33281806Srpaulo	struct dl_list list;
34281806Srpaulo	struct os_reltime time;
35209139Srpaulo	void *eloop_data;
36209139Srpaulo	void *user_data;
37209139Srpaulo	eloop_timeout_handler handler;
38209139Srpaulo};
39209139Srpaulo
40209139Srpaulostruct eloop_signal {
41209139Srpaulo	int sig;
42209139Srpaulo	void *user_data;
43209139Srpaulo	eloop_signal_handler handler;
44209139Srpaulo	int signaled;
45209139Srpaulo};
46209139Srpaulo
47209139Srpaulostruct eloop_data {
48209139Srpaulo	int max_sock;
49209139Srpaulo	size_t reader_count;
50209139Srpaulo	struct eloop_sock *readers;
51209139Srpaulo
52209139Srpaulo	size_t event_count;
53209139Srpaulo	struct eloop_event *events;
54209139Srpaulo
55281806Srpaulo	struct dl_list timeout;
56209139Srpaulo
57209139Srpaulo	int signal_count;
58209139Srpaulo	struct eloop_signal *signals;
59209139Srpaulo	int signaled;
60209139Srpaulo	int pending_terminate;
61209139Srpaulo
62209139Srpaulo	int terminate;
63209139Srpaulo	int reader_table_changed;
64209139Srpaulo
65209139Srpaulo	struct eloop_signal term_signal;
66209139Srpaulo	HANDLE term_event;
67209139Srpaulo
68209139Srpaulo	HANDLE *handles;
69209139Srpaulo	size_t num_handles;
70209139Srpaulo};
71209139Srpaulo
72209139Srpaulostatic struct eloop_data eloop;
73209139Srpaulo
74209139Srpaulo
75214734Srpauloint eloop_init(void)
76209139Srpaulo{
77209139Srpaulo	os_memset(&eloop, 0, sizeof(eloop));
78281806Srpaulo	dl_list_init(&eloop.timeout);
79209139Srpaulo	eloop.num_handles = 1;
80209139Srpaulo	eloop.handles = os_malloc(eloop.num_handles *
81209139Srpaulo				  sizeof(eloop.handles[0]));
82209139Srpaulo	if (eloop.handles == NULL)
83209139Srpaulo		return -1;
84209139Srpaulo
85209139Srpaulo	eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
86209139Srpaulo	if (eloop.term_event == NULL) {
87209139Srpaulo		printf("CreateEvent() failed: %d\n",
88209139Srpaulo		       (int) GetLastError());
89209139Srpaulo		os_free(eloop.handles);
90209139Srpaulo		return -1;
91209139Srpaulo	}
92209139Srpaulo
93209139Srpaulo	return 0;
94209139Srpaulo}
95209139Srpaulo
96209139Srpaulo
97209139Srpaulostatic int eloop_prepare_handles(void)
98209139Srpaulo{
99209139Srpaulo	HANDLE *n;
100209139Srpaulo
101209139Srpaulo	if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
102209139Srpaulo		return 0;
103252726Srpaulo	n = os_realloc_array(eloop.handles, eloop.num_handles * 2,
104252726Srpaulo			     sizeof(eloop.handles[0]));
105209139Srpaulo	if (n == NULL)
106209139Srpaulo		return -1;
107209139Srpaulo	eloop.handles = n;
108209139Srpaulo	eloop.num_handles *= 2;
109209139Srpaulo	return 0;
110209139Srpaulo}
111209139Srpaulo
112209139Srpaulo
113209139Srpauloint eloop_register_read_sock(int sock, eloop_sock_handler handler,
114209139Srpaulo			     void *eloop_data, void *user_data)
115209139Srpaulo{
116209139Srpaulo	WSAEVENT event;
117209139Srpaulo	struct eloop_sock *tmp;
118209139Srpaulo
119209139Srpaulo	if (eloop_prepare_handles())
120209139Srpaulo		return -1;
121209139Srpaulo
122209139Srpaulo	event = WSACreateEvent();
123209139Srpaulo	if (event == WSA_INVALID_EVENT) {
124209139Srpaulo		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
125209139Srpaulo		return -1;
126209139Srpaulo	}
127209139Srpaulo
128209139Srpaulo	if (WSAEventSelect(sock, event, FD_READ)) {
129209139Srpaulo		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
130209139Srpaulo		WSACloseEvent(event);
131209139Srpaulo		return -1;
132209139Srpaulo	}
133252726Srpaulo	tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1,
134252726Srpaulo			       sizeof(struct eloop_sock));
135209139Srpaulo	if (tmp == NULL) {
136209139Srpaulo		WSAEventSelect(sock, event, 0);
137209139Srpaulo		WSACloseEvent(event);
138209139Srpaulo		return -1;
139209139Srpaulo	}
140209139Srpaulo
141209139Srpaulo	tmp[eloop.reader_count].sock = sock;
142209139Srpaulo	tmp[eloop.reader_count].eloop_data = eloop_data;
143209139Srpaulo	tmp[eloop.reader_count].user_data = user_data;
144209139Srpaulo	tmp[eloop.reader_count].handler = handler;
145209139Srpaulo	tmp[eloop.reader_count].event = event;
146209139Srpaulo	eloop.reader_count++;
147209139Srpaulo	eloop.readers = tmp;
148209139Srpaulo	if (sock > eloop.max_sock)
149209139Srpaulo		eloop.max_sock = sock;
150209139Srpaulo	eloop.reader_table_changed = 1;
151209139Srpaulo
152209139Srpaulo	return 0;
153209139Srpaulo}
154209139Srpaulo
155209139Srpaulo
156209139Srpaulovoid eloop_unregister_read_sock(int sock)
157209139Srpaulo{
158209139Srpaulo	size_t i;
159209139Srpaulo
160209139Srpaulo	if (eloop.readers == NULL || eloop.reader_count == 0)
161209139Srpaulo		return;
162209139Srpaulo
163209139Srpaulo	for (i = 0; i < eloop.reader_count; i++) {
164209139Srpaulo		if (eloop.readers[i].sock == sock)
165209139Srpaulo			break;
166209139Srpaulo	}
167209139Srpaulo	if (i == eloop.reader_count)
168209139Srpaulo		return;
169209139Srpaulo
170209139Srpaulo	WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
171209139Srpaulo	WSACloseEvent(eloop.readers[i].event);
172209139Srpaulo
173209139Srpaulo	if (i != eloop.reader_count - 1) {
174209139Srpaulo		os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
175209139Srpaulo			   (eloop.reader_count - i - 1) *
176209139Srpaulo			   sizeof(struct eloop_sock));
177209139Srpaulo	}
178209139Srpaulo	eloop.reader_count--;
179209139Srpaulo	eloop.reader_table_changed = 1;
180209139Srpaulo}
181209139Srpaulo
182209139Srpaulo
183209139Srpauloint eloop_register_event(void *event, size_t event_size,
184209139Srpaulo			 eloop_event_handler handler,
185209139Srpaulo			 void *eloop_data, void *user_data)
186209139Srpaulo{
187209139Srpaulo	struct eloop_event *tmp;
188209139Srpaulo	HANDLE h = event;
189209139Srpaulo
190209139Srpaulo	if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
191209139Srpaulo		return -1;
192209139Srpaulo
193209139Srpaulo	if (eloop_prepare_handles())
194209139Srpaulo		return -1;
195209139Srpaulo
196252726Srpaulo	tmp = os_realloc_array(eloop.events, eloop.event_count + 1,
197252726Srpaulo			       sizeof(struct eloop_event));
198209139Srpaulo	if (tmp == NULL)
199209139Srpaulo		return -1;
200209139Srpaulo
201209139Srpaulo	tmp[eloop.event_count].eloop_data = eloop_data;
202209139Srpaulo	tmp[eloop.event_count].user_data = user_data;
203209139Srpaulo	tmp[eloop.event_count].handler = handler;
204209139Srpaulo	tmp[eloop.event_count].event = h;
205209139Srpaulo	eloop.event_count++;
206209139Srpaulo	eloop.events = tmp;
207209139Srpaulo
208209139Srpaulo	return 0;
209209139Srpaulo}
210209139Srpaulo
211209139Srpaulo
212209139Srpaulovoid eloop_unregister_event(void *event, size_t event_size)
213209139Srpaulo{
214209139Srpaulo	size_t i;
215209139Srpaulo	HANDLE h = event;
216209139Srpaulo
217209139Srpaulo	if (eloop.events == NULL || eloop.event_count == 0 ||
218209139Srpaulo	    event_size != sizeof(HANDLE))
219209139Srpaulo		return;
220209139Srpaulo
221209139Srpaulo	for (i = 0; i < eloop.event_count; i++) {
222209139Srpaulo		if (eloop.events[i].event == h)
223209139Srpaulo			break;
224209139Srpaulo	}
225209139Srpaulo	if (i == eloop.event_count)
226209139Srpaulo		return;
227209139Srpaulo
228209139Srpaulo	if (i != eloop.event_count - 1) {
229209139Srpaulo		os_memmove(&eloop.events[i], &eloop.events[i + 1],
230209139Srpaulo			   (eloop.event_count - i - 1) *
231209139Srpaulo			   sizeof(struct eloop_event));
232209139Srpaulo	}
233209139Srpaulo	eloop.event_count--;
234209139Srpaulo}
235209139Srpaulo
236209139Srpaulo
237209139Srpauloint eloop_register_timeout(unsigned int secs, unsigned int usecs,
238209139Srpaulo			   eloop_timeout_handler handler,
239209139Srpaulo			   void *eloop_data, void *user_data)
240209139Srpaulo{
241281806Srpaulo	struct eloop_timeout *timeout, *tmp;
242252726Srpaulo	os_time_t now_sec;
243209139Srpaulo
244281806Srpaulo	timeout = os_zalloc(sizeof(*timeout));
245209139Srpaulo	if (timeout == NULL)
246209139Srpaulo		return -1;
247281806Srpaulo	if (os_get_reltime(&timeout->time) < 0) {
248281806Srpaulo		os_free(timeout);
249281806Srpaulo		return -1;
250281806Srpaulo	}
251252726Srpaulo	now_sec = timeout->time.sec;
252209139Srpaulo	timeout->time.sec += secs;
253252726Srpaulo	if (timeout->time.sec < now_sec) {
254252726Srpaulo		/*
255252726Srpaulo		 * Integer overflow - assume long enough timeout to be assumed
256252726Srpaulo		 * to be infinite, i.e., the timeout would never happen.
257252726Srpaulo		 */
258252726Srpaulo		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
259252726Srpaulo			   "ever happen - ignore it", secs);
260252726Srpaulo		os_free(timeout);
261252726Srpaulo		return 0;
262252726Srpaulo	}
263209139Srpaulo	timeout->time.usec += usecs;
264209139Srpaulo	while (timeout->time.usec >= 1000000) {
265209139Srpaulo		timeout->time.sec++;
266209139Srpaulo		timeout->time.usec -= 1000000;
267209139Srpaulo	}
268209139Srpaulo	timeout->eloop_data = eloop_data;
269209139Srpaulo	timeout->user_data = user_data;
270209139Srpaulo	timeout->handler = handler;
271209139Srpaulo
272281806Srpaulo	/* Maintain timeouts in order of increasing time */
273281806Srpaulo	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
274281806Srpaulo		if (os_reltime_before(&timeout->time, &tmp->time)) {
275281806Srpaulo			dl_list_add(tmp->list.prev, &timeout->list);
276281806Srpaulo			return 0;
277281806Srpaulo		}
278209139Srpaulo	}
279281806Srpaulo	dl_list_add_tail(&eloop.timeout, &timeout->list);
280209139Srpaulo
281281806Srpaulo	return 0;
282281806Srpaulo}
283209139Srpaulo
284209139Srpaulo
285281806Srpaulostatic void eloop_remove_timeout(struct eloop_timeout *timeout)
286281806Srpaulo{
287281806Srpaulo	dl_list_del(&timeout->list);
288281806Srpaulo	os_free(timeout);
289209139Srpaulo}
290209139Srpaulo
291209139Srpaulo
292209139Srpauloint eloop_cancel_timeout(eloop_timeout_handler handler,
293209139Srpaulo			 void *eloop_data, void *user_data)
294209139Srpaulo{
295281806Srpaulo	struct eloop_timeout *timeout, *prev;
296209139Srpaulo	int removed = 0;
297209139Srpaulo
298281806Srpaulo	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
299281806Srpaulo			      struct eloop_timeout, list) {
300209139Srpaulo		if (timeout->handler == handler &&
301209139Srpaulo		    (timeout->eloop_data == eloop_data ||
302209139Srpaulo		     eloop_data == ELOOP_ALL_CTX) &&
303209139Srpaulo		    (timeout->user_data == user_data ||
304209139Srpaulo		     user_data == ELOOP_ALL_CTX)) {
305281806Srpaulo			eloop_remove_timeout(timeout);
306209139Srpaulo			removed++;
307281806Srpaulo		}
308209139Srpaulo	}
309209139Srpaulo
310209139Srpaulo	return removed;
311209139Srpaulo}
312209139Srpaulo
313209139Srpaulo
314281806Srpauloint eloop_cancel_timeout_one(eloop_timeout_handler handler,
315281806Srpaulo			     void *eloop_data, void *user_data,
316281806Srpaulo			     struct os_reltime *remaining)
317281806Srpaulo{
318281806Srpaulo	struct eloop_timeout *timeout, *prev;
319281806Srpaulo	int removed = 0;
320281806Srpaulo	struct os_reltime now;
321281806Srpaulo
322281806Srpaulo	os_get_reltime(&now);
323281806Srpaulo	remaining->sec = remaining->usec = 0;
324281806Srpaulo
325281806Srpaulo	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
326281806Srpaulo			      struct eloop_timeout, list) {
327281806Srpaulo		if (timeout->handler == handler &&
328281806Srpaulo		    (timeout->eloop_data == eloop_data) &&
329281806Srpaulo		    (timeout->user_data == user_data)) {
330281806Srpaulo			removed = 1;
331281806Srpaulo			if (os_reltime_before(&now, &timeout->time))
332281806Srpaulo				os_reltime_sub(&timeout->time, &now, remaining);
333281806Srpaulo			eloop_remove_timeout(timeout);
334281806Srpaulo			break;
335281806Srpaulo		}
336281806Srpaulo	}
337281806Srpaulo	return removed;
338281806Srpaulo}
339281806Srpaulo
340281806Srpaulo
341209139Srpauloint eloop_is_timeout_registered(eloop_timeout_handler handler,
342209139Srpaulo				void *eloop_data, void *user_data)
343209139Srpaulo{
344209139Srpaulo	struct eloop_timeout *tmp;
345209139Srpaulo
346281806Srpaulo	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
347209139Srpaulo		if (tmp->handler == handler &&
348209139Srpaulo		    tmp->eloop_data == eloop_data &&
349209139Srpaulo		    tmp->user_data == user_data)
350209139Srpaulo			return 1;
351209139Srpaulo	}
352209139Srpaulo
353209139Srpaulo	return 0;
354209139Srpaulo}
355209139Srpaulo
356209139Srpaulo
357281806Srpauloint eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
358281806Srpaulo			  eloop_timeout_handler handler, void *eloop_data,
359281806Srpaulo			  void *user_data)
360281806Srpaulo{
361281806Srpaulo	struct os_reltime now, requested, remaining;
362281806Srpaulo	struct eloop_timeout *tmp;
363281806Srpaulo
364281806Srpaulo	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
365281806Srpaulo		if (tmp->handler == handler &&
366281806Srpaulo		    tmp->eloop_data == eloop_data &&
367281806Srpaulo		    tmp->user_data == user_data) {
368281806Srpaulo			requested.sec = req_secs;
369281806Srpaulo			requested.usec = req_usecs;
370281806Srpaulo			os_get_reltime(&now);
371281806Srpaulo			os_reltime_sub(&tmp->time, &now, &remaining);
372281806Srpaulo			if (os_reltime_before(&requested, &remaining)) {
373281806Srpaulo				eloop_cancel_timeout(handler, eloop_data,
374281806Srpaulo						     user_data);
375281806Srpaulo				eloop_register_timeout(requested.sec,
376281806Srpaulo						       requested.usec,
377281806Srpaulo						       handler, eloop_data,
378281806Srpaulo						       user_data);
379281806Srpaulo				return 1;
380281806Srpaulo			}
381281806Srpaulo			return 0;
382281806Srpaulo		}
383281806Srpaulo	}
384281806Srpaulo
385281806Srpaulo	return -1;
386281806Srpaulo}
387281806Srpaulo
388281806Srpaulo
389281806Srpauloint eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
390281806Srpaulo			    eloop_timeout_handler handler, void *eloop_data,
391281806Srpaulo			    void *user_data)
392281806Srpaulo{
393281806Srpaulo	struct os_reltime now, requested, remaining;
394281806Srpaulo	struct eloop_timeout *tmp;
395281806Srpaulo
396281806Srpaulo	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
397281806Srpaulo		if (tmp->handler == handler &&
398281806Srpaulo		    tmp->eloop_data == eloop_data &&
399281806Srpaulo		    tmp->user_data == user_data) {
400281806Srpaulo			requested.sec = req_secs;
401281806Srpaulo			requested.usec = req_usecs;
402281806Srpaulo			os_get_reltime(&now);
403281806Srpaulo			os_reltime_sub(&tmp->time, &now, &remaining);
404281806Srpaulo			if (os_reltime_before(&remaining, &requested)) {
405281806Srpaulo				eloop_cancel_timeout(handler, eloop_data,
406281806Srpaulo						     user_data);
407281806Srpaulo				eloop_register_timeout(requested.sec,
408281806Srpaulo						       requested.usec,
409281806Srpaulo						       handler, eloop_data,
410281806Srpaulo						       user_data);
411281806Srpaulo				return 1;
412281806Srpaulo			}
413281806Srpaulo			return 0;
414281806Srpaulo		}
415281806Srpaulo	}
416281806Srpaulo
417281806Srpaulo	return -1;
418281806Srpaulo}
419281806Srpaulo
420281806Srpaulo
421209139Srpaulo/* TODO: replace with suitable signal handler */
422209139Srpaulo#if 0
423209139Srpaulostatic void eloop_handle_signal(int sig)
424209139Srpaulo{
425209139Srpaulo	int i;
426209139Srpaulo
427209139Srpaulo	eloop.signaled++;
428209139Srpaulo	for (i = 0; i < eloop.signal_count; i++) {
429209139Srpaulo		if (eloop.signals[i].sig == sig) {
430209139Srpaulo			eloop.signals[i].signaled++;
431209139Srpaulo			break;
432209139Srpaulo		}
433209139Srpaulo	}
434209139Srpaulo}
435209139Srpaulo#endif
436209139Srpaulo
437209139Srpaulo
438209139Srpaulostatic void eloop_process_pending_signals(void)
439209139Srpaulo{
440209139Srpaulo	int i;
441209139Srpaulo
442209139Srpaulo	if (eloop.signaled == 0)
443209139Srpaulo		return;
444209139Srpaulo	eloop.signaled = 0;
445209139Srpaulo
446209139Srpaulo	if (eloop.pending_terminate) {
447209139Srpaulo		eloop.pending_terminate = 0;
448209139Srpaulo	}
449209139Srpaulo
450209139Srpaulo	for (i = 0; i < eloop.signal_count; i++) {
451209139Srpaulo		if (eloop.signals[i].signaled) {
452209139Srpaulo			eloop.signals[i].signaled = 0;
453209139Srpaulo			eloop.signals[i].handler(eloop.signals[i].sig,
454209139Srpaulo						 eloop.signals[i].user_data);
455209139Srpaulo		}
456209139Srpaulo	}
457209139Srpaulo
458209139Srpaulo	if (eloop.term_signal.signaled) {
459209139Srpaulo		eloop.term_signal.signaled = 0;
460209139Srpaulo		eloop.term_signal.handler(eloop.term_signal.sig,
461209139Srpaulo					  eloop.term_signal.user_data);
462209139Srpaulo	}
463209139Srpaulo}
464209139Srpaulo
465209139Srpaulo
466209139Srpauloint eloop_register_signal(int sig, eloop_signal_handler handler,
467209139Srpaulo			  void *user_data)
468209139Srpaulo{
469209139Srpaulo	struct eloop_signal *tmp;
470209139Srpaulo
471252726Srpaulo	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
472252726Srpaulo			       sizeof(struct eloop_signal));
473209139Srpaulo	if (tmp == NULL)
474209139Srpaulo		return -1;
475209139Srpaulo
476209139Srpaulo	tmp[eloop.signal_count].sig = sig;
477209139Srpaulo	tmp[eloop.signal_count].user_data = user_data;
478209139Srpaulo	tmp[eloop.signal_count].handler = handler;
479209139Srpaulo	tmp[eloop.signal_count].signaled = 0;
480209139Srpaulo	eloop.signal_count++;
481209139Srpaulo	eloop.signals = tmp;
482209139Srpaulo
483209139Srpaulo	/* TODO: register signal handler */
484209139Srpaulo
485209139Srpaulo	return 0;
486209139Srpaulo}
487209139Srpaulo
488209139Srpaulo
489209139Srpaulo#ifndef _WIN32_WCE
490209139Srpaulostatic BOOL eloop_handle_console_ctrl(DWORD type)
491209139Srpaulo{
492209139Srpaulo	switch (type) {
493209139Srpaulo	case CTRL_C_EVENT:
494209139Srpaulo	case CTRL_BREAK_EVENT:
495209139Srpaulo		eloop.signaled++;
496209139Srpaulo		eloop.term_signal.signaled++;
497209139Srpaulo		SetEvent(eloop.term_event);
498209139Srpaulo		return TRUE;
499209139Srpaulo	default:
500209139Srpaulo		return FALSE;
501209139Srpaulo	}
502209139Srpaulo}
503209139Srpaulo#endif /* _WIN32_WCE */
504209139Srpaulo
505209139Srpaulo
506209139Srpauloint eloop_register_signal_terminate(eloop_signal_handler handler,
507209139Srpaulo				    void *user_data)
508209139Srpaulo{
509209139Srpaulo#ifndef _WIN32_WCE
510209139Srpaulo	if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
511209139Srpaulo				  TRUE) == 0) {
512209139Srpaulo		printf("SetConsoleCtrlHandler() failed: %d\n",
513209139Srpaulo		       (int) GetLastError());
514209139Srpaulo		return -1;
515209139Srpaulo	}
516209139Srpaulo#endif /* _WIN32_WCE */
517209139Srpaulo
518209139Srpaulo	eloop.term_signal.handler = handler;
519209139Srpaulo	eloop.term_signal.user_data = user_data;
520209139Srpaulo
521209139Srpaulo	return 0;
522209139Srpaulo}
523209139Srpaulo
524209139Srpaulo
525209139Srpauloint eloop_register_signal_reconfig(eloop_signal_handler handler,
526209139Srpaulo				   void *user_data)
527209139Srpaulo{
528209139Srpaulo	/* TODO */
529209139Srpaulo	return 0;
530209139Srpaulo}
531209139Srpaulo
532209139Srpaulo
533209139Srpaulovoid eloop_run(void)
534209139Srpaulo{
535281806Srpaulo	struct os_reltime tv, now;
536281806Srpaulo	DWORD count, ret, timeout_val, err;
537209139Srpaulo	size_t i;
538209139Srpaulo
539209139Srpaulo	while (!eloop.terminate &&
540281806Srpaulo	       (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 ||
541209139Srpaulo		eloop.event_count > 0)) {
542281806Srpaulo		struct eloop_timeout *timeout;
543209139Srpaulo		tv.sec = tv.usec = 0;
544281806Srpaulo		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
545281806Srpaulo					list);
546281806Srpaulo		if (timeout) {
547281806Srpaulo			os_get_reltime(&now);
548281806Srpaulo			if (os_reltime_before(&now, &timeout->time))
549281806Srpaulo				os_reltime_sub(&timeout->time, &now, &tv);
550209139Srpaulo		}
551209139Srpaulo
552209139Srpaulo		count = 0;
553209139Srpaulo		for (i = 0; i < eloop.event_count; i++)
554209139Srpaulo			eloop.handles[count++] = eloop.events[i].event;
555209139Srpaulo
556209139Srpaulo		for (i = 0; i < eloop.reader_count; i++)
557209139Srpaulo			eloop.handles[count++] = eloop.readers[i].event;
558209139Srpaulo
559209139Srpaulo		if (eloop.term_event)
560209139Srpaulo			eloop.handles[count++] = eloop.term_event;
561209139Srpaulo
562281806Srpaulo		if (timeout)
563281806Srpaulo			timeout_val = tv.sec * 1000 + tv.usec / 1000;
564209139Srpaulo		else
565281806Srpaulo			timeout_val = INFINITE;
566209139Srpaulo
567209139Srpaulo		if (count > MAXIMUM_WAIT_OBJECTS) {
568209139Srpaulo			printf("WaitForMultipleObjects: Too many events: "
569209139Srpaulo			       "%d > %d (ignoring extra events)\n",
570209139Srpaulo			       (int) count, MAXIMUM_WAIT_OBJECTS);
571209139Srpaulo			count = MAXIMUM_WAIT_OBJECTS;
572209139Srpaulo		}
573209139Srpaulo#ifdef _WIN32_WCE
574209139Srpaulo		ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
575281806Srpaulo					     timeout_val);
576209139Srpaulo#else /* _WIN32_WCE */
577209139Srpaulo		ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
578281806Srpaulo					       timeout_val, TRUE);
579209139Srpaulo#endif /* _WIN32_WCE */
580209139Srpaulo		err = GetLastError();
581209139Srpaulo
582209139Srpaulo		eloop_process_pending_signals();
583209139Srpaulo
584209139Srpaulo		/* check if some registered timeouts have occurred */
585281806Srpaulo		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
586281806Srpaulo					list);
587281806Srpaulo		if (timeout) {
588281806Srpaulo			os_get_reltime(&now);
589281806Srpaulo			if (!os_reltime_before(&now, &timeout->time)) {
590281806Srpaulo				void *eloop_data = timeout->eloop_data;
591281806Srpaulo				void *user_data = timeout->user_data;
592281806Srpaulo				eloop_timeout_handler handler =
593281806Srpaulo					timeout->handler;
594281806Srpaulo				eloop_remove_timeout(timeout);
595281806Srpaulo				handler(eloop_data, user_data);
596209139Srpaulo			}
597209139Srpaulo
598209139Srpaulo		}
599209139Srpaulo
600209139Srpaulo		if (ret == WAIT_FAILED) {
601209139Srpaulo			printf("WaitForMultipleObjects(count=%d) failed: %d\n",
602209139Srpaulo			       (int) count, (int) err);
603209139Srpaulo			os_sleep(1, 0);
604209139Srpaulo			continue;
605209139Srpaulo		}
606209139Srpaulo
607209139Srpaulo#ifndef _WIN32_WCE
608209139Srpaulo		if (ret == WAIT_IO_COMPLETION)
609209139Srpaulo			continue;
610209139Srpaulo#endif /* _WIN32_WCE */
611209139Srpaulo
612209139Srpaulo		if (ret == WAIT_TIMEOUT)
613209139Srpaulo			continue;
614209139Srpaulo
615209139Srpaulo		while (ret >= WAIT_OBJECT_0 &&
616209139Srpaulo		       ret < WAIT_OBJECT_0 + eloop.event_count) {
617209139Srpaulo			eloop.events[ret].handler(
618209139Srpaulo				eloop.events[ret].eloop_data,
619209139Srpaulo				eloop.events[ret].user_data);
620209139Srpaulo			ret = WaitForMultipleObjects(eloop.event_count,
621209139Srpaulo						     eloop.handles, FALSE, 0);
622209139Srpaulo		}
623209139Srpaulo
624209139Srpaulo		eloop.reader_table_changed = 0;
625209139Srpaulo		for (i = 0; i < eloop.reader_count; i++) {
626209139Srpaulo			WSANETWORKEVENTS events;
627209139Srpaulo			if (WSAEnumNetworkEvents(eloop.readers[i].sock,
628209139Srpaulo						 eloop.readers[i].event,
629209139Srpaulo						 &events) == 0 &&
630209139Srpaulo			    (events.lNetworkEvents & FD_READ)) {
631209139Srpaulo				eloop.readers[i].handler(
632209139Srpaulo					eloop.readers[i].sock,
633209139Srpaulo					eloop.readers[i].eloop_data,
634209139Srpaulo					eloop.readers[i].user_data);
635209139Srpaulo				if (eloop.reader_table_changed)
636209139Srpaulo					break;
637209139Srpaulo			}
638209139Srpaulo		}
639209139Srpaulo	}
640209139Srpaulo}
641209139Srpaulo
642209139Srpaulo
643209139Srpaulovoid eloop_terminate(void)
644209139Srpaulo{
645209139Srpaulo	eloop.terminate = 1;
646209139Srpaulo	SetEvent(eloop.term_event);
647209139Srpaulo}
648209139Srpaulo
649209139Srpaulo
650209139Srpaulovoid eloop_destroy(void)
651209139Srpaulo{
652209139Srpaulo	struct eloop_timeout *timeout, *prev;
653209139Srpaulo
654281806Srpaulo	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
655281806Srpaulo			      struct eloop_timeout, list) {
656281806Srpaulo		eloop_remove_timeout(timeout);
657209139Srpaulo	}
658209139Srpaulo	os_free(eloop.readers);
659209139Srpaulo	os_free(eloop.signals);
660209139Srpaulo	if (eloop.term_event)
661209139Srpaulo		CloseHandle(eloop.term_event);
662209139Srpaulo	os_free(eloop.handles);
663209139Srpaulo	eloop.handles = NULL;
664209139Srpaulo	os_free(eloop.events);
665209139Srpaulo	eloop.events = NULL;
666209139Srpaulo}
667209139Srpaulo
668209139Srpaulo
669209139Srpauloint eloop_terminated(void)
670209139Srpaulo{
671209139Srpaulo	return eloop.terminate;
672209139Srpaulo}
673209139Srpaulo
674209139Srpaulo
675209139Srpaulovoid eloop_wait_for_read_sock(int sock)
676209139Srpaulo{
677209139Srpaulo	WSAEVENT event;
678209139Srpaulo
679209139Srpaulo	event = WSACreateEvent();
680209139Srpaulo	if (event == WSA_INVALID_EVENT) {
681209139Srpaulo		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
682209139Srpaulo		return;
683209139Srpaulo	}
684209139Srpaulo
685209139Srpaulo	if (WSAEventSelect(sock, event, FD_READ)) {
686209139Srpaulo		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
687209139Srpaulo		WSACloseEvent(event);
688209139Srpaulo		return ;
689209139Srpaulo	}
690209139Srpaulo
691209139Srpaulo	WaitForSingleObject(event, INFINITE);
692209139Srpaulo	WSAEventSelect(sock, event, 0);
693209139Srpaulo	WSACloseEvent(event);
694209139Srpaulo}
695337817Scy
696337817Scy
697337817Scyint eloop_sock_requeue(void)
698337817Scy{
699337817Scy	return 0;
700337817Scy}
701