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