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 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 247 timeout = os_malloc(sizeof(*timeout)); 248 if (timeout == NULL) 249 return -1; 250 os_get_time(&timeout->time); 251 timeout->time.sec += secs; 252 timeout->time.usec += usecs; 253 while (timeout->time.usec >= 1000000) { 254 timeout->time.sec++; 255 timeout->time.usec -= 1000000; 256 } 257 timeout->eloop_data = eloop_data; 258 timeout->user_data = user_data; 259 timeout->handler = handler; 260 timeout->next = NULL; 261 262 if (eloop.timeout == NULL) { 263 eloop.timeout = timeout; 264 return 0; 265 } 266 267 prev = NULL; 268 tmp = eloop.timeout; 269 while (tmp != NULL) { 270 if (os_time_before(&timeout->time, &tmp->time)) 271 break; 272 prev = tmp; 273 tmp = tmp->next; 274 } 275 276 if (prev == NULL) { 277 timeout->next = eloop.timeout; 278 eloop.timeout = timeout; 279 } else { 280 timeout->next = prev->next; 281 prev->next = timeout; 282 } 283 284 return 0; 285 } 286 287 288 int eloop_cancel_timeout(eloop_timeout_handler handler, 289 void *eloop_data, void *user_data) 290 { 291 struct eloop_timeout *timeout, *prev, *next; 292 int removed = 0; 293 294 prev = NULL; 295 timeout = eloop.timeout; 296 while (timeout != NULL) { 297 next = timeout->next; 298 299 if (timeout->handler == handler && 300 (timeout->eloop_data == eloop_data || 301 eloop_data == ELOOP_ALL_CTX) && 302 (timeout->user_data == user_data || 303 user_data == ELOOP_ALL_CTX)) { 304 if (prev == NULL) 305 eloop.timeout = next; 306 else 307 prev->next = next; 308 os_free(timeout); 309 removed++; 310 } else 311 prev = timeout; 312 313 timeout = next; 314 } 315 316 return removed; 317 } 318 319 320 int eloop_is_timeout_registered(eloop_timeout_handler handler, 321 void *eloop_data, void *user_data) 322 { 323 struct eloop_timeout *tmp; 324 325 tmp = eloop.timeout; 326 while (tmp != NULL) { 327 if (tmp->handler == handler && 328 tmp->eloop_data == eloop_data && 329 tmp->user_data == user_data) 330 return 1; 331 332 tmp = tmp->next; 333 } 334 335 return 0; 336 } 337 338 339 /* TODO: replace with suitable signal handler */ 340 #if 0 341 static void eloop_handle_signal(int sig) 342 { 343 int i; 344 345 eloop.signaled++; 346 for (i = 0; i < eloop.signal_count; i++) { 347 if (eloop.signals[i].sig == sig) { 348 eloop.signals[i].signaled++; 349 break; 350 } 351 } 352 } 353 #endif 354 355 356 static void eloop_process_pending_signals(void) 357 { 358 int i; 359 360 if (eloop.signaled == 0) 361 return; 362 eloop.signaled = 0; 363 364 if (eloop.pending_terminate) { 365 eloop.pending_terminate = 0; 366 } 367 368 for (i = 0; i < eloop.signal_count; i++) { 369 if (eloop.signals[i].signaled) { 370 eloop.signals[i].signaled = 0; 371 eloop.signals[i].handler(eloop.signals[i].sig, 372 eloop.signals[i].user_data); 373 } 374 } 375 376 if (eloop.term_signal.signaled) { 377 eloop.term_signal.signaled = 0; 378 eloop.term_signal.handler(eloop.term_signal.sig, 379 eloop.term_signal.user_data); 380 } 381 } 382 383 384 int eloop_register_signal(int sig, eloop_signal_handler handler, 385 void *user_data) 386 { 387 struct eloop_signal *tmp; 388 389 tmp = os_realloc(eloop.signals, 390 (eloop.signal_count + 1) * 391 sizeof(struct eloop_signal)); 392 if (tmp == NULL) 393 return -1; 394 395 tmp[eloop.signal_count].sig = sig; 396 tmp[eloop.signal_count].user_data = user_data; 397 tmp[eloop.signal_count].handler = handler; 398 tmp[eloop.signal_count].signaled = 0; 399 eloop.signal_count++; 400 eloop.signals = tmp; 401 402 /* TODO: register signal handler */ 403 404 return 0; 405 } 406 407 408 #ifndef _WIN32_WCE 409 static BOOL eloop_handle_console_ctrl(DWORD type) 410 { 411 switch (type) { 412 case CTRL_C_EVENT: 413 case CTRL_BREAK_EVENT: 414 eloop.signaled++; 415 eloop.term_signal.signaled++; 416 SetEvent(eloop.term_event); 417 return TRUE; 418 default: 419 return FALSE; 420 } 421 } 422 #endif /* _WIN32_WCE */ 423 424 425 int eloop_register_signal_terminate(eloop_signal_handler handler, 426 void *user_data) 427 { 428 #ifndef _WIN32_WCE 429 if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 430 TRUE) == 0) { 431 printf("SetConsoleCtrlHandler() failed: %d\n", 432 (int) GetLastError()); 433 return -1; 434 } 435 #endif /* _WIN32_WCE */ 436 437 eloop.term_signal.handler = handler; 438 eloop.term_signal.user_data = user_data; 439 440 return 0; 441 } 442 443 444 int eloop_register_signal_reconfig(eloop_signal_handler handler, 445 void *user_data) 446 { 447 /* TODO */ 448 return 0; 449 } 450 451 452 void eloop_run(void) 453 { 454 struct os_time tv, now; 455 DWORD count, ret, timeout, err; 456 size_t i; 457 458 while (!eloop.terminate && 459 (eloop.timeout || eloop.reader_count > 0 || 460 eloop.event_count > 0)) { 461 tv.sec = tv.usec = 0; 462 if (eloop.timeout) { 463 os_get_time(&now); 464 if (os_time_before(&now, &eloop.timeout->time)) 465 os_time_sub(&eloop.timeout->time, &now, &tv); 466 } 467 468 count = 0; 469 for (i = 0; i < eloop.event_count; i++) 470 eloop.handles[count++] = eloop.events[i].event; 471 472 for (i = 0; i < eloop.reader_count; i++) 473 eloop.handles[count++] = eloop.readers[i].event; 474 475 if (eloop.term_event) 476 eloop.handles[count++] = eloop.term_event; 477 478 if (eloop.timeout) 479 timeout = tv.sec * 1000 + tv.usec / 1000; 480 else 481 timeout = INFINITE; 482 483 if (count > MAXIMUM_WAIT_OBJECTS) { 484 printf("WaitForMultipleObjects: Too many events: " 485 "%d > %d (ignoring extra events)\n", 486 (int) count, MAXIMUM_WAIT_OBJECTS); 487 count = MAXIMUM_WAIT_OBJECTS; 488 } 489 #ifdef _WIN32_WCE 490 ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 491 timeout); 492 #else /* _WIN32_WCE */ 493 ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 494 timeout, TRUE); 495 #endif /* _WIN32_WCE */ 496 err = GetLastError(); 497 498 eloop_process_pending_signals(); 499 500 /* check if some registered timeouts have occurred */ 501 if (eloop.timeout) { 502 struct eloop_timeout *tmp; 503 504 os_get_time(&now); 505 if (!os_time_before(&now, &eloop.timeout->time)) { 506 tmp = eloop.timeout; 507 eloop.timeout = eloop.timeout->next; 508 tmp->handler(tmp->eloop_data, 509 tmp->user_data); 510 os_free(tmp); 511 } 512 513 } 514 515 if (ret == WAIT_FAILED) { 516 printf("WaitForMultipleObjects(count=%d) failed: %d\n", 517 (int) count, (int) err); 518 os_sleep(1, 0); 519 continue; 520 } 521 522 #ifndef _WIN32_WCE 523 if (ret == WAIT_IO_COMPLETION) 524 continue; 525 #endif /* _WIN32_WCE */ 526 527 if (ret == WAIT_TIMEOUT) 528 continue; 529 530 while (ret >= WAIT_OBJECT_0 && 531 ret < WAIT_OBJECT_0 + eloop.event_count) { 532 eloop.events[ret].handler( 533 eloop.events[ret].eloop_data, 534 eloop.events[ret].user_data); 535 ret = WaitForMultipleObjects(eloop.event_count, 536 eloop.handles, FALSE, 0); 537 } 538 539 eloop.reader_table_changed = 0; 540 for (i = 0; i < eloop.reader_count; i++) { 541 WSANETWORKEVENTS events; 542 if (WSAEnumNetworkEvents(eloop.readers[i].sock, 543 eloop.readers[i].event, 544 &events) == 0 && 545 (events.lNetworkEvents & FD_READ)) { 546 eloop.readers[i].handler( 547 eloop.readers[i].sock, 548 eloop.readers[i].eloop_data, 549 eloop.readers[i].user_data); 550 if (eloop.reader_table_changed) 551 break; 552 } 553 } 554 } 555 } 556 557 558 void eloop_terminate(void) 559 { 560 eloop.terminate = 1; 561 SetEvent(eloop.term_event); 562 } 563 564 565 void eloop_destroy(void) 566 { 567 struct eloop_timeout *timeout, *prev; 568 569 timeout = eloop.timeout; 570 while (timeout != NULL) { 571 prev = timeout; 572 timeout = timeout->next; 573 os_free(prev); 574 } 575 os_free(eloop.readers); 576 os_free(eloop.signals); 577 if (eloop.term_event) 578 CloseHandle(eloop.term_event); 579 os_free(eloop.handles); 580 eloop.handles = NULL; 581 os_free(eloop.events); 582 eloop.events = NULL; 583 } 584 585 586 int eloop_terminated(void) 587 { 588 return eloop.terminate; 589 } 590 591 592 void eloop_wait_for_read_sock(int sock) 593 { 594 WSAEVENT event; 595 596 event = WSACreateEvent(); 597 if (event == WSA_INVALID_EVENT) { 598 printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 599 return; 600 } 601 602 if (WSAEventSelect(sock, event, FD_READ)) { 603 printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 604 WSACloseEvent(event); 605 return ; 606 } 607 608 WaitForSingleObject(event, INFINITE); 609 WSAEventSelect(sock, event, 0); 610 WSACloseEvent(event); 611 } 612