1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * Event loop based on Windows events and WaitForMultipleObjects
3e5b75505Sopenharmony_ci * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci#include <winsock2.h>
11e5b75505Sopenharmony_ci
12e5b75505Sopenharmony_ci#include "common.h"
13e5b75505Sopenharmony_ci#include "list.h"
14e5b75505Sopenharmony_ci#include "eloop.h"
15e5b75505Sopenharmony_ci
16e5b75505Sopenharmony_ci
17e5b75505Sopenharmony_cistruct eloop_sock {
18e5b75505Sopenharmony_ci	int sock;
19e5b75505Sopenharmony_ci	void *eloop_data;
20e5b75505Sopenharmony_ci	void *user_data;
21e5b75505Sopenharmony_ci	eloop_sock_handler handler;
22e5b75505Sopenharmony_ci	WSAEVENT event;
23e5b75505Sopenharmony_ci};
24e5b75505Sopenharmony_ci
25e5b75505Sopenharmony_cistruct eloop_event {
26e5b75505Sopenharmony_ci	void *eloop_data;
27e5b75505Sopenharmony_ci	void *user_data;
28e5b75505Sopenharmony_ci	eloop_event_handler handler;
29e5b75505Sopenharmony_ci	HANDLE event;
30e5b75505Sopenharmony_ci};
31e5b75505Sopenharmony_ci
32e5b75505Sopenharmony_cistruct eloop_timeout {
33e5b75505Sopenharmony_ci	struct dl_list list;
34e5b75505Sopenharmony_ci	struct os_reltime time;
35e5b75505Sopenharmony_ci	void *eloop_data;
36e5b75505Sopenharmony_ci	void *user_data;
37e5b75505Sopenharmony_ci	eloop_timeout_handler handler;
38e5b75505Sopenharmony_ci};
39e5b75505Sopenharmony_ci
40e5b75505Sopenharmony_cistruct eloop_signal {
41e5b75505Sopenharmony_ci	int sig;
42e5b75505Sopenharmony_ci	void *user_data;
43e5b75505Sopenharmony_ci	eloop_signal_handler handler;
44e5b75505Sopenharmony_ci	int signaled;
45e5b75505Sopenharmony_ci};
46e5b75505Sopenharmony_ci
47e5b75505Sopenharmony_cistruct eloop_data {
48e5b75505Sopenharmony_ci	int max_sock;
49e5b75505Sopenharmony_ci	size_t reader_count;
50e5b75505Sopenharmony_ci	struct eloop_sock *readers;
51e5b75505Sopenharmony_ci
52e5b75505Sopenharmony_ci	size_t event_count;
53e5b75505Sopenharmony_ci	struct eloop_event *events;
54e5b75505Sopenharmony_ci
55e5b75505Sopenharmony_ci	struct dl_list timeout;
56e5b75505Sopenharmony_ci
57e5b75505Sopenharmony_ci	int signal_count;
58e5b75505Sopenharmony_ci	struct eloop_signal *signals;
59e5b75505Sopenharmony_ci	int signaled;
60e5b75505Sopenharmony_ci	int pending_terminate;
61e5b75505Sopenharmony_ci
62e5b75505Sopenharmony_ci	int terminate;
63e5b75505Sopenharmony_ci	int reader_table_changed;
64e5b75505Sopenharmony_ci
65e5b75505Sopenharmony_ci	struct eloop_signal term_signal;
66e5b75505Sopenharmony_ci	HANDLE term_event;
67e5b75505Sopenharmony_ci
68e5b75505Sopenharmony_ci	HANDLE *handles;
69e5b75505Sopenharmony_ci	size_t num_handles;
70e5b75505Sopenharmony_ci};
71e5b75505Sopenharmony_ci
72e5b75505Sopenharmony_cistatic struct eloop_data eloop;
73e5b75505Sopenharmony_ci
74e5b75505Sopenharmony_ci
75e5b75505Sopenharmony_ciint eloop_init(void)
76e5b75505Sopenharmony_ci{
77e5b75505Sopenharmony_ci	os_memset(&eloop, 0, sizeof(eloop));
78e5b75505Sopenharmony_ci	dl_list_init(&eloop.timeout);
79e5b75505Sopenharmony_ci	eloop.num_handles = 1;
80e5b75505Sopenharmony_ci	eloop.handles = os_malloc(eloop.num_handles *
81e5b75505Sopenharmony_ci				  sizeof(eloop.handles[0]));
82e5b75505Sopenharmony_ci	if (eloop.handles == NULL)
83e5b75505Sopenharmony_ci		return -1;
84e5b75505Sopenharmony_ci
85e5b75505Sopenharmony_ci	eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
86e5b75505Sopenharmony_ci	if (eloop.term_event == NULL) {
87e5b75505Sopenharmony_ci		printf("CreateEvent() failed: %d\n",
88e5b75505Sopenharmony_ci		       (int) GetLastError());
89e5b75505Sopenharmony_ci		os_free(eloop.handles);
90e5b75505Sopenharmony_ci		return -1;
91e5b75505Sopenharmony_ci	}
92e5b75505Sopenharmony_ci
93e5b75505Sopenharmony_ci	return 0;
94e5b75505Sopenharmony_ci}
95e5b75505Sopenharmony_ci
96e5b75505Sopenharmony_ci
97e5b75505Sopenharmony_cistatic int eloop_prepare_handles(void)
98e5b75505Sopenharmony_ci{
99e5b75505Sopenharmony_ci	HANDLE *n;
100e5b75505Sopenharmony_ci
101e5b75505Sopenharmony_ci	if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
102e5b75505Sopenharmony_ci		return 0;
103e5b75505Sopenharmony_ci	n = os_realloc_array(eloop.handles, eloop.num_handles * 2,
104e5b75505Sopenharmony_ci			     sizeof(eloop.handles[0]));
105e5b75505Sopenharmony_ci	if (n == NULL)
106e5b75505Sopenharmony_ci		return -1;
107e5b75505Sopenharmony_ci	eloop.handles = n;
108e5b75505Sopenharmony_ci	eloop.num_handles *= 2;
109e5b75505Sopenharmony_ci	return 0;
110e5b75505Sopenharmony_ci}
111e5b75505Sopenharmony_ci
112e5b75505Sopenharmony_ci
113e5b75505Sopenharmony_ciint eloop_register_read_sock(int sock, eloop_sock_handler handler,
114e5b75505Sopenharmony_ci			     void *eloop_data, void *user_data)
115e5b75505Sopenharmony_ci{
116e5b75505Sopenharmony_ci	WSAEVENT event;
117e5b75505Sopenharmony_ci	struct eloop_sock *tmp;
118e5b75505Sopenharmony_ci
119e5b75505Sopenharmony_ci	if (eloop_prepare_handles())
120e5b75505Sopenharmony_ci		return -1;
121e5b75505Sopenharmony_ci
122e5b75505Sopenharmony_ci	event = WSACreateEvent();
123e5b75505Sopenharmony_ci	if (event == WSA_INVALID_EVENT) {
124e5b75505Sopenharmony_ci		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
125e5b75505Sopenharmony_ci		return -1;
126e5b75505Sopenharmony_ci	}
127e5b75505Sopenharmony_ci
128e5b75505Sopenharmony_ci	if (WSAEventSelect(sock, event, FD_READ)) {
129e5b75505Sopenharmony_ci		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
130e5b75505Sopenharmony_ci		WSACloseEvent(event);
131e5b75505Sopenharmony_ci		return -1;
132e5b75505Sopenharmony_ci	}
133e5b75505Sopenharmony_ci	tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1,
134e5b75505Sopenharmony_ci			       sizeof(struct eloop_sock));
135e5b75505Sopenharmony_ci	if (tmp == NULL) {
136e5b75505Sopenharmony_ci		WSAEventSelect(sock, event, 0);
137e5b75505Sopenharmony_ci		WSACloseEvent(event);
138e5b75505Sopenharmony_ci		return -1;
139e5b75505Sopenharmony_ci	}
140e5b75505Sopenharmony_ci
141e5b75505Sopenharmony_ci	tmp[eloop.reader_count].sock = sock;
142e5b75505Sopenharmony_ci	tmp[eloop.reader_count].eloop_data = eloop_data;
143e5b75505Sopenharmony_ci	tmp[eloop.reader_count].user_data = user_data;
144e5b75505Sopenharmony_ci	tmp[eloop.reader_count].handler = handler;
145e5b75505Sopenharmony_ci	tmp[eloop.reader_count].event = event;
146e5b75505Sopenharmony_ci	eloop.reader_count++;
147e5b75505Sopenharmony_ci	eloop.readers = tmp;
148e5b75505Sopenharmony_ci	if (sock > eloop.max_sock)
149e5b75505Sopenharmony_ci		eloop.max_sock = sock;
150e5b75505Sopenharmony_ci	eloop.reader_table_changed = 1;
151e5b75505Sopenharmony_ci
152e5b75505Sopenharmony_ci	return 0;
153e5b75505Sopenharmony_ci}
154e5b75505Sopenharmony_ci
155e5b75505Sopenharmony_ci
156e5b75505Sopenharmony_civoid eloop_unregister_read_sock(int sock)
157e5b75505Sopenharmony_ci{
158e5b75505Sopenharmony_ci	size_t i;
159e5b75505Sopenharmony_ci
160e5b75505Sopenharmony_ci	if (eloop.readers == NULL || eloop.reader_count == 0)
161e5b75505Sopenharmony_ci		return;
162e5b75505Sopenharmony_ci
163e5b75505Sopenharmony_ci	for (i = 0; i < eloop.reader_count; i++) {
164e5b75505Sopenharmony_ci		if (eloop.readers[i].sock == sock)
165e5b75505Sopenharmony_ci			break;
166e5b75505Sopenharmony_ci	}
167e5b75505Sopenharmony_ci	if (i == eloop.reader_count)
168e5b75505Sopenharmony_ci		return;
169e5b75505Sopenharmony_ci
170e5b75505Sopenharmony_ci	WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
171e5b75505Sopenharmony_ci	WSACloseEvent(eloop.readers[i].event);
172e5b75505Sopenharmony_ci
173e5b75505Sopenharmony_ci	if (i != eloop.reader_count - 1) {
174e5b75505Sopenharmony_ci		os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
175e5b75505Sopenharmony_ci			   (eloop.reader_count - i - 1) *
176e5b75505Sopenharmony_ci			   sizeof(struct eloop_sock));
177e5b75505Sopenharmony_ci	}
178e5b75505Sopenharmony_ci	eloop.reader_count--;
179e5b75505Sopenharmony_ci	eloop.reader_table_changed = 1;
180e5b75505Sopenharmony_ci}
181e5b75505Sopenharmony_ci
182e5b75505Sopenharmony_ci
183e5b75505Sopenharmony_ciint eloop_register_event(void *event, size_t event_size,
184e5b75505Sopenharmony_ci			 eloop_event_handler handler,
185e5b75505Sopenharmony_ci			 void *eloop_data, void *user_data)
186e5b75505Sopenharmony_ci{
187e5b75505Sopenharmony_ci	struct eloop_event *tmp;
188e5b75505Sopenharmony_ci	HANDLE h = event;
189e5b75505Sopenharmony_ci
190e5b75505Sopenharmony_ci	if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
191e5b75505Sopenharmony_ci		return -1;
192e5b75505Sopenharmony_ci
193e5b75505Sopenharmony_ci	if (eloop_prepare_handles())
194e5b75505Sopenharmony_ci		return -1;
195e5b75505Sopenharmony_ci
196e5b75505Sopenharmony_ci	tmp = os_realloc_array(eloop.events, eloop.event_count + 1,
197e5b75505Sopenharmony_ci			       sizeof(struct eloop_event));
198e5b75505Sopenharmony_ci	if (tmp == NULL)
199e5b75505Sopenharmony_ci		return -1;
200e5b75505Sopenharmony_ci
201e5b75505Sopenharmony_ci	tmp[eloop.event_count].eloop_data = eloop_data;
202e5b75505Sopenharmony_ci	tmp[eloop.event_count].user_data = user_data;
203e5b75505Sopenharmony_ci	tmp[eloop.event_count].handler = handler;
204e5b75505Sopenharmony_ci	tmp[eloop.event_count].event = h;
205e5b75505Sopenharmony_ci	eloop.event_count++;
206e5b75505Sopenharmony_ci	eloop.events = tmp;
207e5b75505Sopenharmony_ci
208e5b75505Sopenharmony_ci	return 0;
209e5b75505Sopenharmony_ci}
210e5b75505Sopenharmony_ci
211e5b75505Sopenharmony_ci
212e5b75505Sopenharmony_civoid eloop_unregister_event(void *event, size_t event_size)
213e5b75505Sopenharmony_ci{
214e5b75505Sopenharmony_ci	size_t i;
215e5b75505Sopenharmony_ci	HANDLE h = event;
216e5b75505Sopenharmony_ci
217e5b75505Sopenharmony_ci	if (eloop.events == NULL || eloop.event_count == 0 ||
218e5b75505Sopenharmony_ci	    event_size != sizeof(HANDLE))
219e5b75505Sopenharmony_ci		return;
220e5b75505Sopenharmony_ci
221e5b75505Sopenharmony_ci	for (i = 0; i < eloop.event_count; i++) {
222e5b75505Sopenharmony_ci		if (eloop.events[i].event == h)
223e5b75505Sopenharmony_ci			break;
224e5b75505Sopenharmony_ci	}
225e5b75505Sopenharmony_ci	if (i == eloop.event_count)
226e5b75505Sopenharmony_ci		return;
227e5b75505Sopenharmony_ci
228e5b75505Sopenharmony_ci	if (i != eloop.event_count - 1) {
229e5b75505Sopenharmony_ci		os_memmove(&eloop.events[i], &eloop.events[i + 1],
230e5b75505Sopenharmony_ci			   (eloop.event_count - i - 1) *
231e5b75505Sopenharmony_ci			   sizeof(struct eloop_event));
232e5b75505Sopenharmony_ci	}
233e5b75505Sopenharmony_ci	eloop.event_count--;
234e5b75505Sopenharmony_ci}
235e5b75505Sopenharmony_ci
236e5b75505Sopenharmony_ci
237e5b75505Sopenharmony_ciint eloop_register_timeout(unsigned int secs, unsigned int usecs,
238e5b75505Sopenharmony_ci			   eloop_timeout_handler handler,
239e5b75505Sopenharmony_ci			   void *eloop_data, void *user_data)
240e5b75505Sopenharmony_ci{
241e5b75505Sopenharmony_ci	struct eloop_timeout *timeout, *tmp;
242e5b75505Sopenharmony_ci	os_time_t now_sec;
243e5b75505Sopenharmony_ci
244e5b75505Sopenharmony_ci	timeout = os_zalloc(sizeof(*timeout));
245e5b75505Sopenharmony_ci	if (timeout == NULL)
246e5b75505Sopenharmony_ci		return -1;
247e5b75505Sopenharmony_ci	if (os_get_reltime(&timeout->time) < 0) {
248e5b75505Sopenharmony_ci		os_free(timeout);
249e5b75505Sopenharmony_ci		return -1;
250e5b75505Sopenharmony_ci	}
251e5b75505Sopenharmony_ci	now_sec = timeout->time.sec;
252e5b75505Sopenharmony_ci	timeout->time.sec += secs;
253e5b75505Sopenharmony_ci	if (timeout->time.sec < now_sec) {
254e5b75505Sopenharmony_ci		/*
255e5b75505Sopenharmony_ci		 * Integer overflow - assume long enough timeout to be assumed
256e5b75505Sopenharmony_ci		 * to be infinite, i.e., the timeout would never happen.
257e5b75505Sopenharmony_ci		 */
258e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
259e5b75505Sopenharmony_ci			   "ever happen - ignore it", secs);
260e5b75505Sopenharmony_ci		os_free(timeout);
261e5b75505Sopenharmony_ci		return 0;
262e5b75505Sopenharmony_ci	}
263e5b75505Sopenharmony_ci	timeout->time.usec += usecs;
264e5b75505Sopenharmony_ci	while (timeout->time.usec >= 1000000) {
265e5b75505Sopenharmony_ci		timeout->time.sec++;
266e5b75505Sopenharmony_ci		timeout->time.usec -= 1000000;
267e5b75505Sopenharmony_ci	}
268e5b75505Sopenharmony_ci	timeout->eloop_data = eloop_data;
269e5b75505Sopenharmony_ci	timeout->user_data = user_data;
270e5b75505Sopenharmony_ci	timeout->handler = handler;
271e5b75505Sopenharmony_ci
272e5b75505Sopenharmony_ci	/* Maintain timeouts in order of increasing time */
273e5b75505Sopenharmony_ci	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
274e5b75505Sopenharmony_ci		if (os_reltime_before(&timeout->time, &tmp->time)) {
275e5b75505Sopenharmony_ci			dl_list_add(tmp->list.prev, &timeout->list);
276e5b75505Sopenharmony_ci			return 0;
277e5b75505Sopenharmony_ci		}
278e5b75505Sopenharmony_ci	}
279e5b75505Sopenharmony_ci	dl_list_add_tail(&eloop.timeout, &timeout->list);
280e5b75505Sopenharmony_ci
281e5b75505Sopenharmony_ci	return 0;
282e5b75505Sopenharmony_ci}
283e5b75505Sopenharmony_ci
284e5b75505Sopenharmony_ci
285e5b75505Sopenharmony_cistatic void eloop_remove_timeout(struct eloop_timeout *timeout)
286e5b75505Sopenharmony_ci{
287e5b75505Sopenharmony_ci	dl_list_del(&timeout->list);
288e5b75505Sopenharmony_ci	os_free(timeout);
289e5b75505Sopenharmony_ci}
290e5b75505Sopenharmony_ci
291e5b75505Sopenharmony_ci
292e5b75505Sopenharmony_ciint eloop_cancel_timeout(eloop_timeout_handler handler,
293e5b75505Sopenharmony_ci			 void *eloop_data, void *user_data)
294e5b75505Sopenharmony_ci{
295e5b75505Sopenharmony_ci	struct eloop_timeout *timeout, *prev;
296e5b75505Sopenharmony_ci	int removed = 0;
297e5b75505Sopenharmony_ci
298e5b75505Sopenharmony_ci	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
299e5b75505Sopenharmony_ci			      struct eloop_timeout, list) {
300e5b75505Sopenharmony_ci		if (timeout->handler == handler &&
301e5b75505Sopenharmony_ci		    (timeout->eloop_data == eloop_data ||
302e5b75505Sopenharmony_ci		     eloop_data == ELOOP_ALL_CTX) &&
303e5b75505Sopenharmony_ci		    (timeout->user_data == user_data ||
304e5b75505Sopenharmony_ci		     user_data == ELOOP_ALL_CTX)) {
305e5b75505Sopenharmony_ci			eloop_remove_timeout(timeout);
306e5b75505Sopenharmony_ci			removed++;
307e5b75505Sopenharmony_ci		}
308e5b75505Sopenharmony_ci	}
309e5b75505Sopenharmony_ci
310e5b75505Sopenharmony_ci	return removed;
311e5b75505Sopenharmony_ci}
312e5b75505Sopenharmony_ci
313e5b75505Sopenharmony_ci
314e5b75505Sopenharmony_ciint eloop_cancel_timeout_one(eloop_timeout_handler handler,
315e5b75505Sopenharmony_ci			     void *eloop_data, void *user_data,
316e5b75505Sopenharmony_ci			     struct os_reltime *remaining)
317e5b75505Sopenharmony_ci{
318e5b75505Sopenharmony_ci	struct eloop_timeout *timeout, *prev;
319e5b75505Sopenharmony_ci	int removed = 0;
320e5b75505Sopenharmony_ci	struct os_reltime now;
321e5b75505Sopenharmony_ci
322e5b75505Sopenharmony_ci	os_get_reltime(&now);
323e5b75505Sopenharmony_ci	remaining->sec = remaining->usec = 0;
324e5b75505Sopenharmony_ci
325e5b75505Sopenharmony_ci	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
326e5b75505Sopenharmony_ci			      struct eloop_timeout, list) {
327e5b75505Sopenharmony_ci		if (timeout->handler == handler &&
328e5b75505Sopenharmony_ci		    (timeout->eloop_data == eloop_data) &&
329e5b75505Sopenharmony_ci		    (timeout->user_data == user_data)) {
330e5b75505Sopenharmony_ci			removed = 1;
331e5b75505Sopenharmony_ci			if (os_reltime_before(&now, &timeout->time))
332e5b75505Sopenharmony_ci				os_reltime_sub(&timeout->time, &now, remaining);
333e5b75505Sopenharmony_ci			eloop_remove_timeout(timeout);
334e5b75505Sopenharmony_ci			break;
335e5b75505Sopenharmony_ci		}
336e5b75505Sopenharmony_ci	}
337e5b75505Sopenharmony_ci	return removed;
338e5b75505Sopenharmony_ci}
339e5b75505Sopenharmony_ci
340e5b75505Sopenharmony_ci
341e5b75505Sopenharmony_ciint eloop_is_timeout_registered(eloop_timeout_handler handler,
342e5b75505Sopenharmony_ci				void *eloop_data, void *user_data)
343e5b75505Sopenharmony_ci{
344e5b75505Sopenharmony_ci	struct eloop_timeout *tmp;
345e5b75505Sopenharmony_ci
346e5b75505Sopenharmony_ci	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
347e5b75505Sopenharmony_ci		if (tmp->handler == handler &&
348e5b75505Sopenharmony_ci		    tmp->eloop_data == eloop_data &&
349e5b75505Sopenharmony_ci		    tmp->user_data == user_data)
350e5b75505Sopenharmony_ci			return 1;
351e5b75505Sopenharmony_ci	}
352e5b75505Sopenharmony_ci
353e5b75505Sopenharmony_ci	return 0;
354e5b75505Sopenharmony_ci}
355e5b75505Sopenharmony_ci
356e5b75505Sopenharmony_ci
357e5b75505Sopenharmony_ciint eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
358e5b75505Sopenharmony_ci			  eloop_timeout_handler handler, void *eloop_data,
359e5b75505Sopenharmony_ci			  void *user_data)
360e5b75505Sopenharmony_ci{
361e5b75505Sopenharmony_ci	struct os_reltime now, requested, remaining;
362e5b75505Sopenharmony_ci	struct eloop_timeout *tmp;
363e5b75505Sopenharmony_ci
364e5b75505Sopenharmony_ci	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
365e5b75505Sopenharmony_ci		if (tmp->handler == handler &&
366e5b75505Sopenharmony_ci		    tmp->eloop_data == eloop_data &&
367e5b75505Sopenharmony_ci		    tmp->user_data == user_data) {
368e5b75505Sopenharmony_ci			requested.sec = req_secs;
369e5b75505Sopenharmony_ci			requested.usec = req_usecs;
370e5b75505Sopenharmony_ci			os_get_reltime(&now);
371e5b75505Sopenharmony_ci			os_reltime_sub(&tmp->time, &now, &remaining);
372e5b75505Sopenharmony_ci			if (os_reltime_before(&requested, &remaining)) {
373e5b75505Sopenharmony_ci				eloop_cancel_timeout(handler, eloop_data,
374e5b75505Sopenharmony_ci						     user_data);
375e5b75505Sopenharmony_ci				eloop_register_timeout(requested.sec,
376e5b75505Sopenharmony_ci						       requested.usec,
377e5b75505Sopenharmony_ci						       handler, eloop_data,
378e5b75505Sopenharmony_ci						       user_data);
379e5b75505Sopenharmony_ci				return 1;
380e5b75505Sopenharmony_ci			}
381e5b75505Sopenharmony_ci			return 0;
382e5b75505Sopenharmony_ci		}
383e5b75505Sopenharmony_ci	}
384e5b75505Sopenharmony_ci
385e5b75505Sopenharmony_ci	return -1;
386e5b75505Sopenharmony_ci}
387e5b75505Sopenharmony_ci
388e5b75505Sopenharmony_ci
389e5b75505Sopenharmony_ciint eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
390e5b75505Sopenharmony_ci			    eloop_timeout_handler handler, void *eloop_data,
391e5b75505Sopenharmony_ci			    void *user_data)
392e5b75505Sopenharmony_ci{
393e5b75505Sopenharmony_ci	struct os_reltime now, requested, remaining;
394e5b75505Sopenharmony_ci	struct eloop_timeout *tmp;
395e5b75505Sopenharmony_ci
396e5b75505Sopenharmony_ci	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
397e5b75505Sopenharmony_ci		if (tmp->handler == handler &&
398e5b75505Sopenharmony_ci		    tmp->eloop_data == eloop_data &&
399e5b75505Sopenharmony_ci		    tmp->user_data == user_data) {
400e5b75505Sopenharmony_ci			requested.sec = req_secs;
401e5b75505Sopenharmony_ci			requested.usec = req_usecs;
402e5b75505Sopenharmony_ci			os_get_reltime(&now);
403e5b75505Sopenharmony_ci			os_reltime_sub(&tmp->time, &now, &remaining);
404e5b75505Sopenharmony_ci			if (os_reltime_before(&remaining, &requested)) {
405e5b75505Sopenharmony_ci				eloop_cancel_timeout(handler, eloop_data,
406e5b75505Sopenharmony_ci						     user_data);
407e5b75505Sopenharmony_ci				eloop_register_timeout(requested.sec,
408e5b75505Sopenharmony_ci						       requested.usec,
409e5b75505Sopenharmony_ci						       handler, eloop_data,
410e5b75505Sopenharmony_ci						       user_data);
411e5b75505Sopenharmony_ci				return 1;
412e5b75505Sopenharmony_ci			}
413e5b75505Sopenharmony_ci			return 0;
414e5b75505Sopenharmony_ci		}
415e5b75505Sopenharmony_ci	}
416e5b75505Sopenharmony_ci
417e5b75505Sopenharmony_ci	return -1;
418e5b75505Sopenharmony_ci}
419e5b75505Sopenharmony_ci
420e5b75505Sopenharmony_ci
421e5b75505Sopenharmony_ci/* TODO: replace with suitable signal handler */
422e5b75505Sopenharmony_ci#if 0
423e5b75505Sopenharmony_cistatic void eloop_handle_signal(int sig)
424e5b75505Sopenharmony_ci{
425e5b75505Sopenharmony_ci	int i;
426e5b75505Sopenharmony_ci
427e5b75505Sopenharmony_ci	eloop.signaled++;
428e5b75505Sopenharmony_ci	for (i = 0; i < eloop.signal_count; i++) {
429e5b75505Sopenharmony_ci		if (eloop.signals[i].sig == sig) {
430e5b75505Sopenharmony_ci			eloop.signals[i].signaled++;
431e5b75505Sopenharmony_ci			break;
432e5b75505Sopenharmony_ci		}
433e5b75505Sopenharmony_ci	}
434e5b75505Sopenharmony_ci}
435e5b75505Sopenharmony_ci#endif
436e5b75505Sopenharmony_ci
437e5b75505Sopenharmony_ci
438e5b75505Sopenharmony_cistatic void eloop_process_pending_signals(void)
439e5b75505Sopenharmony_ci{
440e5b75505Sopenharmony_ci	int i;
441e5b75505Sopenharmony_ci
442e5b75505Sopenharmony_ci	if (eloop.signaled == 0)
443e5b75505Sopenharmony_ci		return;
444e5b75505Sopenharmony_ci	eloop.signaled = 0;
445e5b75505Sopenharmony_ci
446e5b75505Sopenharmony_ci	if (eloop.pending_terminate) {
447e5b75505Sopenharmony_ci		eloop.pending_terminate = 0;
448e5b75505Sopenharmony_ci	}
449e5b75505Sopenharmony_ci
450e5b75505Sopenharmony_ci	for (i = 0; i < eloop.signal_count; i++) {
451e5b75505Sopenharmony_ci		if (eloop.signals[i].signaled) {
452e5b75505Sopenharmony_ci			eloop.signals[i].signaled = 0;
453e5b75505Sopenharmony_ci			eloop.signals[i].handler(eloop.signals[i].sig,
454e5b75505Sopenharmony_ci						 eloop.signals[i].user_data);
455e5b75505Sopenharmony_ci		}
456e5b75505Sopenharmony_ci	}
457e5b75505Sopenharmony_ci
458e5b75505Sopenharmony_ci	if (eloop.term_signal.signaled) {
459e5b75505Sopenharmony_ci		eloop.term_signal.signaled = 0;
460e5b75505Sopenharmony_ci		eloop.term_signal.handler(eloop.term_signal.sig,
461e5b75505Sopenharmony_ci					  eloop.term_signal.user_data);
462e5b75505Sopenharmony_ci	}
463e5b75505Sopenharmony_ci}
464e5b75505Sopenharmony_ci
465e5b75505Sopenharmony_ci
466e5b75505Sopenharmony_ciint eloop_register_signal(int sig, eloop_signal_handler handler,
467e5b75505Sopenharmony_ci			  void *user_data)
468e5b75505Sopenharmony_ci{
469e5b75505Sopenharmony_ci	struct eloop_signal *tmp;
470e5b75505Sopenharmony_ci
471e5b75505Sopenharmony_ci	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
472e5b75505Sopenharmony_ci			       sizeof(struct eloop_signal));
473e5b75505Sopenharmony_ci	if (tmp == NULL)
474e5b75505Sopenharmony_ci		return -1;
475e5b75505Sopenharmony_ci
476e5b75505Sopenharmony_ci	tmp[eloop.signal_count].sig = sig;
477e5b75505Sopenharmony_ci	tmp[eloop.signal_count].user_data = user_data;
478e5b75505Sopenharmony_ci	tmp[eloop.signal_count].handler = handler;
479e5b75505Sopenharmony_ci	tmp[eloop.signal_count].signaled = 0;
480e5b75505Sopenharmony_ci	eloop.signal_count++;
481e5b75505Sopenharmony_ci	eloop.signals = tmp;
482e5b75505Sopenharmony_ci
483e5b75505Sopenharmony_ci	/* TODO: register signal handler */
484e5b75505Sopenharmony_ci
485e5b75505Sopenharmony_ci	return 0;
486e5b75505Sopenharmony_ci}
487e5b75505Sopenharmony_ci
488e5b75505Sopenharmony_ci
489e5b75505Sopenharmony_ci#ifndef _WIN32_WCE
490e5b75505Sopenharmony_cistatic BOOL eloop_handle_console_ctrl(DWORD type)
491e5b75505Sopenharmony_ci{
492e5b75505Sopenharmony_ci	switch (type) {
493e5b75505Sopenharmony_ci	case CTRL_C_EVENT:
494e5b75505Sopenharmony_ci	case CTRL_BREAK_EVENT:
495e5b75505Sopenharmony_ci		eloop.signaled++;
496e5b75505Sopenharmony_ci		eloop.term_signal.signaled++;
497e5b75505Sopenharmony_ci		SetEvent(eloop.term_event);
498e5b75505Sopenharmony_ci		return TRUE;
499e5b75505Sopenharmony_ci	default:
500e5b75505Sopenharmony_ci		return FALSE;
501e5b75505Sopenharmony_ci	}
502e5b75505Sopenharmony_ci}
503e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */
504e5b75505Sopenharmony_ci
505e5b75505Sopenharmony_ci
506e5b75505Sopenharmony_ciint eloop_register_signal_terminate(eloop_signal_handler handler,
507e5b75505Sopenharmony_ci				    void *user_data)
508e5b75505Sopenharmony_ci{
509e5b75505Sopenharmony_ci#ifndef _WIN32_WCE
510e5b75505Sopenharmony_ci	if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
511e5b75505Sopenharmony_ci				  TRUE) == 0) {
512e5b75505Sopenharmony_ci		printf("SetConsoleCtrlHandler() failed: %d\n",
513e5b75505Sopenharmony_ci		       (int) GetLastError());
514e5b75505Sopenharmony_ci		return -1;
515e5b75505Sopenharmony_ci	}
516e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */
517e5b75505Sopenharmony_ci
518e5b75505Sopenharmony_ci	eloop.term_signal.handler = handler;
519e5b75505Sopenharmony_ci	eloop.term_signal.user_data = user_data;
520e5b75505Sopenharmony_ci
521e5b75505Sopenharmony_ci	return 0;
522e5b75505Sopenharmony_ci}
523e5b75505Sopenharmony_ci
524e5b75505Sopenharmony_ci
525e5b75505Sopenharmony_ciint eloop_register_signal_reconfig(eloop_signal_handler handler,
526e5b75505Sopenharmony_ci				   void *user_data)
527e5b75505Sopenharmony_ci{
528e5b75505Sopenharmony_ci	/* TODO */
529e5b75505Sopenharmony_ci	return 0;
530e5b75505Sopenharmony_ci}
531e5b75505Sopenharmony_ci
532e5b75505Sopenharmony_ci
533e5b75505Sopenharmony_civoid eloop_run(void)
534e5b75505Sopenharmony_ci{
535e5b75505Sopenharmony_ci	struct os_reltime tv, now;
536e5b75505Sopenharmony_ci	DWORD count, ret, timeout_val, err;
537e5b75505Sopenharmony_ci	size_t i;
538e5b75505Sopenharmony_ci
539e5b75505Sopenharmony_ci	while (!eloop.terminate &&
540e5b75505Sopenharmony_ci	       (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 ||
541e5b75505Sopenharmony_ci		eloop.event_count > 0)) {
542e5b75505Sopenharmony_ci		struct eloop_timeout *timeout;
543e5b75505Sopenharmony_ci		tv.sec = tv.usec = 0;
544e5b75505Sopenharmony_ci		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
545e5b75505Sopenharmony_ci					list);
546e5b75505Sopenharmony_ci		if (timeout) {
547e5b75505Sopenharmony_ci			os_get_reltime(&now);
548e5b75505Sopenharmony_ci			if (os_reltime_before(&now, &timeout->time))
549e5b75505Sopenharmony_ci				os_reltime_sub(&timeout->time, &now, &tv);
550e5b75505Sopenharmony_ci		}
551e5b75505Sopenharmony_ci
552e5b75505Sopenharmony_ci		count = 0;
553e5b75505Sopenharmony_ci		for (i = 0; i < eloop.event_count; i++)
554e5b75505Sopenharmony_ci			eloop.handles[count++] = eloop.events[i].event;
555e5b75505Sopenharmony_ci
556e5b75505Sopenharmony_ci		for (i = 0; i < eloop.reader_count; i++)
557e5b75505Sopenharmony_ci			eloop.handles[count++] = eloop.readers[i].event;
558e5b75505Sopenharmony_ci
559e5b75505Sopenharmony_ci		if (eloop.term_event)
560e5b75505Sopenharmony_ci			eloop.handles[count++] = eloop.term_event;
561e5b75505Sopenharmony_ci
562e5b75505Sopenharmony_ci		if (timeout)
563e5b75505Sopenharmony_ci			timeout_val = tv.sec * 1000 + tv.usec / 1000;
564e5b75505Sopenharmony_ci		else
565e5b75505Sopenharmony_ci			timeout_val = INFINITE;
566e5b75505Sopenharmony_ci
567e5b75505Sopenharmony_ci		if (count > MAXIMUM_WAIT_OBJECTS) {
568e5b75505Sopenharmony_ci			printf("WaitForMultipleObjects: Too many events: "
569e5b75505Sopenharmony_ci			       "%d > %d (ignoring extra events)\n",
570e5b75505Sopenharmony_ci			       (int) count, MAXIMUM_WAIT_OBJECTS);
571e5b75505Sopenharmony_ci			count = MAXIMUM_WAIT_OBJECTS;
572e5b75505Sopenharmony_ci		}
573e5b75505Sopenharmony_ci#ifdef _WIN32_WCE
574e5b75505Sopenharmony_ci		ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
575e5b75505Sopenharmony_ci					     timeout_val);
576e5b75505Sopenharmony_ci#else /* _WIN32_WCE */
577e5b75505Sopenharmony_ci		ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
578e5b75505Sopenharmony_ci					       timeout_val, TRUE);
579e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */
580e5b75505Sopenharmony_ci		err = GetLastError();
581e5b75505Sopenharmony_ci
582e5b75505Sopenharmony_ci		eloop_process_pending_signals();
583e5b75505Sopenharmony_ci
584e5b75505Sopenharmony_ci		/* check if some registered timeouts have occurred */
585e5b75505Sopenharmony_ci		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
586e5b75505Sopenharmony_ci					list);
587e5b75505Sopenharmony_ci		if (timeout) {
588e5b75505Sopenharmony_ci			os_get_reltime(&now);
589e5b75505Sopenharmony_ci			if (!os_reltime_before(&now, &timeout->time)) {
590e5b75505Sopenharmony_ci				void *eloop_data = timeout->eloop_data;
591e5b75505Sopenharmony_ci				void *user_data = timeout->user_data;
592e5b75505Sopenharmony_ci				eloop_timeout_handler handler =
593e5b75505Sopenharmony_ci					timeout->handler;
594e5b75505Sopenharmony_ci				eloop_remove_timeout(timeout);
595e5b75505Sopenharmony_ci				handler(eloop_data, user_data);
596e5b75505Sopenharmony_ci			}
597e5b75505Sopenharmony_ci
598e5b75505Sopenharmony_ci		}
599e5b75505Sopenharmony_ci
600e5b75505Sopenharmony_ci		if (ret == WAIT_FAILED) {
601e5b75505Sopenharmony_ci			printf("WaitForMultipleObjects(count=%d) failed: %d\n",
602e5b75505Sopenharmony_ci			       (int) count, (int) err);
603e5b75505Sopenharmony_ci			os_sleep(1, 0);
604e5b75505Sopenharmony_ci			continue;
605e5b75505Sopenharmony_ci		}
606e5b75505Sopenharmony_ci
607e5b75505Sopenharmony_ci#ifndef _WIN32_WCE
608e5b75505Sopenharmony_ci		if (ret == WAIT_IO_COMPLETION)
609e5b75505Sopenharmony_ci			continue;
610e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */
611e5b75505Sopenharmony_ci
612e5b75505Sopenharmony_ci		if (ret == WAIT_TIMEOUT)
613e5b75505Sopenharmony_ci			continue;
614e5b75505Sopenharmony_ci
615e5b75505Sopenharmony_ci		while (ret >= WAIT_OBJECT_0 &&
616e5b75505Sopenharmony_ci		       ret < WAIT_OBJECT_0 + eloop.event_count) {
617e5b75505Sopenharmony_ci			eloop.events[ret].handler(
618e5b75505Sopenharmony_ci				eloop.events[ret].eloop_data,
619e5b75505Sopenharmony_ci				eloop.events[ret].user_data);
620e5b75505Sopenharmony_ci			ret = WaitForMultipleObjects(eloop.event_count,
621e5b75505Sopenharmony_ci						     eloop.handles, FALSE, 0);
622e5b75505Sopenharmony_ci		}
623e5b75505Sopenharmony_ci
624e5b75505Sopenharmony_ci		eloop.reader_table_changed = 0;
625e5b75505Sopenharmony_ci		for (i = 0; i < eloop.reader_count; i++) {
626e5b75505Sopenharmony_ci			WSANETWORKEVENTS events;
627e5b75505Sopenharmony_ci			if (WSAEnumNetworkEvents(eloop.readers[i].sock,
628e5b75505Sopenharmony_ci						 eloop.readers[i].event,
629e5b75505Sopenharmony_ci						 &events) == 0 &&
630e5b75505Sopenharmony_ci			    (events.lNetworkEvents & FD_READ)) {
631e5b75505Sopenharmony_ci				eloop.readers[i].handler(
632e5b75505Sopenharmony_ci					eloop.readers[i].sock,
633e5b75505Sopenharmony_ci					eloop.readers[i].eloop_data,
634e5b75505Sopenharmony_ci					eloop.readers[i].user_data);
635e5b75505Sopenharmony_ci				if (eloop.reader_table_changed)
636e5b75505Sopenharmony_ci					break;
637e5b75505Sopenharmony_ci			}
638e5b75505Sopenharmony_ci		}
639e5b75505Sopenharmony_ci	}
640e5b75505Sopenharmony_ci}
641e5b75505Sopenharmony_ci
642e5b75505Sopenharmony_ci
643e5b75505Sopenharmony_civoid eloop_terminate(void)
644e5b75505Sopenharmony_ci{
645e5b75505Sopenharmony_ci	eloop.terminate = 1;
646e5b75505Sopenharmony_ci	SetEvent(eloop.term_event);
647e5b75505Sopenharmony_ci}
648e5b75505Sopenharmony_ci
649e5b75505Sopenharmony_ci
650e5b75505Sopenharmony_civoid eloop_destroy(void)
651e5b75505Sopenharmony_ci{
652e5b75505Sopenharmony_ci	struct eloop_timeout *timeout, *prev;
653e5b75505Sopenharmony_ci
654e5b75505Sopenharmony_ci	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
655e5b75505Sopenharmony_ci			      struct eloop_timeout, list) {
656e5b75505Sopenharmony_ci		eloop_remove_timeout(timeout);
657e5b75505Sopenharmony_ci	}
658e5b75505Sopenharmony_ci	os_free(eloop.readers);
659e5b75505Sopenharmony_ci	os_free(eloop.signals);
660e5b75505Sopenharmony_ci	if (eloop.term_event)
661e5b75505Sopenharmony_ci		CloseHandle(eloop.term_event);
662e5b75505Sopenharmony_ci	os_free(eloop.handles);
663e5b75505Sopenharmony_ci	eloop.handles = NULL;
664e5b75505Sopenharmony_ci	os_free(eloop.events);
665e5b75505Sopenharmony_ci	eloop.events = NULL;
666e5b75505Sopenharmony_ci}
667e5b75505Sopenharmony_ci
668e5b75505Sopenharmony_ci
669e5b75505Sopenharmony_ciint eloop_terminated(void)
670e5b75505Sopenharmony_ci{
671e5b75505Sopenharmony_ci	return eloop.terminate;
672e5b75505Sopenharmony_ci}
673e5b75505Sopenharmony_ci
674e5b75505Sopenharmony_ci
675e5b75505Sopenharmony_civoid eloop_wait_for_read_sock(int sock)
676e5b75505Sopenharmony_ci{
677e5b75505Sopenharmony_ci	WSAEVENT event;
678e5b75505Sopenharmony_ci
679e5b75505Sopenharmony_ci	event = WSACreateEvent();
680e5b75505Sopenharmony_ci	if (event == WSA_INVALID_EVENT) {
681e5b75505Sopenharmony_ci		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
682e5b75505Sopenharmony_ci		return;
683e5b75505Sopenharmony_ci	}
684e5b75505Sopenharmony_ci
685e5b75505Sopenharmony_ci	if (WSAEventSelect(sock, event, FD_READ)) {
686e5b75505Sopenharmony_ci		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
687e5b75505Sopenharmony_ci		WSACloseEvent(event);
688e5b75505Sopenharmony_ci		return ;
689e5b75505Sopenharmony_ci	}
690e5b75505Sopenharmony_ci
691e5b75505Sopenharmony_ci	WaitForSingleObject(event, INFINITE);
692e5b75505Sopenharmony_ci	WSAEventSelect(sock, event, 0);
693e5b75505Sopenharmony_ci	WSACloseEvent(event);
694e5b75505Sopenharmony_ci}
695e5b75505Sopenharmony_ci
696e5b75505Sopenharmony_ci
697e5b75505Sopenharmony_ciint eloop_sock_requeue(void)
698e5b75505Sopenharmony_ci{
699e5b75505Sopenharmony_ci	return 0;
700e5b75505Sopenharmony_ci}
701