eloop_win.c revision e0e48dc666fb14a7bb60264ca87463ba7bc1fe0b
1/* 2 * Event loop based on Windows events and WaitForMultipleObjects 3 * Copyright (c) 2002-2009, Jouni Malinen <j@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 17struct eloop_sock { 18 int sock; 19 void *eloop_data; 20 void *user_data; 21 eloop_sock_handler handler; 22 WSAEVENT event; 23}; 24 25struct eloop_event { 26 void *eloop_data; 27 void *user_data; 28 eloop_event_handler handler; 29 HANDLE event; 30}; 31 32struct 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 40struct eloop_signal { 41 int sig; 42 void *user_data; 43 eloop_signal_handler handler; 44 int signaled; 45}; 46 47struct 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 72static struct eloop_data eloop; 73 74 75int 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 97static 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 113int 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 156void 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 183int 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 212void 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 237int 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 285static void eloop_remove_timeout(struct eloop_timeout *timeout) 286{ 287 dl_list_del(&timeout->list); 288 os_free(timeout); 289} 290 291 292int 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 314int 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 341int 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 357int 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_time 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_time(&now); 371 os_time_sub(&tmp->time, &now, &remaining); 372 if (os_time_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 } 382 } 383 384 return 0; 385} 386 387 388int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, 389 eloop_timeout_handler handler, void *eloop_data, 390 void *user_data) 391{ 392 struct os_time now, requested, remaining; 393 struct eloop_timeout *tmp; 394 395 dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 396 if (tmp->handler == handler && 397 tmp->eloop_data == eloop_data && 398 tmp->user_data == user_data) { 399 requested.sec = req_secs; 400 requested.usec = req_usecs; 401 os_get_time(&now); 402 os_time_sub(&tmp->time, &now, &remaining); 403 if (os_time_before(&remaining, &requested)) { 404 eloop_cancel_timeout(handler, eloop_data, 405 user_data); 406 eloop_register_timeout(requested.sec, 407 requested.usec, 408 handler, eloop_data, 409 user_data); 410 return 1; 411 } 412 } 413 } 414 415 return 0; 416} 417 418 419/* TODO: replace with suitable signal handler */ 420#if 0 421static void eloop_handle_signal(int sig) 422{ 423 int i; 424 425 eloop.signaled++; 426 for (i = 0; i < eloop.signal_count; i++) { 427 if (eloop.signals[i].sig == sig) { 428 eloop.signals[i].signaled++; 429 break; 430 } 431 } 432} 433#endif 434 435 436static void eloop_process_pending_signals(void) 437{ 438 int i; 439 440 if (eloop.signaled == 0) 441 return; 442 eloop.signaled = 0; 443 444 if (eloop.pending_terminate) { 445 eloop.pending_terminate = 0; 446 } 447 448 for (i = 0; i < eloop.signal_count; i++) { 449 if (eloop.signals[i].signaled) { 450 eloop.signals[i].signaled = 0; 451 eloop.signals[i].handler(eloop.signals[i].sig, 452 eloop.signals[i].user_data); 453 } 454 } 455 456 if (eloop.term_signal.signaled) { 457 eloop.term_signal.signaled = 0; 458 eloop.term_signal.handler(eloop.term_signal.sig, 459 eloop.term_signal.user_data); 460 } 461} 462 463 464int eloop_register_signal(int sig, eloop_signal_handler handler, 465 void *user_data) 466{ 467 struct eloop_signal *tmp; 468 469 tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 470 sizeof(struct eloop_signal)); 471 if (tmp == NULL) 472 return -1; 473 474 tmp[eloop.signal_count].sig = sig; 475 tmp[eloop.signal_count].user_data = user_data; 476 tmp[eloop.signal_count].handler = handler; 477 tmp[eloop.signal_count].signaled = 0; 478 eloop.signal_count++; 479 eloop.signals = tmp; 480 481 /* TODO: register signal handler */ 482 483 return 0; 484} 485 486 487#ifndef _WIN32_WCE 488static BOOL eloop_handle_console_ctrl(DWORD type) 489{ 490 switch (type) { 491 case CTRL_C_EVENT: 492 case CTRL_BREAK_EVENT: 493 eloop.signaled++; 494 eloop.term_signal.signaled++; 495 SetEvent(eloop.term_event); 496 return TRUE; 497 default: 498 return FALSE; 499 } 500} 501#endif /* _WIN32_WCE */ 502 503 504int eloop_register_signal_terminate(eloop_signal_handler handler, 505 void *user_data) 506{ 507#ifndef _WIN32_WCE 508 if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 509 TRUE) == 0) { 510 printf("SetConsoleCtrlHandler() failed: %d\n", 511 (int) GetLastError()); 512 return -1; 513 } 514#endif /* _WIN32_WCE */ 515 516 eloop.term_signal.handler = handler; 517 eloop.term_signal.user_data = user_data; 518 519 return 0; 520} 521 522 523int eloop_register_signal_reconfig(eloop_signal_handler handler, 524 void *user_data) 525{ 526 /* TODO */ 527 return 0; 528} 529 530 531void eloop_run(void) 532{ 533 struct os_time tv, now; 534 DWORD count, ret, timeout_val, err; 535 size_t i; 536 537 while (!eloop.terminate && 538 (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 || 539 eloop.event_count > 0)) { 540 struct eloop_timeout *timeout; 541 tv.sec = tv.usec = 0; 542 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 543 list); 544 if (timeout) { 545 os_get_time(&now); 546 if (os_time_before(&now, &timeout->time)) 547 os_time_sub(&timeout->time, &now, &tv); 548 } 549 550 count = 0; 551 for (i = 0; i < eloop.event_count; i++) 552 eloop.handles[count++] = eloop.events[i].event; 553 554 for (i = 0; i < eloop.reader_count; i++) 555 eloop.handles[count++] = eloop.readers[i].event; 556 557 if (eloop.term_event) 558 eloop.handles[count++] = eloop.term_event; 559 560 if (timeout) 561 timeout_val = tv.sec * 1000 + tv.usec / 1000; 562 else 563 timeout_val = INFINITE; 564 565 if (count > MAXIMUM_WAIT_OBJECTS) { 566 printf("WaitForMultipleObjects: Too many events: " 567 "%d > %d (ignoring extra events)\n", 568 (int) count, MAXIMUM_WAIT_OBJECTS); 569 count = MAXIMUM_WAIT_OBJECTS; 570 } 571#ifdef _WIN32_WCE 572 ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 573 timeout_val); 574#else /* _WIN32_WCE */ 575 ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 576 timeout_val, TRUE); 577#endif /* _WIN32_WCE */ 578 err = GetLastError(); 579 580 eloop_process_pending_signals(); 581 582 /* check if some registered timeouts have occurred */ 583 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 584 list); 585 if (timeout) { 586 os_get_time(&now); 587 if (!os_time_before(&now, &timeout->time)) { 588 void *eloop_data = timeout->eloop_data; 589 void *user_data = timeout->user_data; 590 eloop_timeout_handler handler = 591 timeout->handler; 592 eloop_remove_timeout(timeout); 593 handler(eloop_data, user_data); 594 } 595 596 } 597 598 if (ret == WAIT_FAILED) { 599 printf("WaitForMultipleObjects(count=%d) failed: %d\n", 600 (int) count, (int) err); 601 os_sleep(1, 0); 602 continue; 603 } 604 605#ifndef _WIN32_WCE 606 if (ret == WAIT_IO_COMPLETION) 607 continue; 608#endif /* _WIN32_WCE */ 609 610 if (ret == WAIT_TIMEOUT) 611 continue; 612 613 while (ret >= WAIT_OBJECT_0 && 614 ret < WAIT_OBJECT_0 + eloop.event_count) { 615 eloop.events[ret].handler( 616 eloop.events[ret].eloop_data, 617 eloop.events[ret].user_data); 618 ret = WaitForMultipleObjects(eloop.event_count, 619 eloop.handles, FALSE, 0); 620 } 621 622 eloop.reader_table_changed = 0; 623 for (i = 0; i < eloop.reader_count; i++) { 624 WSANETWORKEVENTS events; 625 if (WSAEnumNetworkEvents(eloop.readers[i].sock, 626 eloop.readers[i].event, 627 &events) == 0 && 628 (events.lNetworkEvents & FD_READ)) { 629 eloop.readers[i].handler( 630 eloop.readers[i].sock, 631 eloop.readers[i].eloop_data, 632 eloop.readers[i].user_data); 633 if (eloop.reader_table_changed) 634 break; 635 } 636 } 637 } 638} 639 640 641void eloop_terminate(void) 642{ 643 eloop.terminate = 1; 644 SetEvent(eloop.term_event); 645} 646 647 648void eloop_destroy(void) 649{ 650 struct eloop_timeout *timeout, *prev; 651 652 dl_list_for_each_safe(timeout, prev, &eloop.timeout, 653 struct eloop_timeout, list) { 654 eloop_remove_timeout(timeout); 655 } 656 os_free(eloop.readers); 657 os_free(eloop.signals); 658 if (eloop.term_event) 659 CloseHandle(eloop.term_event); 660 os_free(eloop.handles); 661 eloop.handles = NULL; 662 os_free(eloop.events); 663 eloop.events = NULL; 664} 665 666 667int eloop_terminated(void) 668{ 669 return eloop.terminate; 670} 671 672 673void eloop_wait_for_read_sock(int sock) 674{ 675 WSAEVENT event; 676 677 event = WSACreateEvent(); 678 if (event == WSA_INVALID_EVENT) { 679 printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 680 return; 681 } 682 683 if (WSAEventSelect(sock, event, FD_READ)) { 684 printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 685 WSACloseEvent(event); 686 return ; 687 } 688 689 WaitForSingleObject(event, INFINITE); 690 WSAEventSelect(sock, event, 0); 691 WSACloseEvent(event); 692} 693