1209139Srpaulo/* 2209139Srpaulo * Event loop - empty template (basic structure, but no OS specific operations) 3209139Srpaulo * Copyright (c) 2002-2005, 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 11209139Srpaulo#include "common.h" 12209139Srpaulo#include "eloop.h" 13209139Srpaulo 14209139Srpaulo 15209139Srpaulostruct eloop_sock { 16209139Srpaulo int sock; 17209139Srpaulo void *eloop_data; 18209139Srpaulo void *user_data; 19209139Srpaulo void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); 20209139Srpaulo}; 21209139Srpaulo 22209139Srpaulostruct eloop_timeout { 23209139Srpaulo struct os_time time; 24209139Srpaulo void *eloop_data; 25209139Srpaulo void *user_data; 26209139Srpaulo void (*handler)(void *eloop_ctx, void *sock_ctx); 27209139Srpaulo struct eloop_timeout *next; 28209139Srpaulo}; 29209139Srpaulo 30209139Srpaulostruct eloop_signal { 31209139Srpaulo int sig; 32209139Srpaulo void *user_data; 33209139Srpaulo void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); 34209139Srpaulo int signaled; 35209139Srpaulo}; 36209139Srpaulo 37209139Srpaulostruct eloop_data { 38209139Srpaulo int max_sock, reader_count; 39209139Srpaulo struct eloop_sock *readers; 40209139Srpaulo 41209139Srpaulo struct eloop_timeout *timeout; 42209139Srpaulo 43209139Srpaulo int signal_count; 44209139Srpaulo struct eloop_signal *signals; 45209139Srpaulo int signaled; 46209139Srpaulo int pending_terminate; 47209139Srpaulo 48209139Srpaulo int terminate; 49209139Srpaulo int reader_table_changed; 50209139Srpaulo}; 51209139Srpaulo 52209139Srpaulostatic struct eloop_data eloop; 53209139Srpaulo 54209139Srpaulo 55214734Srpauloint eloop_init(void) 56209139Srpaulo{ 57209139Srpaulo memset(&eloop, 0, sizeof(eloop)); 58209139Srpaulo return 0; 59209139Srpaulo} 60209139Srpaulo 61209139Srpaulo 62209139Srpauloint eloop_register_read_sock(int sock, 63209139Srpaulo void (*handler)(int sock, void *eloop_ctx, 64209139Srpaulo void *sock_ctx), 65209139Srpaulo void *eloop_data, void *user_data) 66209139Srpaulo{ 67209139Srpaulo struct eloop_sock *tmp; 68209139Srpaulo 69209139Srpaulo tmp = (struct eloop_sock *) 70209139Srpaulo realloc(eloop.readers, 71209139Srpaulo (eloop.reader_count + 1) * sizeof(struct eloop_sock)); 72209139Srpaulo if (tmp == NULL) 73209139Srpaulo return -1; 74209139Srpaulo 75209139Srpaulo tmp[eloop.reader_count].sock = sock; 76209139Srpaulo tmp[eloop.reader_count].eloop_data = eloop_data; 77209139Srpaulo tmp[eloop.reader_count].user_data = user_data; 78209139Srpaulo tmp[eloop.reader_count].handler = handler; 79209139Srpaulo eloop.reader_count++; 80209139Srpaulo eloop.readers = tmp; 81209139Srpaulo if (sock > eloop.max_sock) 82209139Srpaulo eloop.max_sock = sock; 83209139Srpaulo eloop.reader_table_changed = 1; 84209139Srpaulo 85209139Srpaulo return 0; 86209139Srpaulo} 87209139Srpaulo 88209139Srpaulo 89209139Srpaulovoid eloop_unregister_read_sock(int sock) 90209139Srpaulo{ 91209139Srpaulo int i; 92209139Srpaulo 93209139Srpaulo if (eloop.readers == NULL || eloop.reader_count == 0) 94209139Srpaulo return; 95209139Srpaulo 96209139Srpaulo for (i = 0; i < eloop.reader_count; i++) { 97209139Srpaulo if (eloop.readers[i].sock == sock) 98209139Srpaulo break; 99209139Srpaulo } 100209139Srpaulo if (i == eloop.reader_count) 101209139Srpaulo return; 102209139Srpaulo if (i != eloop.reader_count - 1) { 103209139Srpaulo memmove(&eloop.readers[i], &eloop.readers[i + 1], 104209139Srpaulo (eloop.reader_count - i - 1) * 105209139Srpaulo sizeof(struct eloop_sock)); 106209139Srpaulo } 107209139Srpaulo eloop.reader_count--; 108209139Srpaulo eloop.reader_table_changed = 1; 109209139Srpaulo} 110209139Srpaulo 111209139Srpaulo 112209139Srpauloint eloop_register_timeout(unsigned int secs, unsigned int usecs, 113209139Srpaulo void (*handler)(void *eloop_ctx, void *timeout_ctx), 114209139Srpaulo void *eloop_data, void *user_data) 115209139Srpaulo{ 116209139Srpaulo struct eloop_timeout *timeout, *tmp, *prev; 117209139Srpaulo 118209139Srpaulo timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); 119209139Srpaulo if (timeout == NULL) 120209139Srpaulo return -1; 121209139Srpaulo os_get_time(&timeout->time); 122209139Srpaulo timeout->time.sec += secs; 123209139Srpaulo timeout->time.usec += usecs; 124209139Srpaulo while (timeout->time.usec >= 1000000) { 125209139Srpaulo timeout->time.sec++; 126209139Srpaulo timeout->time.usec -= 1000000; 127209139Srpaulo } 128209139Srpaulo timeout->eloop_data = eloop_data; 129209139Srpaulo timeout->user_data = user_data; 130209139Srpaulo timeout->handler = handler; 131209139Srpaulo timeout->next = NULL; 132209139Srpaulo 133209139Srpaulo if (eloop.timeout == NULL) { 134209139Srpaulo eloop.timeout = timeout; 135209139Srpaulo return 0; 136209139Srpaulo } 137209139Srpaulo 138209139Srpaulo prev = NULL; 139209139Srpaulo tmp = eloop.timeout; 140209139Srpaulo while (tmp != NULL) { 141209139Srpaulo if (os_time_before(&timeout->time, &tmp->time)) 142209139Srpaulo break; 143209139Srpaulo prev = tmp; 144209139Srpaulo tmp = tmp->next; 145209139Srpaulo } 146209139Srpaulo 147209139Srpaulo if (prev == NULL) { 148209139Srpaulo timeout->next = eloop.timeout; 149209139Srpaulo eloop.timeout = timeout; 150209139Srpaulo } else { 151209139Srpaulo timeout->next = prev->next; 152209139Srpaulo prev->next = timeout; 153209139Srpaulo } 154209139Srpaulo 155209139Srpaulo return 0; 156209139Srpaulo} 157209139Srpaulo 158209139Srpaulo 159209139Srpauloint eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), 160209139Srpaulo void *eloop_data, void *user_data) 161209139Srpaulo{ 162209139Srpaulo struct eloop_timeout *timeout, *prev, *next; 163209139Srpaulo int removed = 0; 164209139Srpaulo 165209139Srpaulo prev = NULL; 166209139Srpaulo timeout = eloop.timeout; 167209139Srpaulo while (timeout != NULL) { 168209139Srpaulo next = timeout->next; 169209139Srpaulo 170209139Srpaulo if (timeout->handler == handler && 171209139Srpaulo (timeout->eloop_data == eloop_data || 172209139Srpaulo eloop_data == ELOOP_ALL_CTX) && 173209139Srpaulo (timeout->user_data == user_data || 174209139Srpaulo user_data == ELOOP_ALL_CTX)) { 175209139Srpaulo if (prev == NULL) 176209139Srpaulo eloop.timeout = next; 177209139Srpaulo else 178209139Srpaulo prev->next = next; 179209139Srpaulo free(timeout); 180209139Srpaulo removed++; 181209139Srpaulo } else 182209139Srpaulo prev = timeout; 183209139Srpaulo 184209139Srpaulo timeout = next; 185209139Srpaulo } 186209139Srpaulo 187209139Srpaulo return removed; 188209139Srpaulo} 189209139Srpaulo 190209139Srpaulo 191209139Srpauloint eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, 192209139Srpaulo void *timeout_ctx), 193209139Srpaulo void *eloop_data, void *user_data) 194209139Srpaulo{ 195209139Srpaulo struct eloop_timeout *tmp; 196209139Srpaulo 197209139Srpaulo tmp = eloop.timeout; 198209139Srpaulo while (tmp != NULL) { 199209139Srpaulo if (tmp->handler == handler && 200209139Srpaulo tmp->eloop_data == eloop_data && 201209139Srpaulo tmp->user_data == user_data) 202209139Srpaulo return 1; 203209139Srpaulo 204209139Srpaulo tmp = tmp->next; 205209139Srpaulo } 206209139Srpaulo 207209139Srpaulo return 0; 208209139Srpaulo} 209209139Srpaulo 210209139Srpaulo 211209139Srpaulo/* TODO: replace with suitable signal handler */ 212209139Srpaulo#if 0 213209139Srpaulostatic void eloop_handle_signal(int sig) 214209139Srpaulo{ 215209139Srpaulo int i; 216209139Srpaulo 217209139Srpaulo eloop.signaled++; 218209139Srpaulo for (i = 0; i < eloop.signal_count; i++) { 219209139Srpaulo if (eloop.signals[i].sig == sig) { 220209139Srpaulo eloop.signals[i].signaled++; 221209139Srpaulo break; 222209139Srpaulo } 223209139Srpaulo } 224209139Srpaulo} 225209139Srpaulo#endif 226209139Srpaulo 227209139Srpaulo 228209139Srpaulostatic void eloop_process_pending_signals(void) 229209139Srpaulo{ 230209139Srpaulo int i; 231209139Srpaulo 232209139Srpaulo if (eloop.signaled == 0) 233209139Srpaulo return; 234209139Srpaulo eloop.signaled = 0; 235209139Srpaulo 236209139Srpaulo if (eloop.pending_terminate) { 237209139Srpaulo eloop.pending_terminate = 0; 238209139Srpaulo } 239209139Srpaulo 240209139Srpaulo for (i = 0; i < eloop.signal_count; i++) { 241209139Srpaulo if (eloop.signals[i].signaled) { 242209139Srpaulo eloop.signals[i].signaled = 0; 243209139Srpaulo eloop.signals[i].handler(eloop.signals[i].sig, 244209139Srpaulo eloop.user_data, 245209139Srpaulo eloop.signals[i].user_data); 246209139Srpaulo } 247209139Srpaulo } 248209139Srpaulo} 249209139Srpaulo 250209139Srpaulo 251209139Srpauloint eloop_register_signal(int sig, 252209139Srpaulo void (*handler)(int sig, void *eloop_ctx, 253209139Srpaulo void *signal_ctx), 254209139Srpaulo void *user_data) 255209139Srpaulo{ 256209139Srpaulo struct eloop_signal *tmp; 257209139Srpaulo 258209139Srpaulo tmp = (struct eloop_signal *) 259209139Srpaulo realloc(eloop.signals, 260209139Srpaulo (eloop.signal_count + 1) * 261209139Srpaulo sizeof(struct eloop_signal)); 262209139Srpaulo if (tmp == NULL) 263209139Srpaulo return -1; 264209139Srpaulo 265209139Srpaulo tmp[eloop.signal_count].sig = sig; 266209139Srpaulo tmp[eloop.signal_count].user_data = user_data; 267209139Srpaulo tmp[eloop.signal_count].handler = handler; 268209139Srpaulo tmp[eloop.signal_count].signaled = 0; 269209139Srpaulo eloop.signal_count++; 270209139Srpaulo eloop.signals = tmp; 271209139Srpaulo 272209139Srpaulo /* TODO: register signal handler */ 273209139Srpaulo 274209139Srpaulo return 0; 275209139Srpaulo} 276209139Srpaulo 277209139Srpaulo 278209139Srpauloint eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx, 279209139Srpaulo void *signal_ctx), 280209139Srpaulo void *user_data) 281209139Srpaulo{ 282209139Srpaulo#if 0 283209139Srpaulo /* TODO: for example */ 284209139Srpaulo int ret = eloop_register_signal(SIGINT, handler, user_data); 285209139Srpaulo if (ret == 0) 286209139Srpaulo ret = eloop_register_signal(SIGTERM, handler, user_data); 287209139Srpaulo return ret; 288209139Srpaulo#endif 289209139Srpaulo return 0; 290209139Srpaulo} 291209139Srpaulo 292209139Srpaulo 293209139Srpauloint eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx, 294209139Srpaulo void *signal_ctx), 295209139Srpaulo void *user_data) 296209139Srpaulo{ 297209139Srpaulo#if 0 298209139Srpaulo /* TODO: for example */ 299209139Srpaulo return eloop_register_signal(SIGHUP, handler, user_data); 300209139Srpaulo#endif 301209139Srpaulo return 0; 302209139Srpaulo} 303209139Srpaulo 304209139Srpaulo 305209139Srpaulovoid eloop_run(void) 306209139Srpaulo{ 307209139Srpaulo int i; 308209139Srpaulo struct os_time tv, now; 309209139Srpaulo 310209139Srpaulo while (!eloop.terminate && 311209139Srpaulo (eloop.timeout || eloop.reader_count > 0)) { 312209139Srpaulo if (eloop.timeout) { 313209139Srpaulo os_get_time(&now); 314209139Srpaulo if (os_time_before(&now, &eloop.timeout->time)) 315209139Srpaulo os_time_sub(&eloop.timeout->time, &now, &tv); 316209139Srpaulo else 317209139Srpaulo tv.sec = tv.usec = 0; 318209139Srpaulo } 319209139Srpaulo 320209139Srpaulo /* 321209139Srpaulo * TODO: wait for any event (read socket ready, timeout (tv), 322209139Srpaulo * signal 323209139Srpaulo */ 324209139Srpaulo os_sleep(1, 0); /* just a dummy wait for testing */ 325209139Srpaulo 326209139Srpaulo eloop_process_pending_signals(); 327209139Srpaulo 328209139Srpaulo /* check if some registered timeouts have occurred */ 329209139Srpaulo if (eloop.timeout) { 330209139Srpaulo struct eloop_timeout *tmp; 331209139Srpaulo 332209139Srpaulo os_get_time(&now); 333209139Srpaulo if (!os_time_before(&now, &eloop.timeout->time)) { 334209139Srpaulo tmp = eloop.timeout; 335209139Srpaulo eloop.timeout = eloop.timeout->next; 336209139Srpaulo tmp->handler(tmp->eloop_data, 337209139Srpaulo tmp->user_data); 338209139Srpaulo free(tmp); 339209139Srpaulo } 340209139Srpaulo 341209139Srpaulo } 342209139Srpaulo 343209139Srpaulo eloop.reader_table_changed = 0; 344209139Srpaulo for (i = 0; i < eloop.reader_count; i++) { 345209139Srpaulo /* 346209139Srpaulo * TODO: call each handler that has pending data to 347209139Srpaulo * read 348209139Srpaulo */ 349209139Srpaulo if (0 /* TODO: eloop.readers[i].sock ready */) { 350209139Srpaulo eloop.readers[i].handler( 351209139Srpaulo eloop.readers[i].sock, 352209139Srpaulo eloop.readers[i].eloop_data, 353209139Srpaulo eloop.readers[i].user_data); 354209139Srpaulo if (eloop.reader_table_changed) 355209139Srpaulo break; 356209139Srpaulo } 357209139Srpaulo } 358209139Srpaulo } 359209139Srpaulo} 360209139Srpaulo 361209139Srpaulo 362209139Srpaulovoid eloop_terminate(void) 363209139Srpaulo{ 364209139Srpaulo eloop.terminate = 1; 365209139Srpaulo} 366209139Srpaulo 367209139Srpaulo 368209139Srpaulovoid eloop_destroy(void) 369209139Srpaulo{ 370209139Srpaulo struct eloop_timeout *timeout, *prev; 371209139Srpaulo 372209139Srpaulo timeout = eloop.timeout; 373209139Srpaulo while (timeout != NULL) { 374209139Srpaulo prev = timeout; 375209139Srpaulo timeout = timeout->next; 376209139Srpaulo free(prev); 377209139Srpaulo } 378209139Srpaulo free(eloop.readers); 379209139Srpaulo free(eloop.signals); 380209139Srpaulo} 381209139Srpaulo 382209139Srpaulo 383209139Srpauloint eloop_terminated(void) 384209139Srpaulo{ 385209139Srpaulo return eloop.terminate; 386209139Srpaulo} 387209139Srpaulo 388209139Srpaulo 389209139Srpaulovoid eloop_wait_for_read_sock(int sock) 390209139Srpaulo{ 391209139Srpaulo /* 392209139Srpaulo * TODO: wait for the file descriptor to have something available for 393209139Srpaulo * reading 394209139Srpaulo */ 395209139Srpaulo} 396