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