xref: /netbsd-src/external/bsd/wpa/dist/src/utils/eloop_win.c (revision bb6183629cf165db498d8e1f4e2de129f7efb21c)
18dbcf02cSchristos /*
28dbcf02cSchristos  * Event loop based on Windows events and WaitForMultipleObjects
33c260e60Schristos  * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
5e604d861Schristos  * This software may be distributed under the terms of the BSD license.
6e604d861Schristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos #include <winsock2.h>
118dbcf02cSchristos 
128dbcf02cSchristos #include "common.h"
133c260e60Schristos #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 {
333c260e60Schristos 	struct dl_list list;
343c260e60Schristos 	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 
553c260e60Schristos 	struct dl_list timeout;
568dbcf02cSchristos 
57*bb618362Schristos 	size_t 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 
758dbcf02cSchristos int eloop_init(void)
768dbcf02cSchristos {
778dbcf02cSchristos 	os_memset(&eloop, 0, sizeof(eloop));
783c260e60Schristos 	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 
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;
103e604d861Schristos 	n = os_realloc_array(eloop.handles, eloop.num_handles * 2,
104e604d861Schristos 			     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 
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 	}
133e604d861Schristos 	tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1,
134e604d861Schristos 			       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 
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 
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 
196e604d861Schristos 	tmp = os_realloc_array(eloop.events, eloop.event_count + 1,
197e604d861Schristos 			       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 
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 
2378dbcf02cSchristos int eloop_register_timeout(unsigned int secs, unsigned int usecs,
2388dbcf02cSchristos 			   eloop_timeout_handler handler,
2398dbcf02cSchristos 			   void *eloop_data, void *user_data)
2408dbcf02cSchristos {
2413c260e60Schristos 	struct eloop_timeout *timeout, *tmp;
242111b9fd8Schristos 	os_time_t now_sec;
2438dbcf02cSchristos 
2443c260e60Schristos 	timeout = os_zalloc(sizeof(*timeout));
2458dbcf02cSchristos 	if (timeout == NULL)
2468dbcf02cSchristos 		return -1;
2473c260e60Schristos 	if (os_get_reltime(&timeout->time) < 0) {
2483c260e60Schristos 		os_free(timeout);
2493c260e60Schristos 		return -1;
2503c260e60Schristos 	}
251111b9fd8Schristos 	now_sec = timeout->time.sec;
2528dbcf02cSchristos 	timeout->time.sec += secs;
253111b9fd8Schristos 	if (timeout->time.sec < now_sec) {
254111b9fd8Schristos 		/*
255111b9fd8Schristos 		 * Integer overflow - assume long enough timeout to be assumed
256111b9fd8Schristos 		 * to be infinite, i.e., the timeout would never happen.
257111b9fd8Schristos 		 */
258111b9fd8Schristos 		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
259111b9fd8Schristos 			   "ever happen - ignore it", secs);
260111b9fd8Schristos 		os_free(timeout);
261111b9fd8Schristos 		return 0;
262111b9fd8Schristos 	}
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 
2723c260e60Schristos 	/* Maintain timeouts in order of increasing time */
2733c260e60Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
2743c260e60Schristos 		if (os_reltime_before(&timeout->time, &tmp->time)) {
2753c260e60Schristos 			dl_list_add(tmp->list.prev, &timeout->list);
2763c260e60Schristos 			return 0;
2773c260e60Schristos 		}
2783c260e60Schristos 	}
2793c260e60Schristos 	dl_list_add_tail(&eloop.timeout, &timeout->list);
2803c260e60Schristos 
2818dbcf02cSchristos 	return 0;
2828dbcf02cSchristos }
2838dbcf02cSchristos 
2848dbcf02cSchristos 
2853c260e60Schristos static void eloop_remove_timeout(struct eloop_timeout *timeout)
2863c260e60Schristos {
2873c260e60Schristos 	dl_list_del(&timeout->list);
2883c260e60Schristos 	os_free(timeout);
2898dbcf02cSchristos }
2908dbcf02cSchristos 
2918dbcf02cSchristos 
2928dbcf02cSchristos int eloop_cancel_timeout(eloop_timeout_handler handler,
2938dbcf02cSchristos 			 void *eloop_data, void *user_data)
2948dbcf02cSchristos {
2953c260e60Schristos 	struct eloop_timeout *timeout, *prev;
2968dbcf02cSchristos 	int removed = 0;
2978dbcf02cSchristos 
2983c260e60Schristos 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
2993c260e60Schristos 			      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)) {
3053c260e60Schristos 			eloop_remove_timeout(timeout);
3068dbcf02cSchristos 			removed++;
3073c260e60Schristos 		}
3088dbcf02cSchristos 	}
3098dbcf02cSchristos 
3108dbcf02cSchristos 	return removed;
3118dbcf02cSchristos }
3128dbcf02cSchristos 
3138dbcf02cSchristos 
3143c260e60Schristos int eloop_cancel_timeout_one(eloop_timeout_handler handler,
3153c260e60Schristos 			     void *eloop_data, void *user_data,
3163c260e60Schristos 			     struct os_reltime *remaining)
3173c260e60Schristos {
3183c260e60Schristos 	struct eloop_timeout *timeout, *prev;
3193c260e60Schristos 	int removed = 0;
3203c260e60Schristos 	struct os_reltime now;
3213c260e60Schristos 
3223c260e60Schristos 	os_get_reltime(&now);
3233c260e60Schristos 	remaining->sec = remaining->usec = 0;
3243c260e60Schristos 
3253c260e60Schristos 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
3263c260e60Schristos 			      struct eloop_timeout, list) {
3273c260e60Schristos 		if (timeout->handler == handler &&
3283c260e60Schristos 		    (timeout->eloop_data == eloop_data) &&
3293c260e60Schristos 		    (timeout->user_data == user_data)) {
3303c260e60Schristos 			removed = 1;
3313c260e60Schristos 			if (os_reltime_before(&now, &timeout->time))
3323c260e60Schristos 				os_reltime_sub(&timeout->time, &now, remaining);
3333c260e60Schristos 			eloop_remove_timeout(timeout);
3343c260e60Schristos 			break;
3353c260e60Schristos 		}
3363c260e60Schristos 	}
3373c260e60Schristos 	return removed;
3383c260e60Schristos }
3393c260e60Schristos 
3403c260e60Schristos 
3418dbcf02cSchristos int eloop_is_timeout_registered(eloop_timeout_handler handler,
3428dbcf02cSchristos 				void *eloop_data, void *user_data)
3438dbcf02cSchristos {
3448dbcf02cSchristos 	struct eloop_timeout *tmp;
3458dbcf02cSchristos 
3463c260e60Schristos 	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 
3573c260e60Schristos int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
3583c260e60Schristos 			  eloop_timeout_handler handler, void *eloop_data,
3593c260e60Schristos 			  void *user_data)
3603c260e60Schristos {
3613c260e60Schristos 	struct os_reltime now, requested, remaining;
3623c260e60Schristos 	struct eloop_timeout *tmp;
3633c260e60Schristos 
3643c260e60Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
3653c260e60Schristos 		if (tmp->handler == handler &&
3663c260e60Schristos 		    tmp->eloop_data == eloop_data &&
3673c260e60Schristos 		    tmp->user_data == user_data) {
3683c260e60Schristos 			requested.sec = req_secs;
3693c260e60Schristos 			requested.usec = req_usecs;
3703c260e60Schristos 			os_get_reltime(&now);
3713c260e60Schristos 			os_reltime_sub(&tmp->time, &now, &remaining);
3723c260e60Schristos 			if (os_reltime_before(&requested, &remaining)) {
3733c260e60Schristos 				eloop_cancel_timeout(handler, eloop_data,
3743c260e60Schristos 						     user_data);
3753c260e60Schristos 				eloop_register_timeout(requested.sec,
3763c260e60Schristos 						       requested.usec,
3773c260e60Schristos 						       handler, eloop_data,
3783c260e60Schristos 						       user_data);
3793c260e60Schristos 				return 1;
3803c260e60Schristos 			}
3813c260e60Schristos 			return 0;
3823c260e60Schristos 		}
3833c260e60Schristos 	}
3843c260e60Schristos 
3853c260e60Schristos 	return -1;
3863c260e60Schristos }
3873c260e60Schristos 
3883c260e60Schristos 
3893c260e60Schristos int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
3903c260e60Schristos 			    eloop_timeout_handler handler, void *eloop_data,
3913c260e60Schristos 			    void *user_data)
3923c260e60Schristos {
3933c260e60Schristos 	struct os_reltime now, requested, remaining;
3943c260e60Schristos 	struct eloop_timeout *tmp;
3953c260e60Schristos 
3963c260e60Schristos 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
3973c260e60Schristos 		if (tmp->handler == handler &&
3983c260e60Schristos 		    tmp->eloop_data == eloop_data &&
3993c260e60Schristos 		    tmp->user_data == user_data) {
4003c260e60Schristos 			requested.sec = req_secs;
4013c260e60Schristos 			requested.usec = req_usecs;
4023c260e60Schristos 			os_get_reltime(&now);
4033c260e60Schristos 			os_reltime_sub(&tmp->time, &now, &remaining);
4043c260e60Schristos 			if (os_reltime_before(&remaining, &requested)) {
4053c260e60Schristos 				eloop_cancel_timeout(handler, eloop_data,
4063c260e60Schristos 						     user_data);
4073c260e60Schristos 				eloop_register_timeout(requested.sec,
4083c260e60Schristos 						       requested.usec,
4093c260e60Schristos 						       handler, eloop_data,
4103c260e60Schristos 						       user_data);
4113c260e60Schristos 				return 1;
4123c260e60Schristos 			}
4133c260e60Schristos 			return 0;
4143c260e60Schristos 		}
4153c260e60Schristos 	}
4163c260e60Schristos 
4173c260e60Schristos 	return -1;
4183c260e60Schristos }
4193c260e60Schristos 
4203c260e60Schristos 
4218dbcf02cSchristos /* TODO: replace with suitable signal handler */
4228dbcf02cSchristos #if 0
4238dbcf02cSchristos static void eloop_handle_signal(int sig)
4248dbcf02cSchristos {
425*bb618362Schristos 	size_t 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 
4388dbcf02cSchristos static void eloop_process_pending_signals(void)
4398dbcf02cSchristos {
440*bb618362Schristos 	size_t 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 
4668dbcf02cSchristos int eloop_register_signal(int sig, eloop_signal_handler handler,
4678dbcf02cSchristos 			  void *user_data)
4688dbcf02cSchristos {
4698dbcf02cSchristos 	struct eloop_signal *tmp;
4708dbcf02cSchristos 
471e604d861Schristos 	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
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 
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 
5258dbcf02cSchristos int eloop_register_signal_reconfig(eloop_signal_handler handler,
5268dbcf02cSchristos 				   void *user_data)
5278dbcf02cSchristos {
5288dbcf02cSchristos 	/* TODO */
5298dbcf02cSchristos 	return 0;
5308dbcf02cSchristos }
5318dbcf02cSchristos 
5328dbcf02cSchristos 
5338dbcf02cSchristos void eloop_run(void)
5348dbcf02cSchristos {
5353c260e60Schristos 	struct os_reltime tv, now;
5363c260e60Schristos 	DWORD count, ret, timeout_val, err;
5378dbcf02cSchristos 	size_t i;
5388dbcf02cSchristos 
5398dbcf02cSchristos 	while (!eloop.terminate &&
5403c260e60Schristos 	       (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 ||
5418dbcf02cSchristos 		eloop.event_count > 0)) {
5423c260e60Schristos 		struct eloop_timeout *timeout;
5438dbcf02cSchristos 		tv.sec = tv.usec = 0;
5443c260e60Schristos 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
5453c260e60Schristos 					list);
5463c260e60Schristos 		if (timeout) {
5473c260e60Schristos 			os_get_reltime(&now);
5483c260e60Schristos 			if (os_reltime_before(&now, &timeout->time))
5493c260e60Schristos 				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 
5623c260e60Schristos 		if (timeout)
5633c260e60Schristos 			timeout_val = tv.sec * 1000 + tv.usec / 1000;
5648dbcf02cSchristos 		else
5653c260e60Schristos 			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,
5753c260e60Schristos 					     timeout_val);
5768dbcf02cSchristos #else /* _WIN32_WCE */
5778dbcf02cSchristos 		ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
5783c260e60Schristos 					       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 */
5853c260e60Schristos 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
5863c260e60Schristos 					list);
5873c260e60Schristos 		if (timeout) {
5883c260e60Schristos 			os_get_reltime(&now);
5893c260e60Schristos 			if (!os_reltime_before(&now, &timeout->time)) {
5903c260e60Schristos 				void *eloop_data = timeout->eloop_data;
5913c260e60Schristos 				void *user_data = timeout->user_data;
5923c260e60Schristos 				eloop_timeout_handler handler =
5933c260e60Schristos 					timeout->handler;
5943c260e60Schristos 				eloop_remove_timeout(timeout);
5953c260e60Schristos 				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 
6438dbcf02cSchristos void eloop_terminate(void)
6448dbcf02cSchristos {
6458dbcf02cSchristos 	eloop.terminate = 1;
6468dbcf02cSchristos 	SetEvent(eloop.term_event);
6478dbcf02cSchristos }
6488dbcf02cSchristos 
6498dbcf02cSchristos 
6508dbcf02cSchristos void eloop_destroy(void)
6518dbcf02cSchristos {
6528dbcf02cSchristos 	struct eloop_timeout *timeout, *prev;
6538dbcf02cSchristos 
6543c260e60Schristos 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
6553c260e60Schristos 			      struct eloop_timeout, list) {
6563c260e60Schristos 		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 
6698dbcf02cSchristos int eloop_terminated(void)
6708dbcf02cSchristos {
6718dbcf02cSchristos 	return eloop.terminate;
6728dbcf02cSchristos }
6738dbcf02cSchristos 
6748dbcf02cSchristos 
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 }
69536ebd06eSchristos 
69636ebd06eSchristos 
69736ebd06eSchristos int eloop_sock_requeue(void)
69836ebd06eSchristos {
69936ebd06eSchristos 	return 0;
70036ebd06eSchristos }
701