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