xref: /netbsd/external/bsd/wpa/dist/src/utils/eloop_win.c (revision 928750b6)
18dbcf02cSchristos /*
28dbcf02cSchristos  * Event loop based on Windows events and WaitForMultipleObjects
336d97821Schristos  * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
562a52023Schristos  * This software may be distributed under the terms of the BSD license.
662a52023Schristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos #include <winsock2.h>
118dbcf02cSchristos 
128dbcf02cSchristos #include "common.h"
1336d97821Schristos #include "list.h"
148dbcf02cSchristos #include "eloop.h"
158dbcf02cSchristos 
168dbcf02cSchristos 
178dbcf02cSchristos struct eloop_sock {
188dbcf02cSchristos 	int sock;
198dbcf02cSchristos 	void *eloop_data;
208dbcf02cSchristos 	void *user_data;
218dbcf02cSchristos 	eloop_sock_handler handler;
228dbcf02cSchristos 	WSAEVENT event;
238dbcf02cSchristos };
248dbcf02cSchristos 
258dbcf02cSchristos struct eloop_event {
268dbcf02cSchristos 	void *eloop_data;
278dbcf02cSchristos 	void *user_data;
288dbcf02cSchristos 	eloop_event_handler handler;
298dbcf02cSchristos 	HANDLE event;
308dbcf02cSchristos };
318dbcf02cSchristos 
328dbcf02cSchristos struct eloop_timeout {
3336d97821Schristos 	struct dl_list list;
3436d97821Schristos 	struct os_reltime time;
358dbcf02cSchristos 	void *eloop_data;
368dbcf02cSchristos 	void *user_data;
378dbcf02cSchristos 	eloop_timeout_handler handler;
388dbcf02cSchristos };
398dbcf02cSchristos 
408dbcf02cSchristos struct eloop_signal {
418dbcf02cSchristos 	int sig;
428dbcf02cSchristos 	void *user_data;
438dbcf02cSchristos 	eloop_signal_handler handler;
448dbcf02cSchristos 	int signaled;
458dbcf02cSchristos };
468dbcf02cSchristos 
478dbcf02cSchristos struct eloop_data {
488dbcf02cSchristos 	int max_sock;
498dbcf02cSchristos 	size_t reader_count;
508dbcf02cSchristos 	struct eloop_sock *readers;
518dbcf02cSchristos 
528dbcf02cSchristos 	size_t event_count;
538dbcf02cSchristos 	struct eloop_event *events;
548dbcf02cSchristos 
5536d97821Schristos 	struct dl_list timeout;
568dbcf02cSchristos 
578dbcf02cSchristos 	int signal_count;
588dbcf02cSchristos 	struct eloop_signal *signals;
598dbcf02cSchristos 	int signaled;
608dbcf02cSchristos 	int pending_terminate;
618dbcf02cSchristos 
628dbcf02cSchristos 	int terminate;
638dbcf02cSchristos 	int reader_table_changed;
648dbcf02cSchristos 
658dbcf02cSchristos 	struct eloop_signal term_signal;
668dbcf02cSchristos 	HANDLE term_event;
678dbcf02cSchristos 
688dbcf02cSchristos 	HANDLE *handles;
698dbcf02cSchristos 	size_t num_handles;
708dbcf02cSchristos };
718dbcf02cSchristos 
728dbcf02cSchristos static struct eloop_data eloop;
738dbcf02cSchristos 
748dbcf02cSchristos 
eloop_init(void)758dbcf02cSchristos int eloop_init(void)
768dbcf02cSchristos {
778dbcf02cSchristos 	os_memset(&eloop, 0, sizeof(eloop));
7836d97821Schristos 	dl_list_init(&eloop.timeout);
798dbcf02cSchristos 	eloop.num_handles = 1;
808dbcf02cSchristos 	eloop.handles = os_malloc(eloop.num_handles *
818dbcf02cSchristos 				  sizeof(eloop.handles[0]));
828dbcf02cSchristos 	if (eloop.handles == NULL)
838dbcf02cSchristos 		return -1;
848dbcf02cSchristos 
858dbcf02cSchristos 	eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
868dbcf02cSchristos 	if (eloop.term_event == NULL) {
878dbcf02cSchristos 		printf("CreateEvent() failed: %d\n",
888dbcf02cSchristos 		       (int) GetLastError());
898dbcf02cSchristos 		os_free(eloop.handles);
908dbcf02cSchristos 		return -1;
918dbcf02cSchristos 	}
928dbcf02cSchristos 
938dbcf02cSchristos 	return 0;
948dbcf02cSchristos }
958dbcf02cSchristos 
968dbcf02cSchristos 
eloop_prepare_handles(void)978dbcf02cSchristos static int eloop_prepare_handles(void)
988dbcf02cSchristos {
998dbcf02cSchristos 	HANDLE *n;
1008dbcf02cSchristos 
1018dbcf02cSchristos 	if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
1028dbcf02cSchristos 		return 0;
10362a52023Schristos 	n = os_realloc_array(eloop.handles, eloop.num_handles * 2,
10462a52023Schristos 			     sizeof(eloop.handles[0]));
1058dbcf02cSchristos 	if (n == NULL)
1068dbcf02cSchristos 		return -1;
1078dbcf02cSchristos 	eloop.handles = n;
1088dbcf02cSchristos 	eloop.num_handles *= 2;
1098dbcf02cSchristos 	return 0;
1108dbcf02cSchristos }
1118dbcf02cSchristos 
1128dbcf02cSchristos 
eloop_register_read_sock(int sock,eloop_sock_handler handler,void * eloop_data,void * user_data)1138dbcf02cSchristos int eloop_register_read_sock(int sock, eloop_sock_handler handler,
1148dbcf02cSchristos 			     void *eloop_data, void *user_data)
1158dbcf02cSchristos {
1168dbcf02cSchristos 	WSAEVENT event;
1178dbcf02cSchristos 	struct eloop_sock *tmp;
1188dbcf02cSchristos 
1198dbcf02cSchristos 	if (eloop_prepare_handles())
1208dbcf02cSchristos 		return -1;
1218dbcf02cSchristos 
1228dbcf02cSchristos 	event = WSACreateEvent();
1238dbcf02cSchristos 	if (event == WSA_INVALID_EVENT) {
1248dbcf02cSchristos 		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
1258dbcf02cSchristos 		return -1;
1268dbcf02cSchristos 	}
1278dbcf02cSchristos 
1288dbcf02cSchristos 	if (WSAEventSelect(sock, event, FD_READ)) {
1298dbcf02cSchristos 		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
1308dbcf02cSchristos 		WSACloseEvent(event);
1318dbcf02cSchristos 		return -1;
1328dbcf02cSchristos 	}
13362a52023Schristos 	tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1,
13462a52023Schristos 			       sizeof(struct eloop_sock));
1358dbcf02cSchristos 	if (tmp == NULL) {
1368dbcf02cSchristos 		WSAEventSelect(sock, event, 0);
1378dbcf02cSchristos 		WSACloseEvent(event);
1388dbcf02cSchristos 		return -1;
1398dbcf02cSchristos 	}
1408dbcf02cSchristos 
1418dbcf02cSchristos 	tmp[eloop.reader_count].sock = sock;
1428dbcf02cSchristos 	tmp[eloop.reader_count].eloop_data = eloop_data;
1438dbcf02cSchristos 	tmp[eloop.reader_count].user_data = user_data;
1448dbcf02cSchristos 	tmp[eloop.reader_count].handler = handler;
1458dbcf02cSchristos 	tmp[eloop.reader_count].event = event;
1468dbcf02cSchristos 	eloop.reader_count++;
1478dbcf02cSchristos 	eloop.readers = tmp;
1488dbcf02cSchristos 	if (sock > eloop.max_sock)
1498dbcf02cSchristos 		eloop.max_sock = sock;
1508dbcf02cSchristos 	eloop.reader_table_changed = 1;
1518dbcf02cSchristos 
1528dbcf02cSchristos 	return 0;
1538dbcf02cSchristos }
1548dbcf02cSchristos 
1558dbcf02cSchristos 
eloop_unregister_read_sock(int sock)1568dbcf02cSchristos void eloop_unregister_read_sock(int sock)
1578dbcf02cSchristos {
1588dbcf02cSchristos 	size_t i;
1598dbcf02cSchristos 
1608dbcf02cSchristos 	if (eloop.readers == NULL || eloop.reader_count == 0)
1618dbcf02cSchristos 		return;
1628dbcf02cSchristos 
1638dbcf02cSchristos 	for (i = 0; i < eloop.reader_count; i++) {
1648dbcf02cSchristos 		if (eloop.readers[i].sock == sock)
1658dbcf02cSchristos 			break;
1668dbcf02cSchristos 	}
1678dbcf02cSchristos 	if (i == eloop.reader_count)
1688dbcf02cSchristos 		return;
1698dbcf02cSchristos 
1708dbcf02cSchristos 	WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
1718dbcf02cSchristos 	WSACloseEvent(eloop.readers[i].event);
1728dbcf02cSchristos 
1738dbcf02cSchristos 	if (i != eloop.reader_count - 1) {
1748dbcf02cSchristos 		os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
1758dbcf02cSchristos 			   (eloop.reader_count - i - 1) *
1768dbcf02cSchristos 			   sizeof(struct eloop_sock));
1778dbcf02cSchristos 	}
1788dbcf02cSchristos 	eloop.reader_count--;
1798dbcf02cSchristos 	eloop.reader_table_changed = 1;
1808dbcf02cSchristos }
1818dbcf02cSchristos 
1828dbcf02cSchristos 
eloop_register_event(void * event,size_t event_size,eloop_event_handler handler,void * eloop_data,void * user_data)1838dbcf02cSchristos int eloop_register_event(void *event, size_t event_size,
1848dbcf02cSchristos 			 eloop_event_handler handler,
1858dbcf02cSchristos 			 void *eloop_data, void *user_data)
1868dbcf02cSchristos {
1878dbcf02cSchristos 	struct eloop_event *tmp;
1888dbcf02cSchristos 	HANDLE h = event;
1898dbcf02cSchristos 
1908dbcf02cSchristos 	if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
1918dbcf02cSchristos 		return -1;
1928dbcf02cSchristos 
1938dbcf02cSchristos 	if (eloop_prepare_handles())
1948dbcf02cSchristos 		return -1;
1958dbcf02cSchristos 
19662a52023Schristos 	tmp = os_realloc_array(eloop.events, eloop.event_count + 1,
19762a52023Schristos 			       sizeof(struct eloop_event));
1988dbcf02cSchristos 	if (tmp == NULL)
1998dbcf02cSchristos 		return -1;
2008dbcf02cSchristos 
2018dbcf02cSchristos 	tmp[eloop.event_count].eloop_data = eloop_data;
2028dbcf02cSchristos 	tmp[eloop.event_count].user_data = user_data;
2038dbcf02cSchristos 	tmp[eloop.event_count].handler = handler;
2048dbcf02cSchristos 	tmp[eloop.event_count].event = h;
2058dbcf02cSchristos 	eloop.event_count++;
2068dbcf02cSchristos 	eloop.events = tmp;
2078dbcf02cSchristos 
2088dbcf02cSchristos 	return 0;
2098dbcf02cSchristos }
2108dbcf02cSchristos 
2118dbcf02cSchristos 
eloop_unregister_event(void * event,size_t event_size)2128dbcf02cSchristos void eloop_unregister_event(void *event, size_t event_size)
2138dbcf02cSchristos {
2148dbcf02cSchristos 	size_t i;
2158dbcf02cSchristos 	HANDLE h = event;
2168dbcf02cSchristos 
2178dbcf02cSchristos 	if (eloop.events == NULL || eloop.event_count == 0 ||
2188dbcf02cSchristos 	    event_size != sizeof(HANDLE))
2198dbcf02cSchristos 		return;
2208dbcf02cSchristos 
2218dbcf02cSchristos 	for (i = 0; i < eloop.event_count; i++) {
2228dbcf02cSchristos 		if (eloop.events[i].event == h)
2238dbcf02cSchristos 			break;
2248dbcf02cSchristos 	}
2258dbcf02cSchristos 	if (i == eloop.event_count)
2268dbcf02cSchristos 		return;
2278dbcf02cSchristos 
2288dbcf02cSchristos 	if (i != eloop.event_count - 1) {
2298dbcf02cSchristos 		os_memmove(&eloop.events[i], &eloop.events[i + 1],
2308dbcf02cSchristos 			   (eloop.event_count - i - 1) *
2318dbcf02cSchristos 			   sizeof(struct eloop_event));
2328dbcf02cSchristos 	}
2338dbcf02cSchristos 	eloop.event_count--;
2348dbcf02cSchristos }
2358dbcf02cSchristos 
2368dbcf02cSchristos 
eloop_register_timeout(unsigned int secs,unsigned int usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)2378dbcf02cSchristos int eloop_register_timeout(unsigned int secs, unsigned int usecs,
2388dbcf02cSchristos 			   eloop_timeout_handler handler,
2398dbcf02cSchristos 			   void *eloop_data, void *user_data)
2408dbcf02cSchristos {
24136d97821Schristos 	struct eloop_timeout *timeout, *tmp;
24242669be3Schristos 	os_time_t now_sec;
2438dbcf02cSchristos 
24436d97821Schristos 	timeout = os_zalloc(sizeof(*timeout));
2458dbcf02cSchristos 	if (timeout == NULL)
2468dbcf02cSchristos 		return -1;
24736d97821Schristos 	if (os_get_reltime(&timeout->time) < 0) {
24836d97821Schristos 		os_free(timeout);
24936d97821Schristos 		return -1;
25036d97821Schristos 	}
25142669be3Schristos 	now_sec = timeout->time.sec;
2528dbcf02cSchristos 	timeout->time.sec += secs;
25342669be3Schristos 	if (timeout->time.sec < now_sec) {
25442669be3Schristos 		/*
25542669be3Schristos 		 * Integer overflow - assume long enough timeout to be assumed
25642669be3Schristos 		 * to be infinite, i.e., the timeout would never happen.
25742669be3Schristos 		 */
25842669be3Schristos 		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
25942669be3Schristos 			   "ever happen - ignore it", secs);
26042669be3Schristos 		os_free(timeout);
26142669be3Schristos 		return 0;
26242669be3Schristos 	}
2638dbcf02cSchristos 	timeout->time.usec += usecs;
2648dbcf02cSchristos 	while (timeout->time.usec >= 1000000) {
2658dbcf02cSchristos 		timeout->time.sec++;
2668dbcf02cSchristos 		timeout->time.usec -= 1000000;
2678dbcf02cSchristos 	}
2688dbcf02cSchristos 	timeout->eloop_data = eloop_data;
2698dbcf02cSchristos 	timeout->user_data = user_data;
2708dbcf02cSchristos 	timeout->handler = handler;
2718dbcf02cSchristos 
27236d97821Schristos 	/* Maintain timeouts in order of increasing time */
27336d97821Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
27436d97821Schristos 		if (os_reltime_before(&timeout->time, &tmp->time)) {
27536d97821Schristos 			dl_list_add(tmp->list.prev, &timeout->list);
27636d97821Schristos 			return 0;
27736d97821Schristos 		}
27836d97821Schristos 	}
27936d97821Schristos 	dl_list_add_tail(&eloop.timeout, &timeout->list);
28036d97821Schristos 
2818dbcf02cSchristos 	return 0;
2828dbcf02cSchristos }
2838dbcf02cSchristos 
2848dbcf02cSchristos 
eloop_remove_timeout(struct eloop_timeout * timeout)28536d97821Schristos static void eloop_remove_timeout(struct eloop_timeout *timeout)
28636d97821Schristos {
28736d97821Schristos 	dl_list_del(&timeout->list);
28836d97821Schristos 	os_free(timeout);
2898dbcf02cSchristos }
2908dbcf02cSchristos 
2918dbcf02cSchristos 
eloop_cancel_timeout(eloop_timeout_handler handler,void * eloop_data,void * user_data)2928dbcf02cSchristos int eloop_cancel_timeout(eloop_timeout_handler handler,
2938dbcf02cSchristos 			 void *eloop_data, void *user_data)
2948dbcf02cSchristos {
29536d97821Schristos 	struct eloop_timeout *timeout, *prev;
2968dbcf02cSchristos 	int removed = 0;
2978dbcf02cSchristos 
29836d97821Schristos 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
29936d97821Schristos 			      struct eloop_timeout, list) {
3008dbcf02cSchristos 		if (timeout->handler == handler &&
3018dbcf02cSchristos 		    (timeout->eloop_data == eloop_data ||
3028dbcf02cSchristos 		     eloop_data == ELOOP_ALL_CTX) &&
3038dbcf02cSchristos 		    (timeout->user_data == user_data ||
3048dbcf02cSchristos 		     user_data == ELOOP_ALL_CTX)) {
30536d97821Schristos 			eloop_remove_timeout(timeout);
3068dbcf02cSchristos 			removed++;
30736d97821Schristos 		}
3088dbcf02cSchristos 	}
3098dbcf02cSchristos 
3108dbcf02cSchristos 	return removed;
3118dbcf02cSchristos }
3128dbcf02cSchristos 
3138dbcf02cSchristos 
eloop_cancel_timeout_one(eloop_timeout_handler handler,void * eloop_data,void * user_data,struct os_reltime * remaining)31436d97821Schristos int eloop_cancel_timeout_one(eloop_timeout_handler handler,
31536d97821Schristos 			     void *eloop_data, void *user_data,
31636d97821Schristos 			     struct os_reltime *remaining)
31736d97821Schristos {
31836d97821Schristos 	struct eloop_timeout *timeout, *prev;
31936d97821Schristos 	int removed = 0;
32036d97821Schristos 	struct os_reltime now;
32136d97821Schristos 
32236d97821Schristos 	os_get_reltime(&now);
32336d97821Schristos 	remaining->sec = remaining->usec = 0;
32436d97821Schristos 
32536d97821Schristos 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
32636d97821Schristos 			      struct eloop_timeout, list) {
32736d97821Schristos 		if (timeout->handler == handler &&
32836d97821Schristos 		    (timeout->eloop_data == eloop_data) &&
32936d97821Schristos 		    (timeout->user_data == user_data)) {
33036d97821Schristos 			removed = 1;
33136d97821Schristos 			if (os_reltime_before(&now, &timeout->time))
33236d97821Schristos 				os_reltime_sub(&timeout->time, &now, remaining);
33336d97821Schristos 			eloop_remove_timeout(timeout);
33436d97821Schristos 			break;
33536d97821Schristos 		}
33636d97821Schristos 	}
33736d97821Schristos 	return removed;
33836d97821Schristos }
33936d97821Schristos 
34036d97821Schristos 
eloop_is_timeout_registered(eloop_timeout_handler handler,void * eloop_data,void * user_data)3418dbcf02cSchristos int eloop_is_timeout_registered(eloop_timeout_handler handler,
3428dbcf02cSchristos 				void *eloop_data, void *user_data)
3438dbcf02cSchristos {
3448dbcf02cSchristos 	struct eloop_timeout *tmp;
3458dbcf02cSchristos 
34636d97821Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
3478dbcf02cSchristos 		if (tmp->handler == handler &&
3488dbcf02cSchristos 		    tmp->eloop_data == eloop_data &&
3498dbcf02cSchristos 		    tmp->user_data == user_data)
3508dbcf02cSchristos 			return 1;
3518dbcf02cSchristos 	}
3528dbcf02cSchristos 
3538dbcf02cSchristos 	return 0;
3548dbcf02cSchristos }
3558dbcf02cSchristos 
3568dbcf02cSchristos 
eloop_deplete_timeout(unsigned int req_secs,unsigned int req_usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)35736d97821Schristos int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
35836d97821Schristos 			  eloop_timeout_handler handler, void *eloop_data,
35936d97821Schristos 			  void *user_data)
36036d97821Schristos {
36136d97821Schristos 	struct os_reltime now, requested, remaining;
36236d97821Schristos 	struct eloop_timeout *tmp;
36336d97821Schristos 
36436d97821Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
36536d97821Schristos 		if (tmp->handler == handler &&
36636d97821Schristos 		    tmp->eloop_data == eloop_data &&
36736d97821Schristos 		    tmp->user_data == user_data) {
36836d97821Schristos 			requested.sec = req_secs;
36936d97821Schristos 			requested.usec = req_usecs;
37036d97821Schristos 			os_get_reltime(&now);
37136d97821Schristos 			os_reltime_sub(&tmp->time, &now, &remaining);
37236d97821Schristos 			if (os_reltime_before(&requested, &remaining)) {
37336d97821Schristos 				eloop_cancel_timeout(handler, eloop_data,
37436d97821Schristos 						     user_data);
37536d97821Schristos 				eloop_register_timeout(requested.sec,
37636d97821Schristos 						       requested.usec,
37736d97821Schristos 						       handler, eloop_data,
37836d97821Schristos 						       user_data);
37936d97821Schristos 				return 1;
38036d97821Schristos 			}
38136d97821Schristos 			return 0;
38236d97821Schristos 		}
38336d97821Schristos 	}
38436d97821Schristos 
38536d97821Schristos 	return -1;
38636d97821Schristos }
38736d97821Schristos 
38836d97821Schristos 
eloop_replenish_timeout(unsigned int req_secs,unsigned int req_usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)38936d97821Schristos int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
39036d97821Schristos 			    eloop_timeout_handler handler, void *eloop_data,
39136d97821Schristos 			    void *user_data)
39236d97821Schristos {
39336d97821Schristos 	struct os_reltime now, requested, remaining;
39436d97821Schristos 	struct eloop_timeout *tmp;
39536d97821Schristos 
39636d97821Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
39736d97821Schristos 		if (tmp->handler == handler &&
39836d97821Schristos 		    tmp->eloop_data == eloop_data &&
39936d97821Schristos 		    tmp->user_data == user_data) {
40036d97821Schristos 			requested.sec = req_secs;
40136d97821Schristos 			requested.usec = req_usecs;
40236d97821Schristos 			os_get_reltime(&now);
40336d97821Schristos 			os_reltime_sub(&tmp->time, &now, &remaining);
40436d97821Schristos 			if (os_reltime_before(&remaining, &requested)) {
40536d97821Schristos 				eloop_cancel_timeout(handler, eloop_data,
40636d97821Schristos 						     user_data);
40736d97821Schristos 				eloop_register_timeout(requested.sec,
40836d97821Schristos 						       requested.usec,
40936d97821Schristos 						       handler, eloop_data,
41036d97821Schristos 						       user_data);
41136d97821Schristos 				return 1;
41236d97821Schristos 			}
41336d97821Schristos 			return 0;
41436d97821Schristos 		}
41536d97821Schristos 	}
41636d97821Schristos 
41736d97821Schristos 	return -1;
41836d97821Schristos }
41936d97821Schristos 
42036d97821Schristos 
4218dbcf02cSchristos /* TODO: replace with suitable signal handler */
4228dbcf02cSchristos #if 0
4238dbcf02cSchristos static void eloop_handle_signal(int sig)
4248dbcf02cSchristos {
4258dbcf02cSchristos 	int i;
4268dbcf02cSchristos 
4278dbcf02cSchristos 	eloop.signaled++;
4288dbcf02cSchristos 	for (i = 0; i < eloop.signal_count; i++) {
4298dbcf02cSchristos 		if (eloop.signals[i].sig == sig) {
4308dbcf02cSchristos 			eloop.signals[i].signaled++;
4318dbcf02cSchristos 			break;
4328dbcf02cSchristos 		}
4338dbcf02cSchristos 	}
4348dbcf02cSchristos }
4358dbcf02cSchristos #endif
4368dbcf02cSchristos 
4378dbcf02cSchristos 
eloop_process_pending_signals(void)4388dbcf02cSchristos static void eloop_process_pending_signals(void)
4398dbcf02cSchristos {
4408dbcf02cSchristos 	int i;
4418dbcf02cSchristos 
4428dbcf02cSchristos 	if (eloop.signaled == 0)
4438dbcf02cSchristos 		return;
4448dbcf02cSchristos 	eloop.signaled = 0;
4458dbcf02cSchristos 
4468dbcf02cSchristos 	if (eloop.pending_terminate) {
4478dbcf02cSchristos 		eloop.pending_terminate = 0;
4488dbcf02cSchristos 	}
4498dbcf02cSchristos 
4508dbcf02cSchristos 	for (i = 0; i < eloop.signal_count; i++) {
4518dbcf02cSchristos 		if (eloop.signals[i].signaled) {
4528dbcf02cSchristos 			eloop.signals[i].signaled = 0;
4538dbcf02cSchristos 			eloop.signals[i].handler(eloop.signals[i].sig,
4548dbcf02cSchristos 						 eloop.signals[i].user_data);
4558dbcf02cSchristos 		}
4568dbcf02cSchristos 	}
4578dbcf02cSchristos 
4588dbcf02cSchristos 	if (eloop.term_signal.signaled) {
4598dbcf02cSchristos 		eloop.term_signal.signaled = 0;
4608dbcf02cSchristos 		eloop.term_signal.handler(eloop.term_signal.sig,
4618dbcf02cSchristos 					  eloop.term_signal.user_data);
4628dbcf02cSchristos 	}
4638dbcf02cSchristos }
4648dbcf02cSchristos 
4658dbcf02cSchristos 
eloop_register_signal(int sig,eloop_signal_handler handler,void * user_data)4668dbcf02cSchristos int eloop_register_signal(int sig, eloop_signal_handler handler,
4678dbcf02cSchristos 			  void *user_data)
4688dbcf02cSchristos {
4698dbcf02cSchristos 	struct eloop_signal *tmp;
4708dbcf02cSchristos 
47162a52023Schristos 	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
4728dbcf02cSchristos 			       sizeof(struct eloop_signal));
4738dbcf02cSchristos 	if (tmp == NULL)
4748dbcf02cSchristos 		return -1;
4758dbcf02cSchristos 
4768dbcf02cSchristos 	tmp[eloop.signal_count].sig = sig;
4778dbcf02cSchristos 	tmp[eloop.signal_count].user_data = user_data;
4788dbcf02cSchristos 	tmp[eloop.signal_count].handler = handler;
4798dbcf02cSchristos 	tmp[eloop.signal_count].signaled = 0;
4808dbcf02cSchristos 	eloop.signal_count++;
4818dbcf02cSchristos 	eloop.signals = tmp;
4828dbcf02cSchristos 
4838dbcf02cSchristos 	/* TODO: register signal handler */
4848dbcf02cSchristos 
4858dbcf02cSchristos 	return 0;
4868dbcf02cSchristos }
4878dbcf02cSchristos 
4888dbcf02cSchristos 
4898dbcf02cSchristos #ifndef _WIN32_WCE
eloop_handle_console_ctrl(DWORD type)4908dbcf02cSchristos static BOOL eloop_handle_console_ctrl(DWORD type)
4918dbcf02cSchristos {
4928dbcf02cSchristos 	switch (type) {
4938dbcf02cSchristos 	case CTRL_C_EVENT:
4948dbcf02cSchristos 	case CTRL_BREAK_EVENT:
4958dbcf02cSchristos 		eloop.signaled++;
4968dbcf02cSchristos 		eloop.term_signal.signaled++;
4978dbcf02cSchristos 		SetEvent(eloop.term_event);
4988dbcf02cSchristos 		return TRUE;
4998dbcf02cSchristos 	default:
5008dbcf02cSchristos 		return FALSE;
5018dbcf02cSchristos 	}
5028dbcf02cSchristos }
5038dbcf02cSchristos #endif /* _WIN32_WCE */
5048dbcf02cSchristos 
5058dbcf02cSchristos 
eloop_register_signal_terminate(eloop_signal_handler handler,void * user_data)5068dbcf02cSchristos int eloop_register_signal_terminate(eloop_signal_handler handler,
5078dbcf02cSchristos 				    void *user_data)
5088dbcf02cSchristos {
5098dbcf02cSchristos #ifndef _WIN32_WCE
5108dbcf02cSchristos 	if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
5118dbcf02cSchristos 				  TRUE) == 0) {
5128dbcf02cSchristos 		printf("SetConsoleCtrlHandler() failed: %d\n",
5138dbcf02cSchristos 		       (int) GetLastError());
5148dbcf02cSchristos 		return -1;
5158dbcf02cSchristos 	}
5168dbcf02cSchristos #endif /* _WIN32_WCE */
5178dbcf02cSchristos 
5188dbcf02cSchristos 	eloop.term_signal.handler = handler;
5198dbcf02cSchristos 	eloop.term_signal.user_data = user_data;
5208dbcf02cSchristos 
5218dbcf02cSchristos 	return 0;
5228dbcf02cSchristos }
5238dbcf02cSchristos 
5248dbcf02cSchristos 
eloop_register_signal_reconfig(eloop_signal_handler handler,void * user_data)5258dbcf02cSchristos int eloop_register_signal_reconfig(eloop_signal_handler handler,
5268dbcf02cSchristos 				   void *user_data)
5278dbcf02cSchristos {
5288dbcf02cSchristos 	/* TODO */
5298dbcf02cSchristos 	return 0;
5308dbcf02cSchristos }
5318dbcf02cSchristos 
5328dbcf02cSchristos 
eloop_run(void)5338dbcf02cSchristos void eloop_run(void)
5348dbcf02cSchristos {
53536d97821Schristos 	struct os_reltime tv, now;
53636d97821Schristos 	DWORD count, ret, timeout_val, err;
5378dbcf02cSchristos 	size_t i;
5388dbcf02cSchristos 
5398dbcf02cSchristos 	while (!eloop.terminate &&
54036d97821Schristos 	       (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 ||
5418dbcf02cSchristos 		eloop.event_count > 0)) {
54236d97821Schristos 		struct eloop_timeout *timeout;
5438dbcf02cSchristos 		tv.sec = tv.usec = 0;
54436d97821Schristos 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
54536d97821Schristos 					list);
54636d97821Schristos 		if (timeout) {
54736d97821Schristos 			os_get_reltime(&now);
54836d97821Schristos 			if (os_reltime_before(&now, &timeout->time))
54936d97821Schristos 				os_reltime_sub(&timeout->time, &now, &tv);
5508dbcf02cSchristos 		}
5518dbcf02cSchristos 
5528dbcf02cSchristos 		count = 0;
5538dbcf02cSchristos 		for (i = 0; i < eloop.event_count; i++)
5548dbcf02cSchristos 			eloop.handles[count++] = eloop.events[i].event;
5558dbcf02cSchristos 
5568dbcf02cSchristos 		for (i = 0; i < eloop.reader_count; i++)
5578dbcf02cSchristos 			eloop.handles[count++] = eloop.readers[i].event;
5588dbcf02cSchristos 
5598dbcf02cSchristos 		if (eloop.term_event)
5608dbcf02cSchristos 			eloop.handles[count++] = eloop.term_event;
5618dbcf02cSchristos 
56236d97821Schristos 		if (timeout)
56336d97821Schristos 			timeout_val = tv.sec * 1000 + tv.usec / 1000;
5648dbcf02cSchristos 		else
56536d97821Schristos 			timeout_val = INFINITE;
5668dbcf02cSchristos 
5678dbcf02cSchristos 		if (count > MAXIMUM_WAIT_OBJECTS) {
5688dbcf02cSchristos 			printf("WaitForMultipleObjects: Too many events: "
5698dbcf02cSchristos 			       "%d > %d (ignoring extra events)\n",
5708dbcf02cSchristos 			       (int) count, MAXIMUM_WAIT_OBJECTS);
5718dbcf02cSchristos 			count = MAXIMUM_WAIT_OBJECTS;
5728dbcf02cSchristos 		}
5738dbcf02cSchristos #ifdef _WIN32_WCE
5748dbcf02cSchristos 		ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
57536d97821Schristos 					     timeout_val);
5768dbcf02cSchristos #else /* _WIN32_WCE */
5778dbcf02cSchristos 		ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
57836d97821Schristos 					       timeout_val, TRUE);
5798dbcf02cSchristos #endif /* _WIN32_WCE */
5808dbcf02cSchristos 		err = GetLastError();
5818dbcf02cSchristos 
5828dbcf02cSchristos 		eloop_process_pending_signals();
5838dbcf02cSchristos 
5848dbcf02cSchristos 		/* check if some registered timeouts have occurred */
58536d97821Schristos 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
58636d97821Schristos 					list);
58736d97821Schristos 		if (timeout) {
58836d97821Schristos 			os_get_reltime(&now);
58936d97821Schristos 			if (!os_reltime_before(&now, &timeout->time)) {
59036d97821Schristos 				void *eloop_data = timeout->eloop_data;
59136d97821Schristos 				void *user_data = timeout->user_data;
59236d97821Schristos 				eloop_timeout_handler handler =
59336d97821Schristos 					timeout->handler;
59436d97821Schristos 				eloop_remove_timeout(timeout);
59536d97821Schristos 				handler(eloop_data, user_data);
5968dbcf02cSchristos 			}
5978dbcf02cSchristos 
5988dbcf02cSchristos 		}
5998dbcf02cSchristos 
6008dbcf02cSchristos 		if (ret == WAIT_FAILED) {
6018dbcf02cSchristos 			printf("WaitForMultipleObjects(count=%d) failed: %d\n",
6028dbcf02cSchristos 			       (int) count, (int) err);
6038dbcf02cSchristos 			os_sleep(1, 0);
6048dbcf02cSchristos 			continue;
6058dbcf02cSchristos 		}
6068dbcf02cSchristos 
6078dbcf02cSchristos #ifndef _WIN32_WCE
6088dbcf02cSchristos 		if (ret == WAIT_IO_COMPLETION)
6098dbcf02cSchristos 			continue;
6108dbcf02cSchristos #endif /* _WIN32_WCE */
6118dbcf02cSchristos 
6128dbcf02cSchristos 		if (ret == WAIT_TIMEOUT)
6138dbcf02cSchristos 			continue;
6148dbcf02cSchristos 
6158dbcf02cSchristos 		while (ret >= WAIT_OBJECT_0 &&
6168dbcf02cSchristos 		       ret < WAIT_OBJECT_0 + eloop.event_count) {
6178dbcf02cSchristos 			eloop.events[ret].handler(
6188dbcf02cSchristos 				eloop.events[ret].eloop_data,
6198dbcf02cSchristos 				eloop.events[ret].user_data);
6208dbcf02cSchristos 			ret = WaitForMultipleObjects(eloop.event_count,
6218dbcf02cSchristos 						     eloop.handles, FALSE, 0);
6228dbcf02cSchristos 		}
6238dbcf02cSchristos 
6248dbcf02cSchristos 		eloop.reader_table_changed = 0;
6258dbcf02cSchristos 		for (i = 0; i < eloop.reader_count; i++) {
6268dbcf02cSchristos 			WSANETWORKEVENTS events;
6278dbcf02cSchristos 			if (WSAEnumNetworkEvents(eloop.readers[i].sock,
6288dbcf02cSchristos 						 eloop.readers[i].event,
6298dbcf02cSchristos 						 &events) == 0 &&
6308dbcf02cSchristos 			    (events.lNetworkEvents & FD_READ)) {
6318dbcf02cSchristos 				eloop.readers[i].handler(
6328dbcf02cSchristos 					eloop.readers[i].sock,
6338dbcf02cSchristos 					eloop.readers[i].eloop_data,
6348dbcf02cSchristos 					eloop.readers[i].user_data);
6358dbcf02cSchristos 				if (eloop.reader_table_changed)
6368dbcf02cSchristos 					break;
6378dbcf02cSchristos 			}
6388dbcf02cSchristos 		}
6398dbcf02cSchristos 	}
6408dbcf02cSchristos }
6418dbcf02cSchristos 
6428dbcf02cSchristos 
eloop_terminate(void)6438dbcf02cSchristos void eloop_terminate(void)
6448dbcf02cSchristos {
6458dbcf02cSchristos 	eloop.terminate = 1;
6468dbcf02cSchristos 	SetEvent(eloop.term_event);
6478dbcf02cSchristos }
6488dbcf02cSchristos 
6498dbcf02cSchristos 
eloop_destroy(void)6508dbcf02cSchristos void eloop_destroy(void)
6518dbcf02cSchristos {
6528dbcf02cSchristos 	struct eloop_timeout *timeout, *prev;
6538dbcf02cSchristos 
65436d97821Schristos 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
65536d97821Schristos 			      struct eloop_timeout, list) {
65636d97821Schristos 		eloop_remove_timeout(timeout);
6578dbcf02cSchristos 	}
6588dbcf02cSchristos 	os_free(eloop.readers);
6598dbcf02cSchristos 	os_free(eloop.signals);
6608dbcf02cSchristos 	if (eloop.term_event)
6618dbcf02cSchristos 		CloseHandle(eloop.term_event);
6628dbcf02cSchristos 	os_free(eloop.handles);
6638dbcf02cSchristos 	eloop.handles = NULL;
6648dbcf02cSchristos 	os_free(eloop.events);
6658dbcf02cSchristos 	eloop.events = NULL;
6668dbcf02cSchristos }
6678dbcf02cSchristos 
6688dbcf02cSchristos 
eloop_terminated(void)6698dbcf02cSchristos int eloop_terminated(void)
6708dbcf02cSchristos {
6718dbcf02cSchristos 	return eloop.terminate;
6728dbcf02cSchristos }
6738dbcf02cSchristos 
6748dbcf02cSchristos 
eloop_wait_for_read_sock(int sock)6758dbcf02cSchristos void eloop_wait_for_read_sock(int sock)
6768dbcf02cSchristos {
6778dbcf02cSchristos 	WSAEVENT event;
6788dbcf02cSchristos 
6798dbcf02cSchristos 	event = WSACreateEvent();
6808dbcf02cSchristos 	if (event == WSA_INVALID_EVENT) {
6818dbcf02cSchristos 		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
6828dbcf02cSchristos 		return;
6838dbcf02cSchristos 	}
6848dbcf02cSchristos 
6858dbcf02cSchristos 	if (WSAEventSelect(sock, event, FD_READ)) {
6868dbcf02cSchristos 		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
6878dbcf02cSchristos 		WSACloseEvent(event);
6888dbcf02cSchristos 		return ;
6898dbcf02cSchristos 	}
6908dbcf02cSchristos 
6918dbcf02cSchristos 	WaitForSingleObject(event, INFINITE);
6928dbcf02cSchristos 	WSAEventSelect(sock, event, 0);
6938dbcf02cSchristos 	WSACloseEvent(event);
6948dbcf02cSchristos }
695*928750b6Schristos 
696*928750b6Schristos 
eloop_sock_requeue(void)697*928750b6Schristos int eloop_sock_requeue(void)
698*928750b6Schristos {
699*928750b6Schristos 	return 0;
700*928750b6Schristos }
701