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_time 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_time(&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_time_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_time *remaining) 317 { 318 struct eloop_timeout *timeout, *prev; 319 int removed = 0; 320 struct os_time now; 321 322 os_get_time(&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_time_before(&now, &timeout->time)) 332 os_time_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 /* TODO: replace with suitable signal handler */ 358 #if 0 359 static void eloop_handle_signal(int sig) 360 { 361 int i; 362 363 eloop.signaled++; 364 for (i = 0; i < eloop.signal_count; i++) { 365 if (eloop.signals[i].sig == sig) { 366 eloop.signals[i].signaled++; 367 break; 368 } 369 } 370 } 371 #endif 372 373 374 static void eloop_process_pending_signals(void) 375 { 376 int i; 377 378 if (eloop.signaled == 0) 379 return; 380 eloop.signaled = 0; 381 382 if (eloop.pending_terminate) { 383 eloop.pending_terminate = 0; 384 } 385 386 for (i = 0; i < eloop.signal_count; i++) { 387 if (eloop.signals[i].signaled) { 388 eloop.signals[i].signaled = 0; 389 eloop.signals[i].handler(eloop.signals[i].sig, 390 eloop.signals[i].user_data); 391 } 392 } 393 394 if (eloop.term_signal.signaled) { 395 eloop.term_signal.signaled = 0; 396 eloop.term_signal.handler(eloop.term_signal.sig, 397 eloop.term_signal.user_data); 398 } 399 } 400 401 402 int eloop_register_signal(int sig, eloop_signal_handler handler, 403 void *user_data) 404 { 405 struct eloop_signal *tmp; 406 407 tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 408 sizeof(struct eloop_signal)); 409 if (tmp == NULL) 410 return -1; 411 412 tmp[eloop.signal_count].sig = sig; 413 tmp[eloop.signal_count].user_data = user_data; 414 tmp[eloop.signal_count].handler = handler; 415 tmp[eloop.signal_count].signaled = 0; 416 eloop.signal_count++; 417 eloop.signals = tmp; 418 419 /* TODO: register signal handler */ 420 421 return 0; 422 } 423 424 425 #ifndef _WIN32_WCE 426 static BOOL eloop_handle_console_ctrl(DWORD type) 427 { 428 switch (type) { 429 case CTRL_C_EVENT: 430 case CTRL_BREAK_EVENT: 431 eloop.signaled++; 432 eloop.term_signal.signaled++; 433 SetEvent(eloop.term_event); 434 return TRUE; 435 default: 436 return FALSE; 437 } 438 } 439 #endif /* _WIN32_WCE */ 440 441 442 int eloop_register_signal_terminate(eloop_signal_handler handler, 443 void *user_data) 444 { 445 #ifndef _WIN32_WCE 446 if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 447 TRUE) == 0) { 448 printf("SetConsoleCtrlHandler() failed: %d\n", 449 (int) GetLastError()); 450 return -1; 451 } 452 #endif /* _WIN32_WCE */ 453 454 eloop.term_signal.handler = handler; 455 eloop.term_signal.user_data = user_data; 456 457 return 0; 458 } 459 460 461 int eloop_register_signal_reconfig(eloop_signal_handler handler, 462 void *user_data) 463 { 464 /* TODO */ 465 return 0; 466 } 467 468 469 void eloop_run(void) 470 { 471 struct os_time tv, now; 472 DWORD count, ret, timeout_val, err; 473 size_t i; 474 475 while (!eloop.terminate && 476 (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 || 477 eloop.event_count > 0)) { 478 struct eloop_timeout *timeout; 479 tv.sec = tv.usec = 0; 480 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 481 list); 482 if (timeout) { 483 os_get_time(&now); 484 if (os_time_before(&now, &timeout->time)) 485 os_time_sub(&timeout->time, &now, &tv); 486 } 487 488 count = 0; 489 for (i = 0; i < eloop.event_count; i++) 490 eloop.handles[count++] = eloop.events[i].event; 491 492 for (i = 0; i < eloop.reader_count; i++) 493 eloop.handles[count++] = eloop.readers[i].event; 494 495 if (eloop.term_event) 496 eloop.handles[count++] = eloop.term_event; 497 498 if (timeout) 499 timeout_val = tv.sec * 1000 + tv.usec / 1000; 500 else 501 timeout_val = INFINITE; 502 503 if (count > MAXIMUM_WAIT_OBJECTS) { 504 printf("WaitForMultipleObjects: Too many events: " 505 "%d > %d (ignoring extra events)\n", 506 (int) count, MAXIMUM_WAIT_OBJECTS); 507 count = MAXIMUM_WAIT_OBJECTS; 508 } 509 #ifdef _WIN32_WCE 510 ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 511 timeout_val); 512 #else /* _WIN32_WCE */ 513 ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 514 timeout_val, TRUE); 515 #endif /* _WIN32_WCE */ 516 err = GetLastError(); 517 518 eloop_process_pending_signals(); 519 520 /* check if some registered timeouts have occurred */ 521 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 522 list); 523 if (timeout) { 524 os_get_time(&now); 525 if (!os_time_before(&now, &timeout->time)) { 526 void *eloop_data = timeout->eloop_data; 527 void *user_data = timeout->user_data; 528 eloop_timeout_handler handler = 529 timeout->handler; 530 eloop_remove_timeout(timeout); 531 handler(eloop_data, user_data); 532 } 533 534 } 535 536 if (ret == WAIT_FAILED) { 537 printf("WaitForMultipleObjects(count=%d) failed: %d\n", 538 (int) count, (int) err); 539 os_sleep(1, 0); 540 continue; 541 } 542 543 #ifndef _WIN32_WCE 544 if (ret == WAIT_IO_COMPLETION) 545 continue; 546 #endif /* _WIN32_WCE */ 547 548 if (ret == WAIT_TIMEOUT) 549 continue; 550 551 while (ret >= WAIT_OBJECT_0 && 552 ret < WAIT_OBJECT_0 + eloop.event_count) { 553 eloop.events[ret].handler( 554 eloop.events[ret].eloop_data, 555 eloop.events[ret].user_data); 556 ret = WaitForMultipleObjects(eloop.event_count, 557 eloop.handles, FALSE, 0); 558 } 559 560 eloop.reader_table_changed = 0; 561 for (i = 0; i < eloop.reader_count; i++) { 562 WSANETWORKEVENTS events; 563 if (WSAEnumNetworkEvents(eloop.readers[i].sock, 564 eloop.readers[i].event, 565 &events) == 0 && 566 (events.lNetworkEvents & FD_READ)) { 567 eloop.readers[i].handler( 568 eloop.readers[i].sock, 569 eloop.readers[i].eloop_data, 570 eloop.readers[i].user_data); 571 if (eloop.reader_table_changed) 572 break; 573 } 574 } 575 } 576 } 577 578 579 void eloop_terminate(void) 580 { 581 eloop.terminate = 1; 582 SetEvent(eloop.term_event); 583 } 584 585 586 void eloop_destroy(void) 587 { 588 struct eloop_timeout *timeout, *prev; 589 590 dl_list_for_each_safe(timeout, prev, &eloop.timeout, 591 struct eloop_timeout, list) { 592 eloop_remove_timeout(timeout); 593 } 594 os_free(eloop.readers); 595 os_free(eloop.signals); 596 if (eloop.term_event) 597 CloseHandle(eloop.term_event); 598 os_free(eloop.handles); 599 eloop.handles = NULL; 600 os_free(eloop.events); 601 eloop.events = NULL; 602 } 603 604 605 int eloop_terminated(void) 606 { 607 return eloop.terminate; 608 } 609 610 611 void eloop_wait_for_read_sock(int sock) 612 { 613 WSAEVENT event; 614 615 event = WSACreateEvent(); 616 if (event == WSA_INVALID_EVENT) { 617 printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 618 return; 619 } 620 621 if (WSAEventSelect(sock, event, FD_READ)) { 622 printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 623 WSACloseEvent(event); 624 return ; 625 } 626 627 WaitForSingleObject(event, INFINITE); 628 WSAEventSelect(sock, event, 0); 629 WSACloseEvent(event); 630 } 631