$search
00001 /* 00002 * Event loop based on Windows events and WaitForMultipleObjects 00003 * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #include <winsock2.h> 00017 00018 #include "common.h" 00019 #include "eloop.h" 00020 00021 00022 struct eloop_sock { 00023 int sock; 00024 void *eloop_data; 00025 void *user_data; 00026 eloop_sock_handler handler; 00027 WSAEVENT event; 00028 }; 00029 00030 struct eloop_event { 00031 void *eloop_data; 00032 void *user_data; 00033 eloop_event_handler handler; 00034 HANDLE event; 00035 }; 00036 00037 struct eloop_timeout { 00038 struct os_time time; 00039 void *eloop_data; 00040 void *user_data; 00041 eloop_timeout_handler handler; 00042 struct eloop_timeout *next; 00043 }; 00044 00045 struct eloop_signal { 00046 int sig; 00047 void *user_data; 00048 eloop_signal_handler handler; 00049 int signaled; 00050 }; 00051 00052 struct eloop_data { 00053 int max_sock; 00054 size_t reader_count; 00055 struct eloop_sock *readers; 00056 00057 size_t event_count; 00058 struct eloop_event *events; 00059 00060 struct eloop_timeout *timeout; 00061 00062 int signal_count; 00063 struct eloop_signal *signals; 00064 int signaled; 00065 int pending_terminate; 00066 00067 int terminate; 00068 int reader_table_changed; 00069 00070 struct eloop_signal term_signal; 00071 HANDLE term_event; 00072 00073 HANDLE *handles; 00074 size_t num_handles; 00075 }; 00076 00077 static struct eloop_data eloop; 00078 00079 00080 int eloop_init(void) 00081 { 00082 os_memset(&eloop, 0, sizeof(eloop)); 00083 eloop.num_handles = 1; 00084 eloop.handles = os_malloc(eloop.num_handles * 00085 sizeof(eloop.handles[0])); 00086 if (eloop.handles == NULL) 00087 return -1; 00088 00089 eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); 00090 if (eloop.term_event == NULL) { 00091 printf("CreateEvent() failed: %d\n", 00092 (int) GetLastError()); 00093 os_free(eloop.handles); 00094 return -1; 00095 } 00096 00097 return 0; 00098 } 00099 00100 00101 static int eloop_prepare_handles(void) 00102 { 00103 HANDLE *n; 00104 00105 if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) 00106 return 0; 00107 n = os_realloc(eloop.handles, 00108 eloop.num_handles * 2 * sizeof(eloop.handles[0])); 00109 if (n == NULL) 00110 return -1; 00111 eloop.handles = n; 00112 eloop.num_handles *= 2; 00113 return 0; 00114 } 00115 00116 00117 int eloop_register_read_sock(int sock, eloop_sock_handler handler, 00118 void *eloop_data, void *user_data) 00119 { 00120 WSAEVENT event; 00121 struct eloop_sock *tmp; 00122 00123 if (eloop_prepare_handles()) 00124 return -1; 00125 00126 event = WSACreateEvent(); 00127 if (event == WSA_INVALID_EVENT) { 00128 printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 00129 return -1; 00130 } 00131 00132 if (WSAEventSelect(sock, event, FD_READ)) { 00133 printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 00134 WSACloseEvent(event); 00135 return -1; 00136 } 00137 tmp = os_realloc(eloop.readers, 00138 (eloop.reader_count + 1) * sizeof(struct eloop_sock)); 00139 if (tmp == NULL) { 00140 WSAEventSelect(sock, event, 0); 00141 WSACloseEvent(event); 00142 return -1; 00143 } 00144 00145 tmp[eloop.reader_count].sock = sock; 00146 tmp[eloop.reader_count].eloop_data = eloop_data; 00147 tmp[eloop.reader_count].user_data = user_data; 00148 tmp[eloop.reader_count].handler = handler; 00149 tmp[eloop.reader_count].event = event; 00150 eloop.reader_count++; 00151 eloop.readers = tmp; 00152 if (sock > eloop.max_sock) 00153 eloop.max_sock = sock; 00154 eloop.reader_table_changed = 1; 00155 00156 return 0; 00157 } 00158 00159 00160 void eloop_unregister_read_sock(int sock) 00161 { 00162 size_t i; 00163 00164 if (eloop.readers == NULL || eloop.reader_count == 0) 00165 return; 00166 00167 for (i = 0; i < eloop.reader_count; i++) { 00168 if (eloop.readers[i].sock == sock) 00169 break; 00170 } 00171 if (i == eloop.reader_count) 00172 return; 00173 00174 WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); 00175 WSACloseEvent(eloop.readers[i].event); 00176 00177 if (i != eloop.reader_count - 1) { 00178 os_memmove(&eloop.readers[i], &eloop.readers[i + 1], 00179 (eloop.reader_count - i - 1) * 00180 sizeof(struct eloop_sock)); 00181 } 00182 eloop.reader_count--; 00183 eloop.reader_table_changed = 1; 00184 } 00185 00186 00187 int eloop_register_event(void *event, size_t event_size, 00188 eloop_event_handler handler, 00189 void *eloop_data, void *user_data) 00190 { 00191 struct eloop_event *tmp; 00192 HANDLE h = event; 00193 00194 if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) 00195 return -1; 00196 00197 if (eloop_prepare_handles()) 00198 return -1; 00199 00200 tmp = os_realloc(eloop.events, 00201 (eloop.event_count + 1) * sizeof(struct eloop_event)); 00202 if (tmp == NULL) 00203 return -1; 00204 00205 tmp[eloop.event_count].eloop_data = eloop_data; 00206 tmp[eloop.event_count].user_data = user_data; 00207 tmp[eloop.event_count].handler = handler; 00208 tmp[eloop.event_count].event = h; 00209 eloop.event_count++; 00210 eloop.events = tmp; 00211 00212 return 0; 00213 } 00214 00215 00216 void eloop_unregister_event(void *event, size_t event_size) 00217 { 00218 size_t i; 00219 HANDLE h = event; 00220 00221 if (eloop.events == NULL || eloop.event_count == 0 || 00222 event_size != sizeof(HANDLE)) 00223 return; 00224 00225 for (i = 0; i < eloop.event_count; i++) { 00226 if (eloop.events[i].event == h) 00227 break; 00228 } 00229 if (i == eloop.event_count) 00230 return; 00231 00232 if (i != eloop.event_count - 1) { 00233 os_memmove(&eloop.events[i], &eloop.events[i + 1], 00234 (eloop.event_count - i - 1) * 00235 sizeof(struct eloop_event)); 00236 } 00237 eloop.event_count--; 00238 } 00239 00240 00241 int eloop_register_timeout(unsigned int secs, unsigned int usecs, 00242 eloop_timeout_handler handler, 00243 void *eloop_data, void *user_data) 00244 { 00245 struct eloop_timeout *timeout, *tmp, *prev; 00246 00247 timeout = os_malloc(sizeof(*timeout)); 00248 if (timeout == NULL) 00249 return -1; 00250 os_get_time(&timeout->time); 00251 timeout->time.sec += secs; 00252 timeout->time.usec += usecs; 00253 while (timeout->time.usec >= 1000000) { 00254 timeout->time.sec++; 00255 timeout->time.usec -= 1000000; 00256 } 00257 timeout->eloop_data = eloop_data; 00258 timeout->user_data = user_data; 00259 timeout->handler = handler; 00260 timeout->next = NULL; 00261 00262 if (eloop.timeout == NULL) { 00263 eloop.timeout = timeout; 00264 return 0; 00265 } 00266 00267 prev = NULL; 00268 tmp = eloop.timeout; 00269 while (tmp != NULL) { 00270 if (os_time_before(&timeout->time, &tmp->time)) 00271 break; 00272 prev = tmp; 00273 tmp = tmp->next; 00274 } 00275 00276 if (prev == NULL) { 00277 timeout->next = eloop.timeout; 00278 eloop.timeout = timeout; 00279 } else { 00280 timeout->next = prev->next; 00281 prev->next = timeout; 00282 } 00283 00284 return 0; 00285 } 00286 00287 00288 int eloop_cancel_timeout(eloop_timeout_handler handler, 00289 void *eloop_data, void *user_data) 00290 { 00291 struct eloop_timeout *timeout, *prev, *next; 00292 int removed = 0; 00293 00294 prev = NULL; 00295 timeout = eloop.timeout; 00296 while (timeout != NULL) { 00297 next = timeout->next; 00298 00299 if (timeout->handler == handler && 00300 (timeout->eloop_data == eloop_data || 00301 eloop_data == ELOOP_ALL_CTX) && 00302 (timeout->user_data == user_data || 00303 user_data == ELOOP_ALL_CTX)) { 00304 if (prev == NULL) 00305 eloop.timeout = next; 00306 else 00307 prev->next = next; 00308 os_free(timeout); 00309 removed++; 00310 } else 00311 prev = timeout; 00312 00313 timeout = next; 00314 } 00315 00316 return removed; 00317 } 00318 00319 00320 int eloop_is_timeout_registered(eloop_timeout_handler handler, 00321 void *eloop_data, void *user_data) 00322 { 00323 struct eloop_timeout *tmp; 00324 00325 tmp = eloop.timeout; 00326 while (tmp != NULL) { 00327 if (tmp->handler == handler && 00328 tmp->eloop_data == eloop_data && 00329 tmp->user_data == user_data) 00330 return 1; 00331 00332 tmp = tmp->next; 00333 } 00334 00335 return 0; 00336 } 00337 00338 00339 /* TODO: replace with suitable signal handler */ 00340 #if 0 00341 static void eloop_handle_signal(int sig) 00342 { 00343 int i; 00344 00345 eloop.signaled++; 00346 for (i = 0; i < eloop.signal_count; i++) { 00347 if (eloop.signals[i].sig == sig) { 00348 eloop.signals[i].signaled++; 00349 break; 00350 } 00351 } 00352 } 00353 #endif 00354 00355 00356 static void eloop_process_pending_signals(void) 00357 { 00358 int i; 00359 00360 if (eloop.signaled == 0) 00361 return; 00362 eloop.signaled = 0; 00363 00364 if (eloop.pending_terminate) { 00365 eloop.pending_terminate = 0; 00366 } 00367 00368 for (i = 0; i < eloop.signal_count; i++) { 00369 if (eloop.signals[i].signaled) { 00370 eloop.signals[i].signaled = 0; 00371 eloop.signals[i].handler(eloop.signals[i].sig, 00372 eloop.signals[i].user_data); 00373 } 00374 } 00375 00376 if (eloop.term_signal.signaled) { 00377 eloop.term_signal.signaled = 0; 00378 eloop.term_signal.handler(eloop.term_signal.sig, 00379 eloop.term_signal.user_data); 00380 } 00381 } 00382 00383 00384 int eloop_register_signal(int sig, eloop_signal_handler handler, 00385 void *user_data) 00386 { 00387 struct eloop_signal *tmp; 00388 00389 tmp = os_realloc(eloop.signals, 00390 (eloop.signal_count + 1) * 00391 sizeof(struct eloop_signal)); 00392 if (tmp == NULL) 00393 return -1; 00394 00395 tmp[eloop.signal_count].sig = sig; 00396 tmp[eloop.signal_count].user_data = user_data; 00397 tmp[eloop.signal_count].handler = handler; 00398 tmp[eloop.signal_count].signaled = 0; 00399 eloop.signal_count++; 00400 eloop.signals = tmp; 00401 00402 /* TODO: register signal handler */ 00403 00404 return 0; 00405 } 00406 00407 00408 #ifndef _WIN32_WCE 00409 static BOOL eloop_handle_console_ctrl(DWORD type) 00410 { 00411 switch (type) { 00412 case CTRL_C_EVENT: 00413 case CTRL_BREAK_EVENT: 00414 eloop.signaled++; 00415 eloop.term_signal.signaled++; 00416 SetEvent(eloop.term_event); 00417 return TRUE; 00418 default: 00419 return FALSE; 00420 } 00421 } 00422 #endif /* _WIN32_WCE */ 00423 00424 00425 int eloop_register_signal_terminate(eloop_signal_handler handler, 00426 void *user_data) 00427 { 00428 #ifndef _WIN32_WCE 00429 if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 00430 TRUE) == 0) { 00431 printf("SetConsoleCtrlHandler() failed: %d\n", 00432 (int) GetLastError()); 00433 return -1; 00434 } 00435 #endif /* _WIN32_WCE */ 00436 00437 eloop.term_signal.handler = handler; 00438 eloop.term_signal.user_data = user_data; 00439 00440 return 0; 00441 } 00442 00443 00444 int eloop_register_signal_reconfig(eloop_signal_handler handler, 00445 void *user_data) 00446 { 00447 /* TODO */ 00448 return 0; 00449 } 00450 00451 00452 void eloop_run(void) 00453 { 00454 struct os_time tv, now; 00455 DWORD count, ret, timeout, err; 00456 size_t i; 00457 00458 while (!eloop.terminate && 00459 (eloop.timeout || eloop.reader_count > 0 || 00460 eloop.event_count > 0)) { 00461 tv.sec = tv.usec = 0; 00462 if (eloop.timeout) { 00463 os_get_time(&now); 00464 if (os_time_before(&now, &eloop.timeout->time)) 00465 os_time_sub(&eloop.timeout->time, &now, &tv); 00466 } 00467 00468 count = 0; 00469 for (i = 0; i < eloop.event_count; i++) 00470 eloop.handles[count++] = eloop.events[i].event; 00471 00472 for (i = 0; i < eloop.reader_count; i++) 00473 eloop.handles[count++] = eloop.readers[i].event; 00474 00475 if (eloop.term_event) 00476 eloop.handles[count++] = eloop.term_event; 00477 00478 if (eloop.timeout) 00479 timeout = tv.sec * 1000 + tv.usec / 1000; 00480 else 00481 timeout = INFINITE; 00482 00483 if (count > MAXIMUM_WAIT_OBJECTS) { 00484 printf("WaitForMultipleObjects: Too many events: " 00485 "%d > %d (ignoring extra events)\n", 00486 (int) count, MAXIMUM_WAIT_OBJECTS); 00487 count = MAXIMUM_WAIT_OBJECTS; 00488 } 00489 #ifdef _WIN32_WCE 00490 ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 00491 timeout); 00492 #else /* _WIN32_WCE */ 00493 ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 00494 timeout, TRUE); 00495 #endif /* _WIN32_WCE */ 00496 err = GetLastError(); 00497 00498 eloop_process_pending_signals(); 00499 00500 /* check if some registered timeouts have occurred */ 00501 if (eloop.timeout) { 00502 struct eloop_timeout *tmp; 00503 00504 os_get_time(&now); 00505 if (!os_time_before(&now, &eloop.timeout->time)) { 00506 tmp = eloop.timeout; 00507 eloop.timeout = eloop.timeout->next; 00508 tmp->handler(tmp->eloop_data, 00509 tmp->user_data); 00510 os_free(tmp); 00511 } 00512 00513 } 00514 00515 if (ret == WAIT_FAILED) { 00516 printf("WaitForMultipleObjects(count=%d) failed: %d\n", 00517 (int) count, (int) err); 00518 os_sleep(1, 0); 00519 continue; 00520 } 00521 00522 #ifndef _WIN32_WCE 00523 if (ret == WAIT_IO_COMPLETION) 00524 continue; 00525 #endif /* _WIN32_WCE */ 00526 00527 if (ret == WAIT_TIMEOUT) 00528 continue; 00529 00530 while (ret >= WAIT_OBJECT_0 && 00531 ret < WAIT_OBJECT_0 + eloop.event_count) { 00532 eloop.events[ret].handler( 00533 eloop.events[ret].eloop_data, 00534 eloop.events[ret].user_data); 00535 ret = WaitForMultipleObjects(eloop.event_count, 00536 eloop.handles, FALSE, 0); 00537 } 00538 00539 eloop.reader_table_changed = 0; 00540 for (i = 0; i < eloop.reader_count; i++) { 00541 WSANETWORKEVENTS events; 00542 if (WSAEnumNetworkEvents(eloop.readers[i].sock, 00543 eloop.readers[i].event, 00544 &events) == 0 && 00545 (events.lNetworkEvents & FD_READ)) { 00546 eloop.readers[i].handler( 00547 eloop.readers[i].sock, 00548 eloop.readers[i].eloop_data, 00549 eloop.readers[i].user_data); 00550 if (eloop.reader_table_changed) 00551 break; 00552 } 00553 } 00554 } 00555 } 00556 00557 00558 void eloop_terminate(void) 00559 { 00560 eloop.terminate = 1; 00561 SetEvent(eloop.term_event); 00562 } 00563 00564 00565 void eloop_destroy(void) 00566 { 00567 struct eloop_timeout *timeout, *prev; 00568 00569 timeout = eloop.timeout; 00570 while (timeout != NULL) { 00571 prev = timeout; 00572 timeout = timeout->next; 00573 os_free(prev); 00574 } 00575 os_free(eloop.readers); 00576 os_free(eloop.signals); 00577 if (eloop.term_event) 00578 CloseHandle(eloop.term_event); 00579 os_free(eloop.handles); 00580 eloop.handles = NULL; 00581 os_free(eloop.events); 00582 eloop.events = NULL; 00583 } 00584 00585 00586 int eloop_terminated(void) 00587 { 00588 return eloop.terminate; 00589 } 00590 00591 00592 void eloop_wait_for_read_sock(int sock) 00593 { 00594 WSAEVENT event; 00595 00596 event = WSACreateEvent(); 00597 if (event == WSA_INVALID_EVENT) { 00598 printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 00599 return; 00600 } 00601 00602 if (WSAEventSelect(sock, event, FD_READ)) { 00603 printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 00604 WSACloseEvent(event); 00605 return ; 00606 } 00607 00608 WaitForSingleObject(event, INFINITE); 00609 WSAEventSelect(sock, event, 0); 00610 WSACloseEvent(event); 00611 }