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