1209139Srpaulo/* 2209139Srpaulo * Event loop based on Windows events and WaitForMultipleObjects 3281806Srpaulo * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 4209139Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7209139Srpaulo */ 8209139Srpaulo 9209139Srpaulo#include "includes.h" 10209139Srpaulo#include <winsock2.h> 11209139Srpaulo 12209139Srpaulo#include "common.h" 13281806Srpaulo#include "list.h" 14209139Srpaulo#include "eloop.h" 15209139Srpaulo 16209139Srpaulo 17209139Srpaulostruct eloop_sock { 18209139Srpaulo int sock; 19209139Srpaulo void *eloop_data; 20209139Srpaulo void *user_data; 21209139Srpaulo eloop_sock_handler handler; 22209139Srpaulo WSAEVENT event; 23209139Srpaulo}; 24209139Srpaulo 25209139Srpaulostruct eloop_event { 26209139Srpaulo void *eloop_data; 27209139Srpaulo void *user_data; 28209139Srpaulo eloop_event_handler handler; 29209139Srpaulo HANDLE event; 30209139Srpaulo}; 31209139Srpaulo 32209139Srpaulostruct eloop_timeout { 33281806Srpaulo struct dl_list list; 34281806Srpaulo struct os_reltime time; 35209139Srpaulo void *eloop_data; 36209139Srpaulo void *user_data; 37209139Srpaulo eloop_timeout_handler handler; 38209139Srpaulo}; 39209139Srpaulo 40209139Srpaulostruct eloop_signal { 41209139Srpaulo int sig; 42209139Srpaulo void *user_data; 43209139Srpaulo eloop_signal_handler handler; 44209139Srpaulo int signaled; 45209139Srpaulo}; 46209139Srpaulo 47209139Srpaulostruct eloop_data { 48209139Srpaulo int max_sock; 49209139Srpaulo size_t reader_count; 50209139Srpaulo struct eloop_sock *readers; 51209139Srpaulo 52209139Srpaulo size_t event_count; 53209139Srpaulo struct eloop_event *events; 54209139Srpaulo 55281806Srpaulo struct dl_list timeout; 56209139Srpaulo 57209139Srpaulo int signal_count; 58209139Srpaulo struct eloop_signal *signals; 59209139Srpaulo int signaled; 60209139Srpaulo int pending_terminate; 61209139Srpaulo 62209139Srpaulo int terminate; 63209139Srpaulo int reader_table_changed; 64209139Srpaulo 65209139Srpaulo struct eloop_signal term_signal; 66209139Srpaulo HANDLE term_event; 67209139Srpaulo 68209139Srpaulo HANDLE *handles; 69209139Srpaulo size_t num_handles; 70209139Srpaulo}; 71209139Srpaulo 72209139Srpaulostatic struct eloop_data eloop; 73209139Srpaulo 74209139Srpaulo 75214734Srpauloint eloop_init(void) 76209139Srpaulo{ 77209139Srpaulo os_memset(&eloop, 0, sizeof(eloop)); 78281806Srpaulo dl_list_init(&eloop.timeout); 79209139Srpaulo eloop.num_handles = 1; 80209139Srpaulo eloop.handles = os_malloc(eloop.num_handles * 81209139Srpaulo sizeof(eloop.handles[0])); 82209139Srpaulo if (eloop.handles == NULL) 83209139Srpaulo return -1; 84209139Srpaulo 85209139Srpaulo eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); 86209139Srpaulo if (eloop.term_event == NULL) { 87209139Srpaulo printf("CreateEvent() failed: %d\n", 88209139Srpaulo (int) GetLastError()); 89209139Srpaulo os_free(eloop.handles); 90209139Srpaulo return -1; 91209139Srpaulo } 92209139Srpaulo 93209139Srpaulo return 0; 94209139Srpaulo} 95209139Srpaulo 96209139Srpaulo 97209139Srpaulostatic int eloop_prepare_handles(void) 98209139Srpaulo{ 99209139Srpaulo HANDLE *n; 100209139Srpaulo 101209139Srpaulo if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) 102209139Srpaulo return 0; 103252726Srpaulo n = os_realloc_array(eloop.handles, eloop.num_handles * 2, 104252726Srpaulo sizeof(eloop.handles[0])); 105209139Srpaulo if (n == NULL) 106209139Srpaulo return -1; 107209139Srpaulo eloop.handles = n; 108209139Srpaulo eloop.num_handles *= 2; 109209139Srpaulo return 0; 110209139Srpaulo} 111209139Srpaulo 112209139Srpaulo 113209139Srpauloint eloop_register_read_sock(int sock, eloop_sock_handler handler, 114209139Srpaulo void *eloop_data, void *user_data) 115209139Srpaulo{ 116209139Srpaulo WSAEVENT event; 117209139Srpaulo struct eloop_sock *tmp; 118209139Srpaulo 119209139Srpaulo if (eloop_prepare_handles()) 120209139Srpaulo return -1; 121209139Srpaulo 122209139Srpaulo event = WSACreateEvent(); 123209139Srpaulo if (event == WSA_INVALID_EVENT) { 124209139Srpaulo printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 125209139Srpaulo return -1; 126209139Srpaulo } 127209139Srpaulo 128209139Srpaulo if (WSAEventSelect(sock, event, FD_READ)) { 129209139Srpaulo printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 130209139Srpaulo WSACloseEvent(event); 131209139Srpaulo return -1; 132209139Srpaulo } 133252726Srpaulo tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1, 134252726Srpaulo sizeof(struct eloop_sock)); 135209139Srpaulo if (tmp == NULL) { 136209139Srpaulo WSAEventSelect(sock, event, 0); 137209139Srpaulo WSACloseEvent(event); 138209139Srpaulo return -1; 139209139Srpaulo } 140209139Srpaulo 141209139Srpaulo tmp[eloop.reader_count].sock = sock; 142209139Srpaulo tmp[eloop.reader_count].eloop_data = eloop_data; 143209139Srpaulo tmp[eloop.reader_count].user_data = user_data; 144209139Srpaulo tmp[eloop.reader_count].handler = handler; 145209139Srpaulo tmp[eloop.reader_count].event = event; 146209139Srpaulo eloop.reader_count++; 147209139Srpaulo eloop.readers = tmp; 148209139Srpaulo if (sock > eloop.max_sock) 149209139Srpaulo eloop.max_sock = sock; 150209139Srpaulo eloop.reader_table_changed = 1; 151209139Srpaulo 152209139Srpaulo return 0; 153209139Srpaulo} 154209139Srpaulo 155209139Srpaulo 156209139Srpaulovoid eloop_unregister_read_sock(int sock) 157209139Srpaulo{ 158209139Srpaulo size_t i; 159209139Srpaulo 160209139Srpaulo if (eloop.readers == NULL || eloop.reader_count == 0) 161209139Srpaulo return; 162209139Srpaulo 163209139Srpaulo for (i = 0; i < eloop.reader_count; i++) { 164209139Srpaulo if (eloop.readers[i].sock == sock) 165209139Srpaulo break; 166209139Srpaulo } 167209139Srpaulo if (i == eloop.reader_count) 168209139Srpaulo return; 169209139Srpaulo 170209139Srpaulo WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); 171209139Srpaulo WSACloseEvent(eloop.readers[i].event); 172209139Srpaulo 173209139Srpaulo if (i != eloop.reader_count - 1) { 174209139Srpaulo os_memmove(&eloop.readers[i], &eloop.readers[i + 1], 175209139Srpaulo (eloop.reader_count - i - 1) * 176209139Srpaulo sizeof(struct eloop_sock)); 177209139Srpaulo } 178209139Srpaulo eloop.reader_count--; 179209139Srpaulo eloop.reader_table_changed = 1; 180209139Srpaulo} 181209139Srpaulo 182209139Srpaulo 183209139Srpauloint eloop_register_event(void *event, size_t event_size, 184209139Srpaulo eloop_event_handler handler, 185209139Srpaulo void *eloop_data, void *user_data) 186209139Srpaulo{ 187209139Srpaulo struct eloop_event *tmp; 188209139Srpaulo HANDLE h = event; 189209139Srpaulo 190209139Srpaulo if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) 191209139Srpaulo return -1; 192209139Srpaulo 193209139Srpaulo if (eloop_prepare_handles()) 194209139Srpaulo return -1; 195209139Srpaulo 196252726Srpaulo tmp = os_realloc_array(eloop.events, eloop.event_count + 1, 197252726Srpaulo sizeof(struct eloop_event)); 198209139Srpaulo if (tmp == NULL) 199209139Srpaulo return -1; 200209139Srpaulo 201209139Srpaulo tmp[eloop.event_count].eloop_data = eloop_data; 202209139Srpaulo tmp[eloop.event_count].user_data = user_data; 203209139Srpaulo tmp[eloop.event_count].handler = handler; 204209139Srpaulo tmp[eloop.event_count].event = h; 205209139Srpaulo eloop.event_count++; 206209139Srpaulo eloop.events = tmp; 207209139Srpaulo 208209139Srpaulo return 0; 209209139Srpaulo} 210209139Srpaulo 211209139Srpaulo 212209139Srpaulovoid eloop_unregister_event(void *event, size_t event_size) 213209139Srpaulo{ 214209139Srpaulo size_t i; 215209139Srpaulo HANDLE h = event; 216209139Srpaulo 217209139Srpaulo if (eloop.events == NULL || eloop.event_count == 0 || 218209139Srpaulo event_size != sizeof(HANDLE)) 219209139Srpaulo return; 220209139Srpaulo 221209139Srpaulo for (i = 0; i < eloop.event_count; i++) { 222209139Srpaulo if (eloop.events[i].event == h) 223209139Srpaulo break; 224209139Srpaulo } 225209139Srpaulo if (i == eloop.event_count) 226209139Srpaulo return; 227209139Srpaulo 228209139Srpaulo if (i != eloop.event_count - 1) { 229209139Srpaulo os_memmove(&eloop.events[i], &eloop.events[i + 1], 230209139Srpaulo (eloop.event_count - i - 1) * 231209139Srpaulo sizeof(struct eloop_event)); 232209139Srpaulo } 233209139Srpaulo eloop.event_count--; 234209139Srpaulo} 235209139Srpaulo 236209139Srpaulo 237209139Srpauloint eloop_register_timeout(unsigned int secs, unsigned int usecs, 238209139Srpaulo eloop_timeout_handler handler, 239209139Srpaulo void *eloop_data, void *user_data) 240209139Srpaulo{ 241281806Srpaulo struct eloop_timeout *timeout, *tmp; 242252726Srpaulo os_time_t now_sec; 243209139Srpaulo 244281806Srpaulo timeout = os_zalloc(sizeof(*timeout)); 245209139Srpaulo if (timeout == NULL) 246209139Srpaulo return -1; 247281806Srpaulo if (os_get_reltime(&timeout->time) < 0) { 248281806Srpaulo os_free(timeout); 249281806Srpaulo return -1; 250281806Srpaulo } 251252726Srpaulo now_sec = timeout->time.sec; 252209139Srpaulo timeout->time.sec += secs; 253252726Srpaulo if (timeout->time.sec < now_sec) { 254252726Srpaulo /* 255252726Srpaulo * Integer overflow - assume long enough timeout to be assumed 256252726Srpaulo * to be infinite, i.e., the timeout would never happen. 257252726Srpaulo */ 258252726Srpaulo wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " 259252726Srpaulo "ever happen - ignore it", secs); 260252726Srpaulo os_free(timeout); 261252726Srpaulo return 0; 262252726Srpaulo } 263209139Srpaulo timeout->time.usec += usecs; 264209139Srpaulo while (timeout->time.usec >= 1000000) { 265209139Srpaulo timeout->time.sec++; 266209139Srpaulo timeout->time.usec -= 1000000; 267209139Srpaulo } 268209139Srpaulo timeout->eloop_data = eloop_data; 269209139Srpaulo timeout->user_data = user_data; 270209139Srpaulo timeout->handler = handler; 271209139Srpaulo 272281806Srpaulo /* Maintain timeouts in order of increasing time */ 273281806Srpaulo dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 274281806Srpaulo if (os_reltime_before(&timeout->time, &tmp->time)) { 275281806Srpaulo dl_list_add(tmp->list.prev, &timeout->list); 276281806Srpaulo return 0; 277281806Srpaulo } 278209139Srpaulo } 279281806Srpaulo dl_list_add_tail(&eloop.timeout, &timeout->list); 280209139Srpaulo 281281806Srpaulo return 0; 282281806Srpaulo} 283209139Srpaulo 284209139Srpaulo 285281806Srpaulostatic void eloop_remove_timeout(struct eloop_timeout *timeout) 286281806Srpaulo{ 287281806Srpaulo dl_list_del(&timeout->list); 288281806Srpaulo os_free(timeout); 289209139Srpaulo} 290209139Srpaulo 291209139Srpaulo 292209139Srpauloint eloop_cancel_timeout(eloop_timeout_handler handler, 293209139Srpaulo void *eloop_data, void *user_data) 294209139Srpaulo{ 295281806Srpaulo struct eloop_timeout *timeout, *prev; 296209139Srpaulo int removed = 0; 297209139Srpaulo 298281806Srpaulo dl_list_for_each_safe(timeout, prev, &eloop.timeout, 299281806Srpaulo struct eloop_timeout, list) { 300209139Srpaulo if (timeout->handler == handler && 301209139Srpaulo (timeout->eloop_data == eloop_data || 302209139Srpaulo eloop_data == ELOOP_ALL_CTX) && 303209139Srpaulo (timeout->user_data == user_data || 304209139Srpaulo user_data == ELOOP_ALL_CTX)) { 305281806Srpaulo eloop_remove_timeout(timeout); 306209139Srpaulo removed++; 307281806Srpaulo } 308209139Srpaulo } 309209139Srpaulo 310209139Srpaulo return removed; 311209139Srpaulo} 312209139Srpaulo 313209139Srpaulo 314281806Srpauloint eloop_cancel_timeout_one(eloop_timeout_handler handler, 315281806Srpaulo void *eloop_data, void *user_data, 316281806Srpaulo struct os_reltime *remaining) 317281806Srpaulo{ 318281806Srpaulo struct eloop_timeout *timeout, *prev; 319281806Srpaulo int removed = 0; 320281806Srpaulo struct os_reltime now; 321281806Srpaulo 322281806Srpaulo os_get_reltime(&now); 323281806Srpaulo remaining->sec = remaining->usec = 0; 324281806Srpaulo 325281806Srpaulo dl_list_for_each_safe(timeout, prev, &eloop.timeout, 326281806Srpaulo struct eloop_timeout, list) { 327281806Srpaulo if (timeout->handler == handler && 328281806Srpaulo (timeout->eloop_data == eloop_data) && 329281806Srpaulo (timeout->user_data == user_data)) { 330281806Srpaulo removed = 1; 331281806Srpaulo if (os_reltime_before(&now, &timeout->time)) 332281806Srpaulo os_reltime_sub(&timeout->time, &now, remaining); 333281806Srpaulo eloop_remove_timeout(timeout); 334281806Srpaulo break; 335281806Srpaulo } 336281806Srpaulo } 337281806Srpaulo return removed; 338281806Srpaulo} 339281806Srpaulo 340281806Srpaulo 341209139Srpauloint eloop_is_timeout_registered(eloop_timeout_handler handler, 342209139Srpaulo void *eloop_data, void *user_data) 343209139Srpaulo{ 344209139Srpaulo struct eloop_timeout *tmp; 345209139Srpaulo 346281806Srpaulo dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 347209139Srpaulo if (tmp->handler == handler && 348209139Srpaulo tmp->eloop_data == eloop_data && 349209139Srpaulo tmp->user_data == user_data) 350209139Srpaulo return 1; 351209139Srpaulo } 352209139Srpaulo 353209139Srpaulo return 0; 354209139Srpaulo} 355209139Srpaulo 356209139Srpaulo 357281806Srpauloint eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, 358281806Srpaulo eloop_timeout_handler handler, void *eloop_data, 359281806Srpaulo void *user_data) 360281806Srpaulo{ 361281806Srpaulo struct os_reltime now, requested, remaining; 362281806Srpaulo struct eloop_timeout *tmp; 363281806Srpaulo 364281806Srpaulo dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 365281806Srpaulo if (tmp->handler == handler && 366281806Srpaulo tmp->eloop_data == eloop_data && 367281806Srpaulo tmp->user_data == user_data) { 368281806Srpaulo requested.sec = req_secs; 369281806Srpaulo requested.usec = req_usecs; 370281806Srpaulo os_get_reltime(&now); 371281806Srpaulo os_reltime_sub(&tmp->time, &now, &remaining); 372281806Srpaulo if (os_reltime_before(&requested, &remaining)) { 373281806Srpaulo eloop_cancel_timeout(handler, eloop_data, 374281806Srpaulo user_data); 375281806Srpaulo eloop_register_timeout(requested.sec, 376281806Srpaulo requested.usec, 377281806Srpaulo handler, eloop_data, 378281806Srpaulo user_data); 379281806Srpaulo return 1; 380281806Srpaulo } 381281806Srpaulo return 0; 382281806Srpaulo } 383281806Srpaulo } 384281806Srpaulo 385281806Srpaulo return -1; 386281806Srpaulo} 387281806Srpaulo 388281806Srpaulo 389281806Srpauloint eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, 390281806Srpaulo eloop_timeout_handler handler, void *eloop_data, 391281806Srpaulo void *user_data) 392281806Srpaulo{ 393281806Srpaulo struct os_reltime now, requested, remaining; 394281806Srpaulo struct eloop_timeout *tmp; 395281806Srpaulo 396281806Srpaulo dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 397281806Srpaulo if (tmp->handler == handler && 398281806Srpaulo tmp->eloop_data == eloop_data && 399281806Srpaulo tmp->user_data == user_data) { 400281806Srpaulo requested.sec = req_secs; 401281806Srpaulo requested.usec = req_usecs; 402281806Srpaulo os_get_reltime(&now); 403281806Srpaulo os_reltime_sub(&tmp->time, &now, &remaining); 404281806Srpaulo if (os_reltime_before(&remaining, &requested)) { 405281806Srpaulo eloop_cancel_timeout(handler, eloop_data, 406281806Srpaulo user_data); 407281806Srpaulo eloop_register_timeout(requested.sec, 408281806Srpaulo requested.usec, 409281806Srpaulo handler, eloop_data, 410281806Srpaulo user_data); 411281806Srpaulo return 1; 412281806Srpaulo } 413281806Srpaulo return 0; 414281806Srpaulo } 415281806Srpaulo } 416281806Srpaulo 417281806Srpaulo return -1; 418281806Srpaulo} 419281806Srpaulo 420281806Srpaulo 421209139Srpaulo/* TODO: replace with suitable signal handler */ 422209139Srpaulo#if 0 423209139Srpaulostatic void eloop_handle_signal(int sig) 424209139Srpaulo{ 425209139Srpaulo int i; 426209139Srpaulo 427209139Srpaulo eloop.signaled++; 428209139Srpaulo for (i = 0; i < eloop.signal_count; i++) { 429209139Srpaulo if (eloop.signals[i].sig == sig) { 430209139Srpaulo eloop.signals[i].signaled++; 431209139Srpaulo break; 432209139Srpaulo } 433209139Srpaulo } 434209139Srpaulo} 435209139Srpaulo#endif 436209139Srpaulo 437209139Srpaulo 438209139Srpaulostatic void eloop_process_pending_signals(void) 439209139Srpaulo{ 440209139Srpaulo int i; 441209139Srpaulo 442209139Srpaulo if (eloop.signaled == 0) 443209139Srpaulo return; 444209139Srpaulo eloop.signaled = 0; 445209139Srpaulo 446209139Srpaulo if (eloop.pending_terminate) { 447209139Srpaulo eloop.pending_terminate = 0; 448209139Srpaulo } 449209139Srpaulo 450209139Srpaulo for (i = 0; i < eloop.signal_count; i++) { 451209139Srpaulo if (eloop.signals[i].signaled) { 452209139Srpaulo eloop.signals[i].signaled = 0; 453209139Srpaulo eloop.signals[i].handler(eloop.signals[i].sig, 454209139Srpaulo eloop.signals[i].user_data); 455209139Srpaulo } 456209139Srpaulo } 457209139Srpaulo 458209139Srpaulo if (eloop.term_signal.signaled) { 459209139Srpaulo eloop.term_signal.signaled = 0; 460209139Srpaulo eloop.term_signal.handler(eloop.term_signal.sig, 461209139Srpaulo eloop.term_signal.user_data); 462209139Srpaulo } 463209139Srpaulo} 464209139Srpaulo 465209139Srpaulo 466209139Srpauloint eloop_register_signal(int sig, eloop_signal_handler handler, 467209139Srpaulo void *user_data) 468209139Srpaulo{ 469209139Srpaulo struct eloop_signal *tmp; 470209139Srpaulo 471252726Srpaulo tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 472252726Srpaulo sizeof(struct eloop_signal)); 473209139Srpaulo if (tmp == NULL) 474209139Srpaulo return -1; 475209139Srpaulo 476209139Srpaulo tmp[eloop.signal_count].sig = sig; 477209139Srpaulo tmp[eloop.signal_count].user_data = user_data; 478209139Srpaulo tmp[eloop.signal_count].handler = handler; 479209139Srpaulo tmp[eloop.signal_count].signaled = 0; 480209139Srpaulo eloop.signal_count++; 481209139Srpaulo eloop.signals = tmp; 482209139Srpaulo 483209139Srpaulo /* TODO: register signal handler */ 484209139Srpaulo 485209139Srpaulo return 0; 486209139Srpaulo} 487209139Srpaulo 488209139Srpaulo 489209139Srpaulo#ifndef _WIN32_WCE 490209139Srpaulostatic BOOL eloop_handle_console_ctrl(DWORD type) 491209139Srpaulo{ 492209139Srpaulo switch (type) { 493209139Srpaulo case CTRL_C_EVENT: 494209139Srpaulo case CTRL_BREAK_EVENT: 495209139Srpaulo eloop.signaled++; 496209139Srpaulo eloop.term_signal.signaled++; 497209139Srpaulo SetEvent(eloop.term_event); 498209139Srpaulo return TRUE; 499209139Srpaulo default: 500209139Srpaulo return FALSE; 501209139Srpaulo } 502209139Srpaulo} 503209139Srpaulo#endif /* _WIN32_WCE */ 504209139Srpaulo 505209139Srpaulo 506209139Srpauloint eloop_register_signal_terminate(eloop_signal_handler handler, 507209139Srpaulo void *user_data) 508209139Srpaulo{ 509209139Srpaulo#ifndef _WIN32_WCE 510209139Srpaulo if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 511209139Srpaulo TRUE) == 0) { 512209139Srpaulo printf("SetConsoleCtrlHandler() failed: %d\n", 513209139Srpaulo (int) GetLastError()); 514209139Srpaulo return -1; 515209139Srpaulo } 516209139Srpaulo#endif /* _WIN32_WCE */ 517209139Srpaulo 518209139Srpaulo eloop.term_signal.handler = handler; 519209139Srpaulo eloop.term_signal.user_data = user_data; 520209139Srpaulo 521209139Srpaulo return 0; 522209139Srpaulo} 523209139Srpaulo 524209139Srpaulo 525209139Srpauloint eloop_register_signal_reconfig(eloop_signal_handler handler, 526209139Srpaulo void *user_data) 527209139Srpaulo{ 528209139Srpaulo /* TODO */ 529209139Srpaulo return 0; 530209139Srpaulo} 531209139Srpaulo 532209139Srpaulo 533209139Srpaulovoid eloop_run(void) 534209139Srpaulo{ 535281806Srpaulo struct os_reltime tv, now; 536281806Srpaulo DWORD count, ret, timeout_val, err; 537209139Srpaulo size_t i; 538209139Srpaulo 539209139Srpaulo while (!eloop.terminate && 540281806Srpaulo (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 || 541209139Srpaulo eloop.event_count > 0)) { 542281806Srpaulo struct eloop_timeout *timeout; 543209139Srpaulo tv.sec = tv.usec = 0; 544281806Srpaulo timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 545281806Srpaulo list); 546281806Srpaulo if (timeout) { 547281806Srpaulo os_get_reltime(&now); 548281806Srpaulo if (os_reltime_before(&now, &timeout->time)) 549281806Srpaulo os_reltime_sub(&timeout->time, &now, &tv); 550209139Srpaulo } 551209139Srpaulo 552209139Srpaulo count = 0; 553209139Srpaulo for (i = 0; i < eloop.event_count; i++) 554209139Srpaulo eloop.handles[count++] = eloop.events[i].event; 555209139Srpaulo 556209139Srpaulo for (i = 0; i < eloop.reader_count; i++) 557209139Srpaulo eloop.handles[count++] = eloop.readers[i].event; 558209139Srpaulo 559209139Srpaulo if (eloop.term_event) 560209139Srpaulo eloop.handles[count++] = eloop.term_event; 561209139Srpaulo 562281806Srpaulo if (timeout) 563281806Srpaulo timeout_val = tv.sec * 1000 + tv.usec / 1000; 564209139Srpaulo else 565281806Srpaulo timeout_val = INFINITE; 566209139Srpaulo 567209139Srpaulo if (count > MAXIMUM_WAIT_OBJECTS) { 568209139Srpaulo printf("WaitForMultipleObjects: Too many events: " 569209139Srpaulo "%d > %d (ignoring extra events)\n", 570209139Srpaulo (int) count, MAXIMUM_WAIT_OBJECTS); 571209139Srpaulo count = MAXIMUM_WAIT_OBJECTS; 572209139Srpaulo } 573209139Srpaulo#ifdef _WIN32_WCE 574209139Srpaulo ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 575281806Srpaulo timeout_val); 576209139Srpaulo#else /* _WIN32_WCE */ 577209139Srpaulo ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 578281806Srpaulo timeout_val, TRUE); 579209139Srpaulo#endif /* _WIN32_WCE */ 580209139Srpaulo err = GetLastError(); 581209139Srpaulo 582209139Srpaulo eloop_process_pending_signals(); 583209139Srpaulo 584209139Srpaulo /* check if some registered timeouts have occurred */ 585281806Srpaulo timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 586281806Srpaulo list); 587281806Srpaulo if (timeout) { 588281806Srpaulo os_get_reltime(&now); 589281806Srpaulo if (!os_reltime_before(&now, &timeout->time)) { 590281806Srpaulo void *eloop_data = timeout->eloop_data; 591281806Srpaulo void *user_data = timeout->user_data; 592281806Srpaulo eloop_timeout_handler handler = 593281806Srpaulo timeout->handler; 594281806Srpaulo eloop_remove_timeout(timeout); 595281806Srpaulo handler(eloop_data, user_data); 596209139Srpaulo } 597209139Srpaulo 598209139Srpaulo } 599209139Srpaulo 600209139Srpaulo if (ret == WAIT_FAILED) { 601209139Srpaulo printf("WaitForMultipleObjects(count=%d) failed: %d\n", 602209139Srpaulo (int) count, (int) err); 603209139Srpaulo os_sleep(1, 0); 604209139Srpaulo continue; 605209139Srpaulo } 606209139Srpaulo 607209139Srpaulo#ifndef _WIN32_WCE 608209139Srpaulo if (ret == WAIT_IO_COMPLETION) 609209139Srpaulo continue; 610209139Srpaulo#endif /* _WIN32_WCE */ 611209139Srpaulo 612209139Srpaulo if (ret == WAIT_TIMEOUT) 613209139Srpaulo continue; 614209139Srpaulo 615209139Srpaulo while (ret >= WAIT_OBJECT_0 && 616209139Srpaulo ret < WAIT_OBJECT_0 + eloop.event_count) { 617209139Srpaulo eloop.events[ret].handler( 618209139Srpaulo eloop.events[ret].eloop_data, 619209139Srpaulo eloop.events[ret].user_data); 620209139Srpaulo ret = WaitForMultipleObjects(eloop.event_count, 621209139Srpaulo eloop.handles, FALSE, 0); 622209139Srpaulo } 623209139Srpaulo 624209139Srpaulo eloop.reader_table_changed = 0; 625209139Srpaulo for (i = 0; i < eloop.reader_count; i++) { 626209139Srpaulo WSANETWORKEVENTS events; 627209139Srpaulo if (WSAEnumNetworkEvents(eloop.readers[i].sock, 628209139Srpaulo eloop.readers[i].event, 629209139Srpaulo &events) == 0 && 630209139Srpaulo (events.lNetworkEvents & FD_READ)) { 631209139Srpaulo eloop.readers[i].handler( 632209139Srpaulo eloop.readers[i].sock, 633209139Srpaulo eloop.readers[i].eloop_data, 634209139Srpaulo eloop.readers[i].user_data); 635209139Srpaulo if (eloop.reader_table_changed) 636209139Srpaulo break; 637209139Srpaulo } 638209139Srpaulo } 639209139Srpaulo } 640209139Srpaulo} 641209139Srpaulo 642209139Srpaulo 643209139Srpaulovoid eloop_terminate(void) 644209139Srpaulo{ 645209139Srpaulo eloop.terminate = 1; 646209139Srpaulo SetEvent(eloop.term_event); 647209139Srpaulo} 648209139Srpaulo 649209139Srpaulo 650209139Srpaulovoid eloop_destroy(void) 651209139Srpaulo{ 652209139Srpaulo struct eloop_timeout *timeout, *prev; 653209139Srpaulo 654281806Srpaulo dl_list_for_each_safe(timeout, prev, &eloop.timeout, 655281806Srpaulo struct eloop_timeout, list) { 656281806Srpaulo eloop_remove_timeout(timeout); 657209139Srpaulo } 658209139Srpaulo os_free(eloop.readers); 659209139Srpaulo os_free(eloop.signals); 660209139Srpaulo if (eloop.term_event) 661209139Srpaulo CloseHandle(eloop.term_event); 662209139Srpaulo os_free(eloop.handles); 663209139Srpaulo eloop.handles = NULL; 664209139Srpaulo os_free(eloop.events); 665209139Srpaulo eloop.events = NULL; 666209139Srpaulo} 667209139Srpaulo 668209139Srpaulo 669209139Srpauloint eloop_terminated(void) 670209139Srpaulo{ 671209139Srpaulo return eloop.terminate; 672209139Srpaulo} 673209139Srpaulo 674209139Srpaulo 675209139Srpaulovoid eloop_wait_for_read_sock(int sock) 676209139Srpaulo{ 677209139Srpaulo WSAEVENT event; 678209139Srpaulo 679209139Srpaulo event = WSACreateEvent(); 680209139Srpaulo if (event == WSA_INVALID_EVENT) { 681209139Srpaulo printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 682209139Srpaulo return; 683209139Srpaulo } 684209139Srpaulo 685209139Srpaulo if (WSAEventSelect(sock, event, FD_READ)) { 686209139Srpaulo printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 687209139Srpaulo WSACloseEvent(event); 688209139Srpaulo return ; 689209139Srpaulo } 690209139Srpaulo 691209139Srpaulo WaitForSingleObject(event, INFINITE); 692209139Srpaulo WSAEventSelect(sock, event, 0); 693209139Srpaulo WSACloseEvent(event); 694209139Srpaulo} 695337817Scy 696337817Scy 697337817Scyint eloop_sock_requeue(void) 698337817Scy{ 699337817Scy return 0; 700337817Scy} 701