18dbcf02cSchristos /* 28dbcf02cSchristos * Event loop based on Windows events and WaitForMultipleObjects 33c260e60Schristos * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 48dbcf02cSchristos * 5e604d861Schristos * This software may be distributed under the terms of the BSD license. 6e604d861Schristos * See README for more details. 78dbcf02cSchristos */ 88dbcf02cSchristos 98dbcf02cSchristos #include "includes.h" 108dbcf02cSchristos #include <winsock2.h> 118dbcf02cSchristos 128dbcf02cSchristos #include "common.h" 133c260e60Schristos #include "list.h" 148dbcf02cSchristos #include "eloop.h" 158dbcf02cSchristos 168dbcf02cSchristos 178dbcf02cSchristos struct eloop_sock { 188dbcf02cSchristos int sock; 198dbcf02cSchristos void *eloop_data; 208dbcf02cSchristos void *user_data; 218dbcf02cSchristos eloop_sock_handler handler; 228dbcf02cSchristos WSAEVENT event; 238dbcf02cSchristos }; 248dbcf02cSchristos 258dbcf02cSchristos struct eloop_event { 268dbcf02cSchristos void *eloop_data; 278dbcf02cSchristos void *user_data; 288dbcf02cSchristos eloop_event_handler handler; 298dbcf02cSchristos HANDLE event; 308dbcf02cSchristos }; 318dbcf02cSchristos 328dbcf02cSchristos struct eloop_timeout { 333c260e60Schristos struct dl_list list; 343c260e60Schristos struct os_reltime time; 358dbcf02cSchristos void *eloop_data; 368dbcf02cSchristos void *user_data; 378dbcf02cSchristos eloop_timeout_handler handler; 388dbcf02cSchristos }; 398dbcf02cSchristos 408dbcf02cSchristos struct eloop_signal { 418dbcf02cSchristos int sig; 428dbcf02cSchristos void *user_data; 438dbcf02cSchristos eloop_signal_handler handler; 448dbcf02cSchristos int signaled; 458dbcf02cSchristos }; 468dbcf02cSchristos 478dbcf02cSchristos struct eloop_data { 488dbcf02cSchristos int max_sock; 498dbcf02cSchristos size_t reader_count; 508dbcf02cSchristos struct eloop_sock *readers; 518dbcf02cSchristos 528dbcf02cSchristos size_t event_count; 538dbcf02cSchristos struct eloop_event *events; 548dbcf02cSchristos 553c260e60Schristos struct dl_list timeout; 568dbcf02cSchristos 57*bb618362Schristos size_t signal_count; 588dbcf02cSchristos struct eloop_signal *signals; 598dbcf02cSchristos int signaled; 608dbcf02cSchristos int pending_terminate; 618dbcf02cSchristos 628dbcf02cSchristos int terminate; 638dbcf02cSchristos int reader_table_changed; 648dbcf02cSchristos 658dbcf02cSchristos struct eloop_signal term_signal; 668dbcf02cSchristos HANDLE term_event; 678dbcf02cSchristos 688dbcf02cSchristos HANDLE *handles; 698dbcf02cSchristos size_t num_handles; 708dbcf02cSchristos }; 718dbcf02cSchristos 728dbcf02cSchristos static struct eloop_data eloop; 738dbcf02cSchristos 748dbcf02cSchristos 758dbcf02cSchristos int eloop_init(void) 768dbcf02cSchristos { 778dbcf02cSchristos os_memset(&eloop, 0, sizeof(eloop)); 783c260e60Schristos dl_list_init(&eloop.timeout); 798dbcf02cSchristos eloop.num_handles = 1; 808dbcf02cSchristos eloop.handles = os_malloc(eloop.num_handles * 818dbcf02cSchristos sizeof(eloop.handles[0])); 828dbcf02cSchristos if (eloop.handles == NULL) 838dbcf02cSchristos return -1; 848dbcf02cSchristos 858dbcf02cSchristos eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); 868dbcf02cSchristos if (eloop.term_event == NULL) { 878dbcf02cSchristos printf("CreateEvent() failed: %d\n", 888dbcf02cSchristos (int) GetLastError()); 898dbcf02cSchristos os_free(eloop.handles); 908dbcf02cSchristos return -1; 918dbcf02cSchristos } 928dbcf02cSchristos 938dbcf02cSchristos return 0; 948dbcf02cSchristos } 958dbcf02cSchristos 968dbcf02cSchristos 978dbcf02cSchristos static int eloop_prepare_handles(void) 988dbcf02cSchristos { 998dbcf02cSchristos HANDLE *n; 1008dbcf02cSchristos 1018dbcf02cSchristos if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) 1028dbcf02cSchristos return 0; 103e604d861Schristos n = os_realloc_array(eloop.handles, eloop.num_handles * 2, 104e604d861Schristos sizeof(eloop.handles[0])); 1058dbcf02cSchristos if (n == NULL) 1068dbcf02cSchristos return -1; 1078dbcf02cSchristos eloop.handles = n; 1088dbcf02cSchristos eloop.num_handles *= 2; 1098dbcf02cSchristos return 0; 1108dbcf02cSchristos } 1118dbcf02cSchristos 1128dbcf02cSchristos 1138dbcf02cSchristos int eloop_register_read_sock(int sock, eloop_sock_handler handler, 1148dbcf02cSchristos void *eloop_data, void *user_data) 1158dbcf02cSchristos { 1168dbcf02cSchristos WSAEVENT event; 1178dbcf02cSchristos struct eloop_sock *tmp; 1188dbcf02cSchristos 1198dbcf02cSchristos if (eloop_prepare_handles()) 1208dbcf02cSchristos return -1; 1218dbcf02cSchristos 1228dbcf02cSchristos event = WSACreateEvent(); 1238dbcf02cSchristos if (event == WSA_INVALID_EVENT) { 1248dbcf02cSchristos printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 1258dbcf02cSchristos return -1; 1268dbcf02cSchristos } 1278dbcf02cSchristos 1288dbcf02cSchristos if (WSAEventSelect(sock, event, FD_READ)) { 1298dbcf02cSchristos printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 1308dbcf02cSchristos WSACloseEvent(event); 1318dbcf02cSchristos return -1; 1328dbcf02cSchristos } 133e604d861Schristos tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1, 134e604d861Schristos sizeof(struct eloop_sock)); 1358dbcf02cSchristos if (tmp == NULL) { 1368dbcf02cSchristos WSAEventSelect(sock, event, 0); 1378dbcf02cSchristos WSACloseEvent(event); 1388dbcf02cSchristos return -1; 1398dbcf02cSchristos } 1408dbcf02cSchristos 1418dbcf02cSchristos tmp[eloop.reader_count].sock = sock; 1428dbcf02cSchristos tmp[eloop.reader_count].eloop_data = eloop_data; 1438dbcf02cSchristos tmp[eloop.reader_count].user_data = user_data; 1448dbcf02cSchristos tmp[eloop.reader_count].handler = handler; 1458dbcf02cSchristos tmp[eloop.reader_count].event = event; 1468dbcf02cSchristos eloop.reader_count++; 1478dbcf02cSchristos eloop.readers = tmp; 1488dbcf02cSchristos if (sock > eloop.max_sock) 1498dbcf02cSchristos eloop.max_sock = sock; 1508dbcf02cSchristos eloop.reader_table_changed = 1; 1518dbcf02cSchristos 1528dbcf02cSchristos return 0; 1538dbcf02cSchristos } 1548dbcf02cSchristos 1558dbcf02cSchristos 1568dbcf02cSchristos void eloop_unregister_read_sock(int sock) 1578dbcf02cSchristos { 1588dbcf02cSchristos size_t i; 1598dbcf02cSchristos 1608dbcf02cSchristos if (eloop.readers == NULL || eloop.reader_count == 0) 1618dbcf02cSchristos return; 1628dbcf02cSchristos 1638dbcf02cSchristos for (i = 0; i < eloop.reader_count; i++) { 1648dbcf02cSchristos if (eloop.readers[i].sock == sock) 1658dbcf02cSchristos break; 1668dbcf02cSchristos } 1678dbcf02cSchristos if (i == eloop.reader_count) 1688dbcf02cSchristos return; 1698dbcf02cSchristos 1708dbcf02cSchristos WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); 1718dbcf02cSchristos WSACloseEvent(eloop.readers[i].event); 1728dbcf02cSchristos 1738dbcf02cSchristos if (i != eloop.reader_count - 1) { 1748dbcf02cSchristos os_memmove(&eloop.readers[i], &eloop.readers[i + 1], 1758dbcf02cSchristos (eloop.reader_count - i - 1) * 1768dbcf02cSchristos sizeof(struct eloop_sock)); 1778dbcf02cSchristos } 1788dbcf02cSchristos eloop.reader_count--; 1798dbcf02cSchristos eloop.reader_table_changed = 1; 1808dbcf02cSchristos } 1818dbcf02cSchristos 1828dbcf02cSchristos 1838dbcf02cSchristos int eloop_register_event(void *event, size_t event_size, 1848dbcf02cSchristos eloop_event_handler handler, 1858dbcf02cSchristos void *eloop_data, void *user_data) 1868dbcf02cSchristos { 1878dbcf02cSchristos struct eloop_event *tmp; 1888dbcf02cSchristos HANDLE h = event; 1898dbcf02cSchristos 1908dbcf02cSchristos if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) 1918dbcf02cSchristos return -1; 1928dbcf02cSchristos 1938dbcf02cSchristos if (eloop_prepare_handles()) 1948dbcf02cSchristos return -1; 1958dbcf02cSchristos 196e604d861Schristos tmp = os_realloc_array(eloop.events, eloop.event_count + 1, 197e604d861Schristos sizeof(struct eloop_event)); 1988dbcf02cSchristos if (tmp == NULL) 1998dbcf02cSchristos return -1; 2008dbcf02cSchristos 2018dbcf02cSchristos tmp[eloop.event_count].eloop_data = eloop_data; 2028dbcf02cSchristos tmp[eloop.event_count].user_data = user_data; 2038dbcf02cSchristos tmp[eloop.event_count].handler = handler; 2048dbcf02cSchristos tmp[eloop.event_count].event = h; 2058dbcf02cSchristos eloop.event_count++; 2068dbcf02cSchristos eloop.events = tmp; 2078dbcf02cSchristos 2088dbcf02cSchristos return 0; 2098dbcf02cSchristos } 2108dbcf02cSchristos 2118dbcf02cSchristos 2128dbcf02cSchristos void eloop_unregister_event(void *event, size_t event_size) 2138dbcf02cSchristos { 2148dbcf02cSchristos size_t i; 2158dbcf02cSchristos HANDLE h = event; 2168dbcf02cSchristos 2178dbcf02cSchristos if (eloop.events == NULL || eloop.event_count == 0 || 2188dbcf02cSchristos event_size != sizeof(HANDLE)) 2198dbcf02cSchristos return; 2208dbcf02cSchristos 2218dbcf02cSchristos for (i = 0; i < eloop.event_count; i++) { 2228dbcf02cSchristos if (eloop.events[i].event == h) 2238dbcf02cSchristos break; 2248dbcf02cSchristos } 2258dbcf02cSchristos if (i == eloop.event_count) 2268dbcf02cSchristos return; 2278dbcf02cSchristos 2288dbcf02cSchristos if (i != eloop.event_count - 1) { 2298dbcf02cSchristos os_memmove(&eloop.events[i], &eloop.events[i + 1], 2308dbcf02cSchristos (eloop.event_count - i - 1) * 2318dbcf02cSchristos sizeof(struct eloop_event)); 2328dbcf02cSchristos } 2338dbcf02cSchristos eloop.event_count--; 2348dbcf02cSchristos } 2358dbcf02cSchristos 2368dbcf02cSchristos 2378dbcf02cSchristos int eloop_register_timeout(unsigned int secs, unsigned int usecs, 2388dbcf02cSchristos eloop_timeout_handler handler, 2398dbcf02cSchristos void *eloop_data, void *user_data) 2408dbcf02cSchristos { 2413c260e60Schristos struct eloop_timeout *timeout, *tmp; 242111b9fd8Schristos os_time_t now_sec; 2438dbcf02cSchristos 2443c260e60Schristos timeout = os_zalloc(sizeof(*timeout)); 2458dbcf02cSchristos if (timeout == NULL) 2468dbcf02cSchristos return -1; 2473c260e60Schristos if (os_get_reltime(&timeout->time) < 0) { 2483c260e60Schristos os_free(timeout); 2493c260e60Schristos return -1; 2503c260e60Schristos } 251111b9fd8Schristos now_sec = timeout->time.sec; 2528dbcf02cSchristos timeout->time.sec += secs; 253111b9fd8Schristos if (timeout->time.sec < now_sec) { 254111b9fd8Schristos /* 255111b9fd8Schristos * Integer overflow - assume long enough timeout to be assumed 256111b9fd8Schristos * to be infinite, i.e., the timeout would never happen. 257111b9fd8Schristos */ 258111b9fd8Schristos wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " 259111b9fd8Schristos "ever happen - ignore it", secs); 260111b9fd8Schristos os_free(timeout); 261111b9fd8Schristos return 0; 262111b9fd8Schristos } 2638dbcf02cSchristos timeout->time.usec += usecs; 2648dbcf02cSchristos while (timeout->time.usec >= 1000000) { 2658dbcf02cSchristos timeout->time.sec++; 2668dbcf02cSchristos timeout->time.usec -= 1000000; 2678dbcf02cSchristos } 2688dbcf02cSchristos timeout->eloop_data = eloop_data; 2698dbcf02cSchristos timeout->user_data = user_data; 2708dbcf02cSchristos timeout->handler = handler; 2718dbcf02cSchristos 2723c260e60Schristos /* Maintain timeouts in order of increasing time */ 2733c260e60Schristos dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 2743c260e60Schristos if (os_reltime_before(&timeout->time, &tmp->time)) { 2753c260e60Schristos dl_list_add(tmp->list.prev, &timeout->list); 2763c260e60Schristos return 0; 2773c260e60Schristos } 2783c260e60Schristos } 2793c260e60Schristos dl_list_add_tail(&eloop.timeout, &timeout->list); 2803c260e60Schristos 2818dbcf02cSchristos return 0; 2828dbcf02cSchristos } 2838dbcf02cSchristos 2848dbcf02cSchristos 2853c260e60Schristos static void eloop_remove_timeout(struct eloop_timeout *timeout) 2863c260e60Schristos { 2873c260e60Schristos dl_list_del(&timeout->list); 2883c260e60Schristos os_free(timeout); 2898dbcf02cSchristos } 2908dbcf02cSchristos 2918dbcf02cSchristos 2928dbcf02cSchristos int eloop_cancel_timeout(eloop_timeout_handler handler, 2938dbcf02cSchristos void *eloop_data, void *user_data) 2948dbcf02cSchristos { 2953c260e60Schristos struct eloop_timeout *timeout, *prev; 2968dbcf02cSchristos int removed = 0; 2978dbcf02cSchristos 2983c260e60Schristos dl_list_for_each_safe(timeout, prev, &eloop.timeout, 2993c260e60Schristos struct eloop_timeout, list) { 3008dbcf02cSchristos if (timeout->handler == handler && 3018dbcf02cSchristos (timeout->eloop_data == eloop_data || 3028dbcf02cSchristos eloop_data == ELOOP_ALL_CTX) && 3038dbcf02cSchristos (timeout->user_data == user_data || 3048dbcf02cSchristos user_data == ELOOP_ALL_CTX)) { 3053c260e60Schristos eloop_remove_timeout(timeout); 3068dbcf02cSchristos removed++; 3073c260e60Schristos } 3088dbcf02cSchristos } 3098dbcf02cSchristos 3108dbcf02cSchristos return removed; 3118dbcf02cSchristos } 3128dbcf02cSchristos 3138dbcf02cSchristos 3143c260e60Schristos int eloop_cancel_timeout_one(eloop_timeout_handler handler, 3153c260e60Schristos void *eloop_data, void *user_data, 3163c260e60Schristos struct os_reltime *remaining) 3173c260e60Schristos { 3183c260e60Schristos struct eloop_timeout *timeout, *prev; 3193c260e60Schristos int removed = 0; 3203c260e60Schristos struct os_reltime now; 3213c260e60Schristos 3223c260e60Schristos os_get_reltime(&now); 3233c260e60Schristos remaining->sec = remaining->usec = 0; 3243c260e60Schristos 3253c260e60Schristos dl_list_for_each_safe(timeout, prev, &eloop.timeout, 3263c260e60Schristos struct eloop_timeout, list) { 3273c260e60Schristos if (timeout->handler == handler && 3283c260e60Schristos (timeout->eloop_data == eloop_data) && 3293c260e60Schristos (timeout->user_data == user_data)) { 3303c260e60Schristos removed = 1; 3313c260e60Schristos if (os_reltime_before(&now, &timeout->time)) 3323c260e60Schristos os_reltime_sub(&timeout->time, &now, remaining); 3333c260e60Schristos eloop_remove_timeout(timeout); 3343c260e60Schristos break; 3353c260e60Schristos } 3363c260e60Schristos } 3373c260e60Schristos return removed; 3383c260e60Schristos } 3393c260e60Schristos 3403c260e60Schristos 3418dbcf02cSchristos int eloop_is_timeout_registered(eloop_timeout_handler handler, 3428dbcf02cSchristos void *eloop_data, void *user_data) 3438dbcf02cSchristos { 3448dbcf02cSchristos struct eloop_timeout *tmp; 3458dbcf02cSchristos 3463c260e60Schristos dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 3478dbcf02cSchristos if (tmp->handler == handler && 3488dbcf02cSchristos tmp->eloop_data == eloop_data && 3498dbcf02cSchristos tmp->user_data == user_data) 3508dbcf02cSchristos return 1; 3518dbcf02cSchristos } 3528dbcf02cSchristos 3538dbcf02cSchristos return 0; 3548dbcf02cSchristos } 3558dbcf02cSchristos 3568dbcf02cSchristos 3573c260e60Schristos int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, 3583c260e60Schristos eloop_timeout_handler handler, void *eloop_data, 3593c260e60Schristos void *user_data) 3603c260e60Schristos { 3613c260e60Schristos struct os_reltime now, requested, remaining; 3623c260e60Schristos struct eloop_timeout *tmp; 3633c260e60Schristos 3643c260e60Schristos dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 3653c260e60Schristos if (tmp->handler == handler && 3663c260e60Schristos tmp->eloop_data == eloop_data && 3673c260e60Schristos tmp->user_data == user_data) { 3683c260e60Schristos requested.sec = req_secs; 3693c260e60Schristos requested.usec = req_usecs; 3703c260e60Schristos os_get_reltime(&now); 3713c260e60Schristos os_reltime_sub(&tmp->time, &now, &remaining); 3723c260e60Schristos if (os_reltime_before(&requested, &remaining)) { 3733c260e60Schristos eloop_cancel_timeout(handler, eloop_data, 3743c260e60Schristos user_data); 3753c260e60Schristos eloop_register_timeout(requested.sec, 3763c260e60Schristos requested.usec, 3773c260e60Schristos handler, eloop_data, 3783c260e60Schristos user_data); 3793c260e60Schristos return 1; 3803c260e60Schristos } 3813c260e60Schristos return 0; 3823c260e60Schristos } 3833c260e60Schristos } 3843c260e60Schristos 3853c260e60Schristos return -1; 3863c260e60Schristos } 3873c260e60Schristos 3883c260e60Schristos 3893c260e60Schristos int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, 3903c260e60Schristos eloop_timeout_handler handler, void *eloop_data, 3913c260e60Schristos void *user_data) 3923c260e60Schristos { 3933c260e60Schristos struct os_reltime now, requested, remaining; 3943c260e60Schristos struct eloop_timeout *tmp; 3953c260e60Schristos 3963c260e60Schristos dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 3973c260e60Schristos if (tmp->handler == handler && 3983c260e60Schristos tmp->eloop_data == eloop_data && 3993c260e60Schristos tmp->user_data == user_data) { 4003c260e60Schristos requested.sec = req_secs; 4013c260e60Schristos requested.usec = req_usecs; 4023c260e60Schristos os_get_reltime(&now); 4033c260e60Schristos os_reltime_sub(&tmp->time, &now, &remaining); 4043c260e60Schristos if (os_reltime_before(&remaining, &requested)) { 4053c260e60Schristos eloop_cancel_timeout(handler, eloop_data, 4063c260e60Schristos user_data); 4073c260e60Schristos eloop_register_timeout(requested.sec, 4083c260e60Schristos requested.usec, 4093c260e60Schristos handler, eloop_data, 4103c260e60Schristos user_data); 4113c260e60Schristos return 1; 4123c260e60Schristos } 4133c260e60Schristos return 0; 4143c260e60Schristos } 4153c260e60Schristos } 4163c260e60Schristos 4173c260e60Schristos return -1; 4183c260e60Schristos } 4193c260e60Schristos 4203c260e60Schristos 4218dbcf02cSchristos /* TODO: replace with suitable signal handler */ 4228dbcf02cSchristos #if 0 4238dbcf02cSchristos static void eloop_handle_signal(int sig) 4248dbcf02cSchristos { 425*bb618362Schristos size_t i; 4268dbcf02cSchristos 4278dbcf02cSchristos eloop.signaled++; 4288dbcf02cSchristos for (i = 0; i < eloop.signal_count; i++) { 4298dbcf02cSchristos if (eloop.signals[i].sig == sig) { 4308dbcf02cSchristos eloop.signals[i].signaled++; 4318dbcf02cSchristos break; 4328dbcf02cSchristos } 4338dbcf02cSchristos } 4348dbcf02cSchristos } 4358dbcf02cSchristos #endif 4368dbcf02cSchristos 4378dbcf02cSchristos 4388dbcf02cSchristos static void eloop_process_pending_signals(void) 4398dbcf02cSchristos { 440*bb618362Schristos size_t i; 4418dbcf02cSchristos 4428dbcf02cSchristos if (eloop.signaled == 0) 4438dbcf02cSchristos return; 4448dbcf02cSchristos eloop.signaled = 0; 4458dbcf02cSchristos 4468dbcf02cSchristos if (eloop.pending_terminate) { 4478dbcf02cSchristos eloop.pending_terminate = 0; 4488dbcf02cSchristos } 4498dbcf02cSchristos 4508dbcf02cSchristos for (i = 0; i < eloop.signal_count; i++) { 4518dbcf02cSchristos if (eloop.signals[i].signaled) { 4528dbcf02cSchristos eloop.signals[i].signaled = 0; 4538dbcf02cSchristos eloop.signals[i].handler(eloop.signals[i].sig, 4548dbcf02cSchristos eloop.signals[i].user_data); 4558dbcf02cSchristos } 4568dbcf02cSchristos } 4578dbcf02cSchristos 4588dbcf02cSchristos if (eloop.term_signal.signaled) { 4598dbcf02cSchristos eloop.term_signal.signaled = 0; 4608dbcf02cSchristos eloop.term_signal.handler(eloop.term_signal.sig, 4618dbcf02cSchristos eloop.term_signal.user_data); 4628dbcf02cSchristos } 4638dbcf02cSchristos } 4648dbcf02cSchristos 4658dbcf02cSchristos 4668dbcf02cSchristos int eloop_register_signal(int sig, eloop_signal_handler handler, 4678dbcf02cSchristos void *user_data) 4688dbcf02cSchristos { 4698dbcf02cSchristos struct eloop_signal *tmp; 4708dbcf02cSchristos 471e604d861Schristos tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 4728dbcf02cSchristos sizeof(struct eloop_signal)); 4738dbcf02cSchristos if (tmp == NULL) 4748dbcf02cSchristos return -1; 4758dbcf02cSchristos 4768dbcf02cSchristos tmp[eloop.signal_count].sig = sig; 4778dbcf02cSchristos tmp[eloop.signal_count].user_data = user_data; 4788dbcf02cSchristos tmp[eloop.signal_count].handler = handler; 4798dbcf02cSchristos tmp[eloop.signal_count].signaled = 0; 4808dbcf02cSchristos eloop.signal_count++; 4818dbcf02cSchristos eloop.signals = tmp; 4828dbcf02cSchristos 4838dbcf02cSchristos /* TODO: register signal handler */ 4848dbcf02cSchristos 4858dbcf02cSchristos return 0; 4868dbcf02cSchristos } 4878dbcf02cSchristos 4888dbcf02cSchristos 4898dbcf02cSchristos #ifndef _WIN32_WCE 4908dbcf02cSchristos static BOOL eloop_handle_console_ctrl(DWORD type) 4918dbcf02cSchristos { 4928dbcf02cSchristos switch (type) { 4938dbcf02cSchristos case CTRL_C_EVENT: 4948dbcf02cSchristos case CTRL_BREAK_EVENT: 4958dbcf02cSchristos eloop.signaled++; 4968dbcf02cSchristos eloop.term_signal.signaled++; 4978dbcf02cSchristos SetEvent(eloop.term_event); 4988dbcf02cSchristos return TRUE; 4998dbcf02cSchristos default: 5008dbcf02cSchristos return FALSE; 5018dbcf02cSchristos } 5028dbcf02cSchristos } 5038dbcf02cSchristos #endif /* _WIN32_WCE */ 5048dbcf02cSchristos 5058dbcf02cSchristos 5068dbcf02cSchristos int eloop_register_signal_terminate(eloop_signal_handler handler, 5078dbcf02cSchristos void *user_data) 5088dbcf02cSchristos { 5098dbcf02cSchristos #ifndef _WIN32_WCE 5108dbcf02cSchristos if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 5118dbcf02cSchristos TRUE) == 0) { 5128dbcf02cSchristos printf("SetConsoleCtrlHandler() failed: %d\n", 5138dbcf02cSchristos (int) GetLastError()); 5148dbcf02cSchristos return -1; 5158dbcf02cSchristos } 5168dbcf02cSchristos #endif /* _WIN32_WCE */ 5178dbcf02cSchristos 5188dbcf02cSchristos eloop.term_signal.handler = handler; 5198dbcf02cSchristos eloop.term_signal.user_data = user_data; 5208dbcf02cSchristos 5218dbcf02cSchristos return 0; 5228dbcf02cSchristos } 5238dbcf02cSchristos 5248dbcf02cSchristos 5258dbcf02cSchristos int eloop_register_signal_reconfig(eloop_signal_handler handler, 5268dbcf02cSchristos void *user_data) 5278dbcf02cSchristos { 5288dbcf02cSchristos /* TODO */ 5298dbcf02cSchristos return 0; 5308dbcf02cSchristos } 5318dbcf02cSchristos 5328dbcf02cSchristos 5338dbcf02cSchristos void eloop_run(void) 5348dbcf02cSchristos { 5353c260e60Schristos struct os_reltime tv, now; 5363c260e60Schristos DWORD count, ret, timeout_val, err; 5378dbcf02cSchristos size_t i; 5388dbcf02cSchristos 5398dbcf02cSchristos while (!eloop.terminate && 5403c260e60Schristos (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 || 5418dbcf02cSchristos eloop.event_count > 0)) { 5423c260e60Schristos struct eloop_timeout *timeout; 5438dbcf02cSchristos tv.sec = tv.usec = 0; 5443c260e60Schristos timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 5453c260e60Schristos list); 5463c260e60Schristos if (timeout) { 5473c260e60Schristos os_get_reltime(&now); 5483c260e60Schristos if (os_reltime_before(&now, &timeout->time)) 5493c260e60Schristos os_reltime_sub(&timeout->time, &now, &tv); 5508dbcf02cSchristos } 5518dbcf02cSchristos 5528dbcf02cSchristos count = 0; 5538dbcf02cSchristos for (i = 0; i < eloop.event_count; i++) 5548dbcf02cSchristos eloop.handles[count++] = eloop.events[i].event; 5558dbcf02cSchristos 5568dbcf02cSchristos for (i = 0; i < eloop.reader_count; i++) 5578dbcf02cSchristos eloop.handles[count++] = eloop.readers[i].event; 5588dbcf02cSchristos 5598dbcf02cSchristos if (eloop.term_event) 5608dbcf02cSchristos eloop.handles[count++] = eloop.term_event; 5618dbcf02cSchristos 5623c260e60Schristos if (timeout) 5633c260e60Schristos timeout_val = tv.sec * 1000 + tv.usec / 1000; 5648dbcf02cSchristos else 5653c260e60Schristos timeout_val = INFINITE; 5668dbcf02cSchristos 5678dbcf02cSchristos if (count > MAXIMUM_WAIT_OBJECTS) { 5688dbcf02cSchristos printf("WaitForMultipleObjects: Too many events: " 5698dbcf02cSchristos "%d > %d (ignoring extra events)\n", 5708dbcf02cSchristos (int) count, MAXIMUM_WAIT_OBJECTS); 5718dbcf02cSchristos count = MAXIMUM_WAIT_OBJECTS; 5728dbcf02cSchristos } 5738dbcf02cSchristos #ifdef _WIN32_WCE 5748dbcf02cSchristos ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 5753c260e60Schristos timeout_val); 5768dbcf02cSchristos #else /* _WIN32_WCE */ 5778dbcf02cSchristos ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 5783c260e60Schristos timeout_val, TRUE); 5798dbcf02cSchristos #endif /* _WIN32_WCE */ 5808dbcf02cSchristos err = GetLastError(); 5818dbcf02cSchristos 5828dbcf02cSchristos eloop_process_pending_signals(); 5838dbcf02cSchristos 5848dbcf02cSchristos /* check if some registered timeouts have occurred */ 5853c260e60Schristos timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 5863c260e60Schristos list); 5873c260e60Schristos if (timeout) { 5883c260e60Schristos os_get_reltime(&now); 5893c260e60Schristos if (!os_reltime_before(&now, &timeout->time)) { 5903c260e60Schristos void *eloop_data = timeout->eloop_data; 5913c260e60Schristos void *user_data = timeout->user_data; 5923c260e60Schristos eloop_timeout_handler handler = 5933c260e60Schristos timeout->handler; 5943c260e60Schristos eloop_remove_timeout(timeout); 5953c260e60Schristos handler(eloop_data, user_data); 5968dbcf02cSchristos } 5978dbcf02cSchristos 5988dbcf02cSchristos } 5998dbcf02cSchristos 6008dbcf02cSchristos if (ret == WAIT_FAILED) { 6018dbcf02cSchristos printf("WaitForMultipleObjects(count=%d) failed: %d\n", 6028dbcf02cSchristos (int) count, (int) err); 6038dbcf02cSchristos os_sleep(1, 0); 6048dbcf02cSchristos continue; 6058dbcf02cSchristos } 6068dbcf02cSchristos 6078dbcf02cSchristos #ifndef _WIN32_WCE 6088dbcf02cSchristos if (ret == WAIT_IO_COMPLETION) 6098dbcf02cSchristos continue; 6108dbcf02cSchristos #endif /* _WIN32_WCE */ 6118dbcf02cSchristos 6128dbcf02cSchristos if (ret == WAIT_TIMEOUT) 6138dbcf02cSchristos continue; 6148dbcf02cSchristos 6158dbcf02cSchristos while (ret >= WAIT_OBJECT_0 && 6168dbcf02cSchristos ret < WAIT_OBJECT_0 + eloop.event_count) { 6178dbcf02cSchristos eloop.events[ret].handler( 6188dbcf02cSchristos eloop.events[ret].eloop_data, 6198dbcf02cSchristos eloop.events[ret].user_data); 6208dbcf02cSchristos ret = WaitForMultipleObjects(eloop.event_count, 6218dbcf02cSchristos eloop.handles, FALSE, 0); 6228dbcf02cSchristos } 6238dbcf02cSchristos 6248dbcf02cSchristos eloop.reader_table_changed = 0; 6258dbcf02cSchristos for (i = 0; i < eloop.reader_count; i++) { 6268dbcf02cSchristos WSANETWORKEVENTS events; 6278dbcf02cSchristos if (WSAEnumNetworkEvents(eloop.readers[i].sock, 6288dbcf02cSchristos eloop.readers[i].event, 6298dbcf02cSchristos &events) == 0 && 6308dbcf02cSchristos (events.lNetworkEvents & FD_READ)) { 6318dbcf02cSchristos eloop.readers[i].handler( 6328dbcf02cSchristos eloop.readers[i].sock, 6338dbcf02cSchristos eloop.readers[i].eloop_data, 6348dbcf02cSchristos eloop.readers[i].user_data); 6358dbcf02cSchristos if (eloop.reader_table_changed) 6368dbcf02cSchristos break; 6378dbcf02cSchristos } 6388dbcf02cSchristos } 6398dbcf02cSchristos } 6408dbcf02cSchristos } 6418dbcf02cSchristos 6428dbcf02cSchristos 6438dbcf02cSchristos void eloop_terminate(void) 6448dbcf02cSchristos { 6458dbcf02cSchristos eloop.terminate = 1; 6468dbcf02cSchristos SetEvent(eloop.term_event); 6478dbcf02cSchristos } 6488dbcf02cSchristos 6498dbcf02cSchristos 6508dbcf02cSchristos void eloop_destroy(void) 6518dbcf02cSchristos { 6528dbcf02cSchristos struct eloop_timeout *timeout, *prev; 6538dbcf02cSchristos 6543c260e60Schristos dl_list_for_each_safe(timeout, prev, &eloop.timeout, 6553c260e60Schristos struct eloop_timeout, list) { 6563c260e60Schristos eloop_remove_timeout(timeout); 6578dbcf02cSchristos } 6588dbcf02cSchristos os_free(eloop.readers); 6598dbcf02cSchristos os_free(eloop.signals); 6608dbcf02cSchristos if (eloop.term_event) 6618dbcf02cSchristos CloseHandle(eloop.term_event); 6628dbcf02cSchristos os_free(eloop.handles); 6638dbcf02cSchristos eloop.handles = NULL; 6648dbcf02cSchristos os_free(eloop.events); 6658dbcf02cSchristos eloop.events = NULL; 6668dbcf02cSchristos } 6678dbcf02cSchristos 6688dbcf02cSchristos 6698dbcf02cSchristos int eloop_terminated(void) 6708dbcf02cSchristos { 6718dbcf02cSchristos return eloop.terminate; 6728dbcf02cSchristos } 6738dbcf02cSchristos 6748dbcf02cSchristos 6758dbcf02cSchristos void eloop_wait_for_read_sock(int sock) 6768dbcf02cSchristos { 6778dbcf02cSchristos WSAEVENT event; 6788dbcf02cSchristos 6798dbcf02cSchristos event = WSACreateEvent(); 6808dbcf02cSchristos if (event == WSA_INVALID_EVENT) { 6818dbcf02cSchristos printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 6828dbcf02cSchristos return; 6838dbcf02cSchristos } 6848dbcf02cSchristos 6858dbcf02cSchristos if (WSAEventSelect(sock, event, FD_READ)) { 6868dbcf02cSchristos printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 6878dbcf02cSchristos WSACloseEvent(event); 6888dbcf02cSchristos return ; 6898dbcf02cSchristos } 6908dbcf02cSchristos 6918dbcf02cSchristos WaitForSingleObject(event, INFINITE); 6928dbcf02cSchristos WSAEventSelect(sock, event, 0); 6938dbcf02cSchristos WSACloseEvent(event); 6948dbcf02cSchristos } 69536ebd06eSchristos 69636ebd06eSchristos 69736ebd06eSchristos int eloop_sock_requeue(void) 69836ebd06eSchristos { 69936ebd06eSchristos return 0; 70036ebd06eSchristos } 701