Home | History | Annotate | Download | only in utils
      1 /*
      2  * Event loop based on Windows events and WaitForMultipleObjects
      3  * Copyright (c) 2002-2006, Jouni Malinen <j (at) 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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    456 int eloop_register_signal_reconfig(eloop_signal_handler handler,
    457 				   void *user_data)
    458 {
    459 	/* TODO */
    460 	return 0;
    461 }
    462 
    463 
    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 
    570 void eloop_terminate(void)
    571 {
    572 	eloop.terminate = 1;
    573 	SetEvent(eloop.term_event);
    574 }
    575 
    576 
    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 
    598 int eloop_terminated(void)
    599 {
    600 	return eloop.terminate;
    601 }
    602 
    603 
    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