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