eloop_win.c revision 252726
199193Sjmallett/* 299193Sjmallett * Event loop based on Windows events and WaitForMultipleObjects 399193Sjmallett * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> 499193Sjmallett * 599193Sjmallett * This software may be distributed under the terms of the BSD license. 699193Sjmallett * See README for more details. 799193Sjmallett */ 899193Sjmallett 999193Sjmallett#include "includes.h" 1099193Sjmallett#include <winsock2.h> 1199193Sjmallett 1299193Sjmallett#include "common.h" 1399193Sjmallett#include "eloop.h" 1499193Sjmallett 1599193Sjmallett 1699193Sjmallettstruct eloop_sock { 1799193Sjmallett int sock; 1899193Sjmallett void *eloop_data; 1999193Sjmallett void *user_data; 2099193Sjmallett eloop_sock_handler handler; 2199193Sjmallett WSAEVENT event; 2299193Sjmallett}; 2399193Sjmallett 2499193Sjmallettstruct eloop_event { 2599193Sjmallett void *eloop_data; 2699193Sjmallett void *user_data; 2799193Sjmallett eloop_event_handler handler; 2899193Sjmallett HANDLE event; 2999193Sjmallett}; 3099193Sjmallett 3199193Sjmallettstruct eloop_timeout { 3299193Sjmallett struct os_time time; 3399193Sjmallett void *eloop_data; 3499193Sjmallett void *user_data; 3599193Sjmallett eloop_timeout_handler handler; 3699193Sjmallett struct eloop_timeout *next; 3799193Sjmallett}; 3899193Sjmallett 3999193Sjmallettstruct eloop_signal { 4099193Sjmallett int sig; 4199193Sjmallett void *user_data; 42109506Sjmallett eloop_signal_handler handler; 43109506Sjmallett int signaled; 4499193Sjmallett}; 4599193Sjmallett 4699193Sjmallettstruct eloop_data { 4799193Sjmallett int max_sock; 4899193Sjmallett size_t reader_count; 4999193Sjmallett struct eloop_sock *readers; 5099193Sjmallett 51109506Sjmallett size_t event_count; 52109506Sjmallett struct eloop_event *events; 53110066Sjmallett 54110066Sjmallett struct eloop_timeout *timeout; 55109506Sjmallett 5699193Sjmallett int signal_count; 5799193Sjmallett struct eloop_signal *signals; 5899193Sjmallett int signaled; 59109462Sjmallett int pending_terminate; 6099193Sjmallett 6199193Sjmallett int terminate; 6299193Sjmallett int reader_table_changed; 6399193Sjmallett 6499193Sjmallett struct eloop_signal term_signal; 65109506Sjmallett HANDLE term_event; 66109506Sjmallett 67109506Sjmallett HANDLE *handles; 68109506Sjmallett size_t num_handles; 69207141Sjeff}; 70207141Sjeff 71207141Sjeffstatic struct eloop_data eloop; 72207141Sjeff 73116084Sjmallett 7499193Sjmallettint eloop_init(void) 7599193Sjmallett{ 7699193Sjmallett os_memset(&eloop, 0, sizeof(eloop)); 7799193Sjmallett eloop.num_handles = 1; 7899193Sjmallett eloop.handles = os_malloc(eloop.num_handles * 79109755Sjmallett sizeof(eloop.handles[0])); 80116084Sjmallett if (eloop.handles == NULL) 81109755Sjmallett return -1; 82109755Sjmallett 83109755Sjmallett eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); 84116084Sjmallett if (eloop.term_event == NULL) { 85109755Sjmallett printf("CreateEvent() failed: %d\n", 86116084Sjmallett (int) GetLastError()); 87109755Sjmallett os_free(eloop.handles); 88109755Sjmallett return -1; 89109755Sjmallett } 90109755Sjmallett 91109755Sjmallett return 0; 92109506Sjmallett} 93109506Sjmallett 94167625Spjd 95109506Sjmallettstatic int eloop_prepare_handles(void) 96109506Sjmallett{ 97167625Spjd HANDLE *n; 9899193Sjmallett 99109462Sjmallett if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) 10099222Sjmallett return 0; 101109506Sjmallett n = os_realloc_array(eloop.handles, eloop.num_handles * 2, 102167625Spjd sizeof(eloop.handles[0])); 103109506Sjmallett if (n == NULL) 104109506Sjmallett return -1; 105109506Sjmallett eloop.handles = n; 106109506Sjmallett eloop.num_handles *= 2; 107109506Sjmallett return 0; 108167625Spjd} 109167625Spjd 110167625Spjd 111167625Spjdint eloop_register_read_sock(int sock, eloop_sock_handler handler, 112167625Spjd void *eloop_data, void *user_data) 113167625Spjd{ 114167625Spjd WSAEVENT event; 115194030Sjmallett struct eloop_sock *tmp; 116194030Sjmallett 117194030Sjmallett if (eloop_prepare_handles()) 118194030Sjmallett return -1; 119167625Spjd 120167625Spjd event = WSACreateEvent(); 121167625Spjd if (event == WSA_INVALID_EVENT) { 122167625Spjd printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 123167625Spjd return -1; 124167625Spjd } 125167625Spjd 126167625Spjd if (WSAEventSelect(sock, event, FD_READ)) { 127167625Spjd printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 128167625Spjd WSACloseEvent(event); 129167625Spjd return -1; 130167625Spjd } 131167625Spjd tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1, 132167625Spjd sizeof(struct eloop_sock)); 133167625Spjd if (tmp == NULL) { 134167625Spjd WSAEventSelect(sock, event, 0); 135167625Spjd WSACloseEvent(event); 136167625Spjd return -1; 137167625Spjd } 138167625Spjd 139167625Spjd tmp[eloop.reader_count].sock = sock; 140167625Spjd tmp[eloop.reader_count].eloop_data = eloop_data; 141167625Spjd tmp[eloop.reader_count].user_data = user_data; 142167625Spjd tmp[eloop.reader_count].handler = handler; 143167625Spjd tmp[eloop.reader_count].event = event; 144109506Sjmallett eloop.reader_count++; 145116084Sjmallett eloop.readers = tmp; 146109506Sjmallett if (sock > eloop.max_sock) 14799193Sjmallett eloop.max_sock = sock; 14899193Sjmallett eloop.reader_table_changed = 1; 149109506Sjmallett 150116084Sjmallett return 0; 15199193Sjmallett} 15299193Sjmallett 15399193Sjmallett 154109509Sjmallettvoid eloop_unregister_read_sock(int sock) 15599193Sjmallett{ 15699193Sjmallett size_t i; 15799823Sjmallett 15899823Sjmallett if (eloop.readers == NULL || eloop.reader_count == 0) 159109518Sjmallett return; 160109506Sjmallett 161101687Sjmallett for (i = 0; i < eloop.reader_count; i++) { 162105737Sjmallett if (eloop.readers[i].sock == sock) 163207141Sjeff break; 16499193Sjmallett } 165109506Sjmallett if (i == eloop.reader_count) 166109506Sjmallett return; 167109506Sjmallett 168109506Sjmallett WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); 169116084Sjmallett WSACloseEvent(eloop.readers[i].event); 170109506Sjmallett 171109506Sjmallett if (i != eloop.reader_count - 1) { 172109506Sjmallett os_memmove(&eloop.readers[i], &eloop.readers[i + 1], 173109506Sjmallett (eloop.reader_count - i - 1) * 174109506Sjmallett sizeof(struct eloop_sock)); 175116084Sjmallett } 17699193Sjmallett eloop.reader_count--; 177110066Sjmallett eloop.reader_table_changed = 1; 178110066Sjmallett} 179110066Sjmallett 180110066Sjmallett 181110066Sjmallettint eloop_register_event(void *event, size_t event_size, 182110066Sjmallett eloop_event_handler handler, 183110066Sjmallett void *eloop_data, void *user_data) 184116084Sjmallett{ 185110066Sjmallett struct eloop_event *tmp; 186112730Sjmallett HANDLE h = event; 187110066Sjmallett 188110066Sjmallett if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) 189110066Sjmallett return -1; 190110066Sjmallett 191116084Sjmallett if (eloop_prepare_handles()) 192110066Sjmallett return -1; 193110066Sjmallett 194110066Sjmallett tmp = os_realloc_array(eloop.events, eloop.event_count + 1, 195110066Sjmallett sizeof(struct eloop_event)); 196116084Sjmallett if (tmp == NULL) 197110066Sjmallett 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 210void 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 235int 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 294int 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 326int 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 347static 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 362static 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 390int eloop_register_signal(int sig, eloop_signal_handler handler, 391 void *user_data) 392{ 393 struct eloop_signal *tmp; 394 395 tmp = os_realloc_array(eloop.signals, 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 414static 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 430int 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 449int eloop_register_signal_reconfig(eloop_signal_handler handler, 450 void *user_data) 451{ 452 /* TODO */ 453 return 0; 454} 455 456 457void 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 563void eloop_terminate(void) 564{ 565 eloop.terminate = 1; 566 SetEvent(eloop.term_event); 567} 568 569 570void 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 591int eloop_terminated(void) 592{ 593 return eloop.terminate; 594} 595 596 597void 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