1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * Event loop based on Windows events and WaitForMultipleObjects 3e5b75505Sopenharmony_ci * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "includes.h" 10e5b75505Sopenharmony_ci#include <winsock2.h> 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "common.h" 13e5b75505Sopenharmony_ci#include "list.h" 14e5b75505Sopenharmony_ci#include "eloop.h" 15e5b75505Sopenharmony_ci 16e5b75505Sopenharmony_ci 17e5b75505Sopenharmony_cistruct eloop_sock { 18e5b75505Sopenharmony_ci int sock; 19e5b75505Sopenharmony_ci void *eloop_data; 20e5b75505Sopenharmony_ci void *user_data; 21e5b75505Sopenharmony_ci eloop_sock_handler handler; 22e5b75505Sopenharmony_ci WSAEVENT event; 23e5b75505Sopenharmony_ci}; 24e5b75505Sopenharmony_ci 25e5b75505Sopenharmony_cistruct eloop_event { 26e5b75505Sopenharmony_ci void *eloop_data; 27e5b75505Sopenharmony_ci void *user_data; 28e5b75505Sopenharmony_ci eloop_event_handler handler; 29e5b75505Sopenharmony_ci HANDLE event; 30e5b75505Sopenharmony_ci}; 31e5b75505Sopenharmony_ci 32e5b75505Sopenharmony_cistruct eloop_timeout { 33e5b75505Sopenharmony_ci struct dl_list list; 34e5b75505Sopenharmony_ci struct os_reltime time; 35e5b75505Sopenharmony_ci void *eloop_data; 36e5b75505Sopenharmony_ci void *user_data; 37e5b75505Sopenharmony_ci eloop_timeout_handler handler; 38e5b75505Sopenharmony_ci}; 39e5b75505Sopenharmony_ci 40e5b75505Sopenharmony_cistruct eloop_signal { 41e5b75505Sopenharmony_ci int sig; 42e5b75505Sopenharmony_ci void *user_data; 43e5b75505Sopenharmony_ci eloop_signal_handler handler; 44e5b75505Sopenharmony_ci int signaled; 45e5b75505Sopenharmony_ci}; 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_cistruct eloop_data { 48e5b75505Sopenharmony_ci int max_sock; 49e5b75505Sopenharmony_ci size_t reader_count; 50e5b75505Sopenharmony_ci struct eloop_sock *readers; 51e5b75505Sopenharmony_ci 52e5b75505Sopenharmony_ci size_t event_count; 53e5b75505Sopenharmony_ci struct eloop_event *events; 54e5b75505Sopenharmony_ci 55e5b75505Sopenharmony_ci struct dl_list timeout; 56e5b75505Sopenharmony_ci 57e5b75505Sopenharmony_ci int signal_count; 58e5b75505Sopenharmony_ci struct eloop_signal *signals; 59e5b75505Sopenharmony_ci int signaled; 60e5b75505Sopenharmony_ci int pending_terminate; 61e5b75505Sopenharmony_ci 62e5b75505Sopenharmony_ci int terminate; 63e5b75505Sopenharmony_ci int reader_table_changed; 64e5b75505Sopenharmony_ci 65e5b75505Sopenharmony_ci struct eloop_signal term_signal; 66e5b75505Sopenharmony_ci HANDLE term_event; 67e5b75505Sopenharmony_ci 68e5b75505Sopenharmony_ci HANDLE *handles; 69e5b75505Sopenharmony_ci size_t num_handles; 70e5b75505Sopenharmony_ci}; 71e5b75505Sopenharmony_ci 72e5b75505Sopenharmony_cistatic struct eloop_data eloop; 73e5b75505Sopenharmony_ci 74e5b75505Sopenharmony_ci 75e5b75505Sopenharmony_ciint eloop_init(void) 76e5b75505Sopenharmony_ci{ 77e5b75505Sopenharmony_ci os_memset(&eloop, 0, sizeof(eloop)); 78e5b75505Sopenharmony_ci dl_list_init(&eloop.timeout); 79e5b75505Sopenharmony_ci eloop.num_handles = 1; 80e5b75505Sopenharmony_ci eloop.handles = os_malloc(eloop.num_handles * 81e5b75505Sopenharmony_ci sizeof(eloop.handles[0])); 82e5b75505Sopenharmony_ci if (eloop.handles == NULL) 83e5b75505Sopenharmony_ci return -1; 84e5b75505Sopenharmony_ci 85e5b75505Sopenharmony_ci eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); 86e5b75505Sopenharmony_ci if (eloop.term_event == NULL) { 87e5b75505Sopenharmony_ci printf("CreateEvent() failed: %d\n", 88e5b75505Sopenharmony_ci (int) GetLastError()); 89e5b75505Sopenharmony_ci os_free(eloop.handles); 90e5b75505Sopenharmony_ci return -1; 91e5b75505Sopenharmony_ci } 92e5b75505Sopenharmony_ci 93e5b75505Sopenharmony_ci return 0; 94e5b75505Sopenharmony_ci} 95e5b75505Sopenharmony_ci 96e5b75505Sopenharmony_ci 97e5b75505Sopenharmony_cistatic int eloop_prepare_handles(void) 98e5b75505Sopenharmony_ci{ 99e5b75505Sopenharmony_ci HANDLE *n; 100e5b75505Sopenharmony_ci 101e5b75505Sopenharmony_ci if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) 102e5b75505Sopenharmony_ci return 0; 103e5b75505Sopenharmony_ci n = os_realloc_array(eloop.handles, eloop.num_handles * 2, 104e5b75505Sopenharmony_ci sizeof(eloop.handles[0])); 105e5b75505Sopenharmony_ci if (n == NULL) 106e5b75505Sopenharmony_ci return -1; 107e5b75505Sopenharmony_ci eloop.handles = n; 108e5b75505Sopenharmony_ci eloop.num_handles *= 2; 109e5b75505Sopenharmony_ci return 0; 110e5b75505Sopenharmony_ci} 111e5b75505Sopenharmony_ci 112e5b75505Sopenharmony_ci 113e5b75505Sopenharmony_ciint eloop_register_read_sock(int sock, eloop_sock_handler handler, 114e5b75505Sopenharmony_ci void *eloop_data, void *user_data) 115e5b75505Sopenharmony_ci{ 116e5b75505Sopenharmony_ci WSAEVENT event; 117e5b75505Sopenharmony_ci struct eloop_sock *tmp; 118e5b75505Sopenharmony_ci 119e5b75505Sopenharmony_ci if (eloop_prepare_handles()) 120e5b75505Sopenharmony_ci return -1; 121e5b75505Sopenharmony_ci 122e5b75505Sopenharmony_ci event = WSACreateEvent(); 123e5b75505Sopenharmony_ci if (event == WSA_INVALID_EVENT) { 124e5b75505Sopenharmony_ci printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 125e5b75505Sopenharmony_ci return -1; 126e5b75505Sopenharmony_ci } 127e5b75505Sopenharmony_ci 128e5b75505Sopenharmony_ci if (WSAEventSelect(sock, event, FD_READ)) { 129e5b75505Sopenharmony_ci printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 130e5b75505Sopenharmony_ci WSACloseEvent(event); 131e5b75505Sopenharmony_ci return -1; 132e5b75505Sopenharmony_ci } 133e5b75505Sopenharmony_ci tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1, 134e5b75505Sopenharmony_ci sizeof(struct eloop_sock)); 135e5b75505Sopenharmony_ci if (tmp == NULL) { 136e5b75505Sopenharmony_ci WSAEventSelect(sock, event, 0); 137e5b75505Sopenharmony_ci WSACloseEvent(event); 138e5b75505Sopenharmony_ci return -1; 139e5b75505Sopenharmony_ci } 140e5b75505Sopenharmony_ci 141e5b75505Sopenharmony_ci tmp[eloop.reader_count].sock = sock; 142e5b75505Sopenharmony_ci tmp[eloop.reader_count].eloop_data = eloop_data; 143e5b75505Sopenharmony_ci tmp[eloop.reader_count].user_data = user_data; 144e5b75505Sopenharmony_ci tmp[eloop.reader_count].handler = handler; 145e5b75505Sopenharmony_ci tmp[eloop.reader_count].event = event; 146e5b75505Sopenharmony_ci eloop.reader_count++; 147e5b75505Sopenharmony_ci eloop.readers = tmp; 148e5b75505Sopenharmony_ci if (sock > eloop.max_sock) 149e5b75505Sopenharmony_ci eloop.max_sock = sock; 150e5b75505Sopenharmony_ci eloop.reader_table_changed = 1; 151e5b75505Sopenharmony_ci 152e5b75505Sopenharmony_ci return 0; 153e5b75505Sopenharmony_ci} 154e5b75505Sopenharmony_ci 155e5b75505Sopenharmony_ci 156e5b75505Sopenharmony_civoid eloop_unregister_read_sock(int sock) 157e5b75505Sopenharmony_ci{ 158e5b75505Sopenharmony_ci size_t i; 159e5b75505Sopenharmony_ci 160e5b75505Sopenharmony_ci if (eloop.readers == NULL || eloop.reader_count == 0) 161e5b75505Sopenharmony_ci return; 162e5b75505Sopenharmony_ci 163e5b75505Sopenharmony_ci for (i = 0; i < eloop.reader_count; i++) { 164e5b75505Sopenharmony_ci if (eloop.readers[i].sock == sock) 165e5b75505Sopenharmony_ci break; 166e5b75505Sopenharmony_ci } 167e5b75505Sopenharmony_ci if (i == eloop.reader_count) 168e5b75505Sopenharmony_ci return; 169e5b75505Sopenharmony_ci 170e5b75505Sopenharmony_ci WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); 171e5b75505Sopenharmony_ci WSACloseEvent(eloop.readers[i].event); 172e5b75505Sopenharmony_ci 173e5b75505Sopenharmony_ci if (i != eloop.reader_count - 1) { 174e5b75505Sopenharmony_ci os_memmove(&eloop.readers[i], &eloop.readers[i + 1], 175e5b75505Sopenharmony_ci (eloop.reader_count - i - 1) * 176e5b75505Sopenharmony_ci sizeof(struct eloop_sock)); 177e5b75505Sopenharmony_ci } 178e5b75505Sopenharmony_ci eloop.reader_count--; 179e5b75505Sopenharmony_ci eloop.reader_table_changed = 1; 180e5b75505Sopenharmony_ci} 181e5b75505Sopenharmony_ci 182e5b75505Sopenharmony_ci 183e5b75505Sopenharmony_ciint eloop_register_event(void *event, size_t event_size, 184e5b75505Sopenharmony_ci eloop_event_handler handler, 185e5b75505Sopenharmony_ci void *eloop_data, void *user_data) 186e5b75505Sopenharmony_ci{ 187e5b75505Sopenharmony_ci struct eloop_event *tmp; 188e5b75505Sopenharmony_ci HANDLE h = event; 189e5b75505Sopenharmony_ci 190e5b75505Sopenharmony_ci if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) 191e5b75505Sopenharmony_ci return -1; 192e5b75505Sopenharmony_ci 193e5b75505Sopenharmony_ci if (eloop_prepare_handles()) 194e5b75505Sopenharmony_ci return -1; 195e5b75505Sopenharmony_ci 196e5b75505Sopenharmony_ci tmp = os_realloc_array(eloop.events, eloop.event_count + 1, 197e5b75505Sopenharmony_ci sizeof(struct eloop_event)); 198e5b75505Sopenharmony_ci if (tmp == NULL) 199e5b75505Sopenharmony_ci return -1; 200e5b75505Sopenharmony_ci 201e5b75505Sopenharmony_ci tmp[eloop.event_count].eloop_data = eloop_data; 202e5b75505Sopenharmony_ci tmp[eloop.event_count].user_data = user_data; 203e5b75505Sopenharmony_ci tmp[eloop.event_count].handler = handler; 204e5b75505Sopenharmony_ci tmp[eloop.event_count].event = h; 205e5b75505Sopenharmony_ci eloop.event_count++; 206e5b75505Sopenharmony_ci eloop.events = tmp; 207e5b75505Sopenharmony_ci 208e5b75505Sopenharmony_ci return 0; 209e5b75505Sopenharmony_ci} 210e5b75505Sopenharmony_ci 211e5b75505Sopenharmony_ci 212e5b75505Sopenharmony_civoid eloop_unregister_event(void *event, size_t event_size) 213e5b75505Sopenharmony_ci{ 214e5b75505Sopenharmony_ci size_t i; 215e5b75505Sopenharmony_ci HANDLE h = event; 216e5b75505Sopenharmony_ci 217e5b75505Sopenharmony_ci if (eloop.events == NULL || eloop.event_count == 0 || 218e5b75505Sopenharmony_ci event_size != sizeof(HANDLE)) 219e5b75505Sopenharmony_ci return; 220e5b75505Sopenharmony_ci 221e5b75505Sopenharmony_ci for (i = 0; i < eloop.event_count; i++) { 222e5b75505Sopenharmony_ci if (eloop.events[i].event == h) 223e5b75505Sopenharmony_ci break; 224e5b75505Sopenharmony_ci } 225e5b75505Sopenharmony_ci if (i == eloop.event_count) 226e5b75505Sopenharmony_ci return; 227e5b75505Sopenharmony_ci 228e5b75505Sopenharmony_ci if (i != eloop.event_count - 1) { 229e5b75505Sopenharmony_ci os_memmove(&eloop.events[i], &eloop.events[i + 1], 230e5b75505Sopenharmony_ci (eloop.event_count - i - 1) * 231e5b75505Sopenharmony_ci sizeof(struct eloop_event)); 232e5b75505Sopenharmony_ci } 233e5b75505Sopenharmony_ci eloop.event_count--; 234e5b75505Sopenharmony_ci} 235e5b75505Sopenharmony_ci 236e5b75505Sopenharmony_ci 237e5b75505Sopenharmony_ciint eloop_register_timeout(unsigned int secs, unsigned int usecs, 238e5b75505Sopenharmony_ci eloop_timeout_handler handler, 239e5b75505Sopenharmony_ci void *eloop_data, void *user_data) 240e5b75505Sopenharmony_ci{ 241e5b75505Sopenharmony_ci struct eloop_timeout *timeout, *tmp; 242e5b75505Sopenharmony_ci os_time_t now_sec; 243e5b75505Sopenharmony_ci 244e5b75505Sopenharmony_ci timeout = os_zalloc(sizeof(*timeout)); 245e5b75505Sopenharmony_ci if (timeout == NULL) 246e5b75505Sopenharmony_ci return -1; 247e5b75505Sopenharmony_ci if (os_get_reltime(&timeout->time) < 0) { 248e5b75505Sopenharmony_ci os_free(timeout); 249e5b75505Sopenharmony_ci return -1; 250e5b75505Sopenharmony_ci } 251e5b75505Sopenharmony_ci now_sec = timeout->time.sec; 252e5b75505Sopenharmony_ci timeout->time.sec += secs; 253e5b75505Sopenharmony_ci if (timeout->time.sec < now_sec) { 254e5b75505Sopenharmony_ci /* 255e5b75505Sopenharmony_ci * Integer overflow - assume long enough timeout to be assumed 256e5b75505Sopenharmony_ci * to be infinite, i.e., the timeout would never happen. 257e5b75505Sopenharmony_ci */ 258e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " 259e5b75505Sopenharmony_ci "ever happen - ignore it", secs); 260e5b75505Sopenharmony_ci os_free(timeout); 261e5b75505Sopenharmony_ci return 0; 262e5b75505Sopenharmony_ci } 263e5b75505Sopenharmony_ci timeout->time.usec += usecs; 264e5b75505Sopenharmony_ci while (timeout->time.usec >= 1000000) { 265e5b75505Sopenharmony_ci timeout->time.sec++; 266e5b75505Sopenharmony_ci timeout->time.usec -= 1000000; 267e5b75505Sopenharmony_ci } 268e5b75505Sopenharmony_ci timeout->eloop_data = eloop_data; 269e5b75505Sopenharmony_ci timeout->user_data = user_data; 270e5b75505Sopenharmony_ci timeout->handler = handler; 271e5b75505Sopenharmony_ci 272e5b75505Sopenharmony_ci /* Maintain timeouts in order of increasing time */ 273e5b75505Sopenharmony_ci dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 274e5b75505Sopenharmony_ci if (os_reltime_before(&timeout->time, &tmp->time)) { 275e5b75505Sopenharmony_ci dl_list_add(tmp->list.prev, &timeout->list); 276e5b75505Sopenharmony_ci return 0; 277e5b75505Sopenharmony_ci } 278e5b75505Sopenharmony_ci } 279e5b75505Sopenharmony_ci dl_list_add_tail(&eloop.timeout, &timeout->list); 280e5b75505Sopenharmony_ci 281e5b75505Sopenharmony_ci return 0; 282e5b75505Sopenharmony_ci} 283e5b75505Sopenharmony_ci 284e5b75505Sopenharmony_ci 285e5b75505Sopenharmony_cistatic void eloop_remove_timeout(struct eloop_timeout *timeout) 286e5b75505Sopenharmony_ci{ 287e5b75505Sopenharmony_ci dl_list_del(&timeout->list); 288e5b75505Sopenharmony_ci os_free(timeout); 289e5b75505Sopenharmony_ci} 290e5b75505Sopenharmony_ci 291e5b75505Sopenharmony_ci 292e5b75505Sopenharmony_ciint eloop_cancel_timeout(eloop_timeout_handler handler, 293e5b75505Sopenharmony_ci void *eloop_data, void *user_data) 294e5b75505Sopenharmony_ci{ 295e5b75505Sopenharmony_ci struct eloop_timeout *timeout, *prev; 296e5b75505Sopenharmony_ci int removed = 0; 297e5b75505Sopenharmony_ci 298e5b75505Sopenharmony_ci dl_list_for_each_safe(timeout, prev, &eloop.timeout, 299e5b75505Sopenharmony_ci struct eloop_timeout, list) { 300e5b75505Sopenharmony_ci if (timeout->handler == handler && 301e5b75505Sopenharmony_ci (timeout->eloop_data == eloop_data || 302e5b75505Sopenharmony_ci eloop_data == ELOOP_ALL_CTX) && 303e5b75505Sopenharmony_ci (timeout->user_data == user_data || 304e5b75505Sopenharmony_ci user_data == ELOOP_ALL_CTX)) { 305e5b75505Sopenharmony_ci eloop_remove_timeout(timeout); 306e5b75505Sopenharmony_ci removed++; 307e5b75505Sopenharmony_ci } 308e5b75505Sopenharmony_ci } 309e5b75505Sopenharmony_ci 310e5b75505Sopenharmony_ci return removed; 311e5b75505Sopenharmony_ci} 312e5b75505Sopenharmony_ci 313e5b75505Sopenharmony_ci 314e5b75505Sopenharmony_ciint eloop_cancel_timeout_one(eloop_timeout_handler handler, 315e5b75505Sopenharmony_ci void *eloop_data, void *user_data, 316e5b75505Sopenharmony_ci struct os_reltime *remaining) 317e5b75505Sopenharmony_ci{ 318e5b75505Sopenharmony_ci struct eloop_timeout *timeout, *prev; 319e5b75505Sopenharmony_ci int removed = 0; 320e5b75505Sopenharmony_ci struct os_reltime now; 321e5b75505Sopenharmony_ci 322e5b75505Sopenharmony_ci os_get_reltime(&now); 323e5b75505Sopenharmony_ci remaining->sec = remaining->usec = 0; 324e5b75505Sopenharmony_ci 325e5b75505Sopenharmony_ci dl_list_for_each_safe(timeout, prev, &eloop.timeout, 326e5b75505Sopenharmony_ci struct eloop_timeout, list) { 327e5b75505Sopenharmony_ci if (timeout->handler == handler && 328e5b75505Sopenharmony_ci (timeout->eloop_data == eloop_data) && 329e5b75505Sopenharmony_ci (timeout->user_data == user_data)) { 330e5b75505Sopenharmony_ci removed = 1; 331e5b75505Sopenharmony_ci if (os_reltime_before(&now, &timeout->time)) 332e5b75505Sopenharmony_ci os_reltime_sub(&timeout->time, &now, remaining); 333e5b75505Sopenharmony_ci eloop_remove_timeout(timeout); 334e5b75505Sopenharmony_ci break; 335e5b75505Sopenharmony_ci } 336e5b75505Sopenharmony_ci } 337e5b75505Sopenharmony_ci return removed; 338e5b75505Sopenharmony_ci} 339e5b75505Sopenharmony_ci 340e5b75505Sopenharmony_ci 341e5b75505Sopenharmony_ciint eloop_is_timeout_registered(eloop_timeout_handler handler, 342e5b75505Sopenharmony_ci void *eloop_data, void *user_data) 343e5b75505Sopenharmony_ci{ 344e5b75505Sopenharmony_ci struct eloop_timeout *tmp; 345e5b75505Sopenharmony_ci 346e5b75505Sopenharmony_ci dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 347e5b75505Sopenharmony_ci if (tmp->handler == handler && 348e5b75505Sopenharmony_ci tmp->eloop_data == eloop_data && 349e5b75505Sopenharmony_ci tmp->user_data == user_data) 350e5b75505Sopenharmony_ci return 1; 351e5b75505Sopenharmony_ci } 352e5b75505Sopenharmony_ci 353e5b75505Sopenharmony_ci return 0; 354e5b75505Sopenharmony_ci} 355e5b75505Sopenharmony_ci 356e5b75505Sopenharmony_ci 357e5b75505Sopenharmony_ciint eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, 358e5b75505Sopenharmony_ci eloop_timeout_handler handler, void *eloop_data, 359e5b75505Sopenharmony_ci void *user_data) 360e5b75505Sopenharmony_ci{ 361e5b75505Sopenharmony_ci struct os_reltime now, requested, remaining; 362e5b75505Sopenharmony_ci struct eloop_timeout *tmp; 363e5b75505Sopenharmony_ci 364e5b75505Sopenharmony_ci dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 365e5b75505Sopenharmony_ci if (tmp->handler == handler && 366e5b75505Sopenharmony_ci tmp->eloop_data == eloop_data && 367e5b75505Sopenharmony_ci tmp->user_data == user_data) { 368e5b75505Sopenharmony_ci requested.sec = req_secs; 369e5b75505Sopenharmony_ci requested.usec = req_usecs; 370e5b75505Sopenharmony_ci os_get_reltime(&now); 371e5b75505Sopenharmony_ci os_reltime_sub(&tmp->time, &now, &remaining); 372e5b75505Sopenharmony_ci if (os_reltime_before(&requested, &remaining)) { 373e5b75505Sopenharmony_ci eloop_cancel_timeout(handler, eloop_data, 374e5b75505Sopenharmony_ci user_data); 375e5b75505Sopenharmony_ci eloop_register_timeout(requested.sec, 376e5b75505Sopenharmony_ci requested.usec, 377e5b75505Sopenharmony_ci handler, eloop_data, 378e5b75505Sopenharmony_ci user_data); 379e5b75505Sopenharmony_ci return 1; 380e5b75505Sopenharmony_ci } 381e5b75505Sopenharmony_ci return 0; 382e5b75505Sopenharmony_ci } 383e5b75505Sopenharmony_ci } 384e5b75505Sopenharmony_ci 385e5b75505Sopenharmony_ci return -1; 386e5b75505Sopenharmony_ci} 387e5b75505Sopenharmony_ci 388e5b75505Sopenharmony_ci 389e5b75505Sopenharmony_ciint eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, 390e5b75505Sopenharmony_ci eloop_timeout_handler handler, void *eloop_data, 391e5b75505Sopenharmony_ci void *user_data) 392e5b75505Sopenharmony_ci{ 393e5b75505Sopenharmony_ci struct os_reltime now, requested, remaining; 394e5b75505Sopenharmony_ci struct eloop_timeout *tmp; 395e5b75505Sopenharmony_ci 396e5b75505Sopenharmony_ci dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 397e5b75505Sopenharmony_ci if (tmp->handler == handler && 398e5b75505Sopenharmony_ci tmp->eloop_data == eloop_data && 399e5b75505Sopenharmony_ci tmp->user_data == user_data) { 400e5b75505Sopenharmony_ci requested.sec = req_secs; 401e5b75505Sopenharmony_ci requested.usec = req_usecs; 402e5b75505Sopenharmony_ci os_get_reltime(&now); 403e5b75505Sopenharmony_ci os_reltime_sub(&tmp->time, &now, &remaining); 404e5b75505Sopenharmony_ci if (os_reltime_before(&remaining, &requested)) { 405e5b75505Sopenharmony_ci eloop_cancel_timeout(handler, eloop_data, 406e5b75505Sopenharmony_ci user_data); 407e5b75505Sopenharmony_ci eloop_register_timeout(requested.sec, 408e5b75505Sopenharmony_ci requested.usec, 409e5b75505Sopenharmony_ci handler, eloop_data, 410e5b75505Sopenharmony_ci user_data); 411e5b75505Sopenharmony_ci return 1; 412e5b75505Sopenharmony_ci } 413e5b75505Sopenharmony_ci return 0; 414e5b75505Sopenharmony_ci } 415e5b75505Sopenharmony_ci } 416e5b75505Sopenharmony_ci 417e5b75505Sopenharmony_ci return -1; 418e5b75505Sopenharmony_ci} 419e5b75505Sopenharmony_ci 420e5b75505Sopenharmony_ci 421e5b75505Sopenharmony_ci/* TODO: replace with suitable signal handler */ 422e5b75505Sopenharmony_ci#if 0 423e5b75505Sopenharmony_cistatic void eloop_handle_signal(int sig) 424e5b75505Sopenharmony_ci{ 425e5b75505Sopenharmony_ci int i; 426e5b75505Sopenharmony_ci 427e5b75505Sopenharmony_ci eloop.signaled++; 428e5b75505Sopenharmony_ci for (i = 0; i < eloop.signal_count; i++) { 429e5b75505Sopenharmony_ci if (eloop.signals[i].sig == sig) { 430e5b75505Sopenharmony_ci eloop.signals[i].signaled++; 431e5b75505Sopenharmony_ci break; 432e5b75505Sopenharmony_ci } 433e5b75505Sopenharmony_ci } 434e5b75505Sopenharmony_ci} 435e5b75505Sopenharmony_ci#endif 436e5b75505Sopenharmony_ci 437e5b75505Sopenharmony_ci 438e5b75505Sopenharmony_cistatic void eloop_process_pending_signals(void) 439e5b75505Sopenharmony_ci{ 440e5b75505Sopenharmony_ci int i; 441e5b75505Sopenharmony_ci 442e5b75505Sopenharmony_ci if (eloop.signaled == 0) 443e5b75505Sopenharmony_ci return; 444e5b75505Sopenharmony_ci eloop.signaled = 0; 445e5b75505Sopenharmony_ci 446e5b75505Sopenharmony_ci if (eloop.pending_terminate) { 447e5b75505Sopenharmony_ci eloop.pending_terminate = 0; 448e5b75505Sopenharmony_ci } 449e5b75505Sopenharmony_ci 450e5b75505Sopenharmony_ci for (i = 0; i < eloop.signal_count; i++) { 451e5b75505Sopenharmony_ci if (eloop.signals[i].signaled) { 452e5b75505Sopenharmony_ci eloop.signals[i].signaled = 0; 453e5b75505Sopenharmony_ci eloop.signals[i].handler(eloop.signals[i].sig, 454e5b75505Sopenharmony_ci eloop.signals[i].user_data); 455e5b75505Sopenharmony_ci } 456e5b75505Sopenharmony_ci } 457e5b75505Sopenharmony_ci 458e5b75505Sopenharmony_ci if (eloop.term_signal.signaled) { 459e5b75505Sopenharmony_ci eloop.term_signal.signaled = 0; 460e5b75505Sopenharmony_ci eloop.term_signal.handler(eloop.term_signal.sig, 461e5b75505Sopenharmony_ci eloop.term_signal.user_data); 462e5b75505Sopenharmony_ci } 463e5b75505Sopenharmony_ci} 464e5b75505Sopenharmony_ci 465e5b75505Sopenharmony_ci 466e5b75505Sopenharmony_ciint eloop_register_signal(int sig, eloop_signal_handler handler, 467e5b75505Sopenharmony_ci void *user_data) 468e5b75505Sopenharmony_ci{ 469e5b75505Sopenharmony_ci struct eloop_signal *tmp; 470e5b75505Sopenharmony_ci 471e5b75505Sopenharmony_ci tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 472e5b75505Sopenharmony_ci sizeof(struct eloop_signal)); 473e5b75505Sopenharmony_ci if (tmp == NULL) 474e5b75505Sopenharmony_ci return -1; 475e5b75505Sopenharmony_ci 476e5b75505Sopenharmony_ci tmp[eloop.signal_count].sig = sig; 477e5b75505Sopenharmony_ci tmp[eloop.signal_count].user_data = user_data; 478e5b75505Sopenharmony_ci tmp[eloop.signal_count].handler = handler; 479e5b75505Sopenharmony_ci tmp[eloop.signal_count].signaled = 0; 480e5b75505Sopenharmony_ci eloop.signal_count++; 481e5b75505Sopenharmony_ci eloop.signals = tmp; 482e5b75505Sopenharmony_ci 483e5b75505Sopenharmony_ci /* TODO: register signal handler */ 484e5b75505Sopenharmony_ci 485e5b75505Sopenharmony_ci return 0; 486e5b75505Sopenharmony_ci} 487e5b75505Sopenharmony_ci 488e5b75505Sopenharmony_ci 489e5b75505Sopenharmony_ci#ifndef _WIN32_WCE 490e5b75505Sopenharmony_cistatic BOOL eloop_handle_console_ctrl(DWORD type) 491e5b75505Sopenharmony_ci{ 492e5b75505Sopenharmony_ci switch (type) { 493e5b75505Sopenharmony_ci case CTRL_C_EVENT: 494e5b75505Sopenharmony_ci case CTRL_BREAK_EVENT: 495e5b75505Sopenharmony_ci eloop.signaled++; 496e5b75505Sopenharmony_ci eloop.term_signal.signaled++; 497e5b75505Sopenharmony_ci SetEvent(eloop.term_event); 498e5b75505Sopenharmony_ci return TRUE; 499e5b75505Sopenharmony_ci default: 500e5b75505Sopenharmony_ci return FALSE; 501e5b75505Sopenharmony_ci } 502e5b75505Sopenharmony_ci} 503e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */ 504e5b75505Sopenharmony_ci 505e5b75505Sopenharmony_ci 506e5b75505Sopenharmony_ciint eloop_register_signal_terminate(eloop_signal_handler handler, 507e5b75505Sopenharmony_ci void *user_data) 508e5b75505Sopenharmony_ci{ 509e5b75505Sopenharmony_ci#ifndef _WIN32_WCE 510e5b75505Sopenharmony_ci if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, 511e5b75505Sopenharmony_ci TRUE) == 0) { 512e5b75505Sopenharmony_ci printf("SetConsoleCtrlHandler() failed: %d\n", 513e5b75505Sopenharmony_ci (int) GetLastError()); 514e5b75505Sopenharmony_ci return -1; 515e5b75505Sopenharmony_ci } 516e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */ 517e5b75505Sopenharmony_ci 518e5b75505Sopenharmony_ci eloop.term_signal.handler = handler; 519e5b75505Sopenharmony_ci eloop.term_signal.user_data = user_data; 520e5b75505Sopenharmony_ci 521e5b75505Sopenharmony_ci return 0; 522e5b75505Sopenharmony_ci} 523e5b75505Sopenharmony_ci 524e5b75505Sopenharmony_ci 525e5b75505Sopenharmony_ciint eloop_register_signal_reconfig(eloop_signal_handler handler, 526e5b75505Sopenharmony_ci void *user_data) 527e5b75505Sopenharmony_ci{ 528e5b75505Sopenharmony_ci /* TODO */ 529e5b75505Sopenharmony_ci return 0; 530e5b75505Sopenharmony_ci} 531e5b75505Sopenharmony_ci 532e5b75505Sopenharmony_ci 533e5b75505Sopenharmony_civoid eloop_run(void) 534e5b75505Sopenharmony_ci{ 535e5b75505Sopenharmony_ci struct os_reltime tv, now; 536e5b75505Sopenharmony_ci DWORD count, ret, timeout_val, err; 537e5b75505Sopenharmony_ci size_t i; 538e5b75505Sopenharmony_ci 539e5b75505Sopenharmony_ci while (!eloop.terminate && 540e5b75505Sopenharmony_ci (!dl_list_empty(&eloop.timeout) || eloop.reader_count > 0 || 541e5b75505Sopenharmony_ci eloop.event_count > 0)) { 542e5b75505Sopenharmony_ci struct eloop_timeout *timeout; 543e5b75505Sopenharmony_ci tv.sec = tv.usec = 0; 544e5b75505Sopenharmony_ci timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 545e5b75505Sopenharmony_ci list); 546e5b75505Sopenharmony_ci if (timeout) { 547e5b75505Sopenharmony_ci os_get_reltime(&now); 548e5b75505Sopenharmony_ci if (os_reltime_before(&now, &timeout->time)) 549e5b75505Sopenharmony_ci os_reltime_sub(&timeout->time, &now, &tv); 550e5b75505Sopenharmony_ci } 551e5b75505Sopenharmony_ci 552e5b75505Sopenharmony_ci count = 0; 553e5b75505Sopenharmony_ci for (i = 0; i < eloop.event_count; i++) 554e5b75505Sopenharmony_ci eloop.handles[count++] = eloop.events[i].event; 555e5b75505Sopenharmony_ci 556e5b75505Sopenharmony_ci for (i = 0; i < eloop.reader_count; i++) 557e5b75505Sopenharmony_ci eloop.handles[count++] = eloop.readers[i].event; 558e5b75505Sopenharmony_ci 559e5b75505Sopenharmony_ci if (eloop.term_event) 560e5b75505Sopenharmony_ci eloop.handles[count++] = eloop.term_event; 561e5b75505Sopenharmony_ci 562e5b75505Sopenharmony_ci if (timeout) 563e5b75505Sopenharmony_ci timeout_val = tv.sec * 1000 + tv.usec / 1000; 564e5b75505Sopenharmony_ci else 565e5b75505Sopenharmony_ci timeout_val = INFINITE; 566e5b75505Sopenharmony_ci 567e5b75505Sopenharmony_ci if (count > MAXIMUM_WAIT_OBJECTS) { 568e5b75505Sopenharmony_ci printf("WaitForMultipleObjects: Too many events: " 569e5b75505Sopenharmony_ci "%d > %d (ignoring extra events)\n", 570e5b75505Sopenharmony_ci (int) count, MAXIMUM_WAIT_OBJECTS); 571e5b75505Sopenharmony_ci count = MAXIMUM_WAIT_OBJECTS; 572e5b75505Sopenharmony_ci } 573e5b75505Sopenharmony_ci#ifdef _WIN32_WCE 574e5b75505Sopenharmony_ci ret = WaitForMultipleObjects(count, eloop.handles, FALSE, 575e5b75505Sopenharmony_ci timeout_val); 576e5b75505Sopenharmony_ci#else /* _WIN32_WCE */ 577e5b75505Sopenharmony_ci ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, 578e5b75505Sopenharmony_ci timeout_val, TRUE); 579e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */ 580e5b75505Sopenharmony_ci err = GetLastError(); 581e5b75505Sopenharmony_ci 582e5b75505Sopenharmony_ci eloop_process_pending_signals(); 583e5b75505Sopenharmony_ci 584e5b75505Sopenharmony_ci /* check if some registered timeouts have occurred */ 585e5b75505Sopenharmony_ci timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 586e5b75505Sopenharmony_ci list); 587e5b75505Sopenharmony_ci if (timeout) { 588e5b75505Sopenharmony_ci os_get_reltime(&now); 589e5b75505Sopenharmony_ci if (!os_reltime_before(&now, &timeout->time)) { 590e5b75505Sopenharmony_ci void *eloop_data = timeout->eloop_data; 591e5b75505Sopenharmony_ci void *user_data = timeout->user_data; 592e5b75505Sopenharmony_ci eloop_timeout_handler handler = 593e5b75505Sopenharmony_ci timeout->handler; 594e5b75505Sopenharmony_ci eloop_remove_timeout(timeout); 595e5b75505Sopenharmony_ci handler(eloop_data, user_data); 596e5b75505Sopenharmony_ci } 597e5b75505Sopenharmony_ci 598e5b75505Sopenharmony_ci } 599e5b75505Sopenharmony_ci 600e5b75505Sopenharmony_ci if (ret == WAIT_FAILED) { 601e5b75505Sopenharmony_ci printf("WaitForMultipleObjects(count=%d) failed: %d\n", 602e5b75505Sopenharmony_ci (int) count, (int) err); 603e5b75505Sopenharmony_ci os_sleep(1, 0); 604e5b75505Sopenharmony_ci continue; 605e5b75505Sopenharmony_ci } 606e5b75505Sopenharmony_ci 607e5b75505Sopenharmony_ci#ifndef _WIN32_WCE 608e5b75505Sopenharmony_ci if (ret == WAIT_IO_COMPLETION) 609e5b75505Sopenharmony_ci continue; 610e5b75505Sopenharmony_ci#endif /* _WIN32_WCE */ 611e5b75505Sopenharmony_ci 612e5b75505Sopenharmony_ci if (ret == WAIT_TIMEOUT) 613e5b75505Sopenharmony_ci continue; 614e5b75505Sopenharmony_ci 615e5b75505Sopenharmony_ci while (ret >= WAIT_OBJECT_0 && 616e5b75505Sopenharmony_ci ret < WAIT_OBJECT_0 + eloop.event_count) { 617e5b75505Sopenharmony_ci eloop.events[ret].handler( 618e5b75505Sopenharmony_ci eloop.events[ret].eloop_data, 619e5b75505Sopenharmony_ci eloop.events[ret].user_data); 620e5b75505Sopenharmony_ci ret = WaitForMultipleObjects(eloop.event_count, 621e5b75505Sopenharmony_ci eloop.handles, FALSE, 0); 622e5b75505Sopenharmony_ci } 623e5b75505Sopenharmony_ci 624e5b75505Sopenharmony_ci eloop.reader_table_changed = 0; 625e5b75505Sopenharmony_ci for (i = 0; i < eloop.reader_count; i++) { 626e5b75505Sopenharmony_ci WSANETWORKEVENTS events; 627e5b75505Sopenharmony_ci if (WSAEnumNetworkEvents(eloop.readers[i].sock, 628e5b75505Sopenharmony_ci eloop.readers[i].event, 629e5b75505Sopenharmony_ci &events) == 0 && 630e5b75505Sopenharmony_ci (events.lNetworkEvents & FD_READ)) { 631e5b75505Sopenharmony_ci eloop.readers[i].handler( 632e5b75505Sopenharmony_ci eloop.readers[i].sock, 633e5b75505Sopenharmony_ci eloop.readers[i].eloop_data, 634e5b75505Sopenharmony_ci eloop.readers[i].user_data); 635e5b75505Sopenharmony_ci if (eloop.reader_table_changed) 636e5b75505Sopenharmony_ci break; 637e5b75505Sopenharmony_ci } 638e5b75505Sopenharmony_ci } 639e5b75505Sopenharmony_ci } 640e5b75505Sopenharmony_ci} 641e5b75505Sopenharmony_ci 642e5b75505Sopenharmony_ci 643e5b75505Sopenharmony_civoid eloop_terminate(void) 644e5b75505Sopenharmony_ci{ 645e5b75505Sopenharmony_ci eloop.terminate = 1; 646e5b75505Sopenharmony_ci SetEvent(eloop.term_event); 647e5b75505Sopenharmony_ci} 648e5b75505Sopenharmony_ci 649e5b75505Sopenharmony_ci 650e5b75505Sopenharmony_civoid eloop_destroy(void) 651e5b75505Sopenharmony_ci{ 652e5b75505Sopenharmony_ci struct eloop_timeout *timeout, *prev; 653e5b75505Sopenharmony_ci 654e5b75505Sopenharmony_ci dl_list_for_each_safe(timeout, prev, &eloop.timeout, 655e5b75505Sopenharmony_ci struct eloop_timeout, list) { 656e5b75505Sopenharmony_ci eloop_remove_timeout(timeout); 657e5b75505Sopenharmony_ci } 658e5b75505Sopenharmony_ci os_free(eloop.readers); 659e5b75505Sopenharmony_ci os_free(eloop.signals); 660e5b75505Sopenharmony_ci if (eloop.term_event) 661e5b75505Sopenharmony_ci CloseHandle(eloop.term_event); 662e5b75505Sopenharmony_ci os_free(eloop.handles); 663e5b75505Sopenharmony_ci eloop.handles = NULL; 664e5b75505Sopenharmony_ci os_free(eloop.events); 665e5b75505Sopenharmony_ci eloop.events = NULL; 666e5b75505Sopenharmony_ci} 667e5b75505Sopenharmony_ci 668e5b75505Sopenharmony_ci 669e5b75505Sopenharmony_ciint eloop_terminated(void) 670e5b75505Sopenharmony_ci{ 671e5b75505Sopenharmony_ci return eloop.terminate; 672e5b75505Sopenharmony_ci} 673e5b75505Sopenharmony_ci 674e5b75505Sopenharmony_ci 675e5b75505Sopenharmony_civoid eloop_wait_for_read_sock(int sock) 676e5b75505Sopenharmony_ci{ 677e5b75505Sopenharmony_ci WSAEVENT event; 678e5b75505Sopenharmony_ci 679e5b75505Sopenharmony_ci event = WSACreateEvent(); 680e5b75505Sopenharmony_ci if (event == WSA_INVALID_EVENT) { 681e5b75505Sopenharmony_ci printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); 682e5b75505Sopenharmony_ci return; 683e5b75505Sopenharmony_ci } 684e5b75505Sopenharmony_ci 685e5b75505Sopenharmony_ci if (WSAEventSelect(sock, event, FD_READ)) { 686e5b75505Sopenharmony_ci printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); 687e5b75505Sopenharmony_ci WSACloseEvent(event); 688e5b75505Sopenharmony_ci return ; 689e5b75505Sopenharmony_ci } 690e5b75505Sopenharmony_ci 691e5b75505Sopenharmony_ci WaitForSingleObject(event, INFINITE); 692e5b75505Sopenharmony_ci WSAEventSelect(sock, event, 0); 693e5b75505Sopenharmony_ci WSACloseEvent(event); 694e5b75505Sopenharmony_ci} 695e5b75505Sopenharmony_ci 696e5b75505Sopenharmony_ci 697e5b75505Sopenharmony_ciint eloop_sock_requeue(void) 698e5b75505Sopenharmony_ci{ 699e5b75505Sopenharmony_ci return 0; 700e5b75505Sopenharmony_ci} 701