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