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