00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "trace.h"
00019 #include "list.h"
00020 #include "eloop.h"
00021
00022
00023 struct eloop_sock {
00024 int sock;
00025 void *eloop_data;
00026 void *user_data;
00027 eloop_sock_handler handler;
00028 WPA_TRACE_REF(eloop);
00029 WPA_TRACE_REF(user);
00030 WPA_TRACE_INFO
00031 };
00032
00033 struct eloop_timeout {
00034 struct dl_list list;
00035 struct os_time time;
00036 void *eloop_data;
00037 void *user_data;
00038 eloop_timeout_handler handler;
00039 WPA_TRACE_REF(eloop);
00040 WPA_TRACE_REF(user);
00041 WPA_TRACE_INFO
00042 };
00043
00044 struct eloop_signal {
00045 int sig;
00046 void *user_data;
00047 eloop_signal_handler handler;
00048 int signaled;
00049 };
00050
00051 struct eloop_sock_table {
00052 int count;
00053 struct eloop_sock *table;
00054 int changed;
00055 };
00056
00057 struct eloop_data {
00058 int max_sock;
00059
00060 struct eloop_sock_table readers;
00061 struct eloop_sock_table writers;
00062 struct eloop_sock_table exceptions;
00063
00064 struct dl_list timeout;
00065
00066 int signal_count;
00067 struct eloop_signal *signals;
00068 int signaled;
00069 int pending_terminate;
00070
00071 int terminate;
00072 int reader_table_changed;
00073 };
00074
00075 static struct eloop_data eloop;
00076
00077
00078 #ifdef WPA_TRACE
00079
00080 static void eloop_sigsegv_handler(int sig)
00081 {
00082 wpa_trace_show("eloop SIGSEGV");
00083 abort();
00084 }
00085
00086 static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
00087 {
00088 int i;
00089 if (table == NULL || table->table == NULL)
00090 return;
00091 for (i = 0; i < table->count; i++) {
00092 wpa_trace_add_ref(&table->table[i], eloop,
00093 table->table[i].eloop_data);
00094 wpa_trace_add_ref(&table->table[i], user,
00095 table->table[i].user_data);
00096 }
00097 }
00098
00099
00100 static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
00101 {
00102 int i;
00103 if (table == NULL || table->table == NULL)
00104 return;
00105 for (i = 0; i < table->count; i++) {
00106 wpa_trace_remove_ref(&table->table[i], eloop,
00107 table->table[i].eloop_data);
00108 wpa_trace_remove_ref(&table->table[i], user,
00109 table->table[i].user_data);
00110 }
00111 }
00112
00113 #else
00114
00115 #define eloop_trace_sock_add_ref(table) do { } while (0)
00116 #define eloop_trace_sock_remove_ref(table) do { } while (0)
00117
00118 #endif
00119
00120
00121 int eloop_init(void)
00122 {
00123 os_memset(&eloop, 0, sizeof(eloop));
00124 dl_list_init(&eloop.timeout);
00125 #ifdef WPA_TRACE
00126 signal(SIGSEGV, eloop_sigsegv_handler);
00127 #endif
00128 return 0;
00129 }
00130
00131
00132 static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
00133 int sock, eloop_sock_handler handler,
00134 void *eloop_data, void *user_data)
00135 {
00136 struct eloop_sock *tmp;
00137
00138 if (table == NULL)
00139 return -1;
00140
00141 eloop_trace_sock_remove_ref(table);
00142 tmp = (struct eloop_sock *)
00143 os_realloc(table->table,
00144 (table->count + 1) * sizeof(struct eloop_sock));
00145 if (tmp == NULL)
00146 return -1;
00147
00148 tmp[table->count].sock = sock;
00149 tmp[table->count].eloop_data = eloop_data;
00150 tmp[table->count].user_data = user_data;
00151 tmp[table->count].handler = handler;
00152 wpa_trace_record(&tmp[table->count]);
00153 table->count++;
00154 table->table = tmp;
00155 if (sock > eloop.max_sock)
00156 eloop.max_sock = sock;
00157 table->changed = 1;
00158 eloop_trace_sock_add_ref(table);
00159
00160 return 0;
00161 }
00162
00163
00164 static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
00165 int sock)
00166 {
00167 int i;
00168
00169 if (table == NULL || table->table == NULL || table->count == 0)
00170 return;
00171
00172 for (i = 0; i < table->count; i++) {
00173 if (table->table[i].sock == sock)
00174 break;
00175 }
00176 if (i == table->count)
00177 return;
00178 eloop_trace_sock_remove_ref(table);
00179 if (i != table->count - 1) {
00180 os_memmove(&table->table[i], &table->table[i + 1],
00181 (table->count - i - 1) *
00182 sizeof(struct eloop_sock));
00183 }
00184 table->count--;
00185 table->changed = 1;
00186 eloop_trace_sock_add_ref(table);
00187 }
00188
00189
00190 static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
00191 fd_set *fds)
00192 {
00193 int i;
00194
00195 FD_ZERO(fds);
00196
00197 if (table->table == NULL)
00198 return;
00199
00200 for (i = 0; i < table->count; i++)
00201 FD_SET(table->table[i].sock, fds);
00202 }
00203
00204
00205 static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
00206 fd_set *fds)
00207 {
00208 int i;
00209
00210 if (table == NULL || table->table == NULL)
00211 return;
00212
00213 table->changed = 0;
00214 for (i = 0; i < table->count; i++) {
00215 if (FD_ISSET(table->table[i].sock, fds)) {
00216 table->table[i].handler(table->table[i].sock,
00217 table->table[i].eloop_data,
00218 table->table[i].user_data);
00219 if (table->changed)
00220 break;
00221 }
00222 }
00223 }
00224
00225
00226 static void eloop_sock_table_destroy(struct eloop_sock_table *table)
00227 {
00228 if (table) {
00229 int i;
00230 for (i = 0; i < table->count && table->table; i++) {
00231 wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
00232 "sock=%d eloop_data=%p user_data=%p "
00233 "handler=%p",
00234 table->table[i].sock,
00235 table->table[i].eloop_data,
00236 table->table[i].user_data,
00237 table->table[i].handler);
00238 wpa_trace_dump_funcname("eloop unregistered socket "
00239 "handler",
00240 table->table[i].handler);
00241 wpa_trace_dump("eloop sock", &table->table[i]);
00242 }
00243 os_free(table->table);
00244 }
00245 }
00246
00247
00248 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
00249 void *eloop_data, void *user_data)
00250 {
00251 return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
00252 eloop_data, user_data);
00253 }
00254
00255
00256 void eloop_unregister_read_sock(int sock)
00257 {
00258 eloop_unregister_sock(sock, EVENT_TYPE_READ);
00259 }
00260
00261
00262 static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
00263 {
00264 switch (type) {
00265 case EVENT_TYPE_READ:
00266 return &eloop.readers;
00267 case EVENT_TYPE_WRITE:
00268 return &eloop.writers;
00269 case EVENT_TYPE_EXCEPTION:
00270 return &eloop.exceptions;
00271 }
00272
00273 return NULL;
00274 }
00275
00276
00277 int eloop_register_sock(int sock, eloop_event_type type,
00278 eloop_sock_handler handler,
00279 void *eloop_data, void *user_data)
00280 {
00281 struct eloop_sock_table *table;
00282
00283 table = eloop_get_sock_table(type);
00284 return eloop_sock_table_add_sock(table, sock, handler,
00285 eloop_data, user_data);
00286 }
00287
00288
00289 void eloop_unregister_sock(int sock, eloop_event_type type)
00290 {
00291 struct eloop_sock_table *table;
00292
00293 table = eloop_get_sock_table(type);
00294 eloop_sock_table_remove_sock(table, sock);
00295 }
00296
00297
00298 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
00299 eloop_timeout_handler handler,
00300 void *eloop_data, void *user_data)
00301 {
00302 struct eloop_timeout *timeout, *tmp;
00303
00304 timeout = os_zalloc(sizeof(*timeout));
00305 if (timeout == NULL)
00306 return -1;
00307 if (os_get_time(&timeout->time) < 0) {
00308 os_free(timeout);
00309 return -1;
00310 }
00311 timeout->time.sec += secs;
00312 timeout->time.usec += usecs;
00313 while (timeout->time.usec >= 1000000) {
00314 timeout->time.sec++;
00315 timeout->time.usec -= 1000000;
00316 }
00317 timeout->eloop_data = eloop_data;
00318 timeout->user_data = user_data;
00319 timeout->handler = handler;
00320 wpa_trace_add_ref(timeout, eloop, eloop_data);
00321 wpa_trace_add_ref(timeout, user, user_data);
00322 wpa_trace_record(timeout);
00323
00324
00325 dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
00326 if (os_time_before(&timeout->time, &tmp->time)) {
00327 dl_list_add(tmp->list.prev, &timeout->list);
00328 return 0;
00329 }
00330 }
00331 dl_list_add_tail(&eloop.timeout, &timeout->list);
00332
00333 return 0;
00334 }
00335
00336
00337 static void eloop_remove_timeout(struct eloop_timeout *timeout)
00338 {
00339 dl_list_del(&timeout->list);
00340 wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
00341 wpa_trace_remove_ref(timeout, user, timeout->user_data);
00342 os_free(timeout);
00343 }
00344
00345
00346 int eloop_cancel_timeout(eloop_timeout_handler handler,
00347 void *eloop_data, void *user_data)
00348 {
00349 struct eloop_timeout *timeout, *prev;
00350 int removed = 0;
00351
00352 dl_list_for_each_safe(timeout, prev, &eloop.timeout,
00353 struct eloop_timeout, list) {
00354 if (timeout->handler == handler &&
00355 (timeout->eloop_data == eloop_data ||
00356 eloop_data == ELOOP_ALL_CTX) &&
00357 (timeout->user_data == user_data ||
00358 user_data == ELOOP_ALL_CTX)) {
00359 eloop_remove_timeout(timeout);
00360 removed++;
00361 }
00362 }
00363
00364 return removed;
00365 }
00366
00367
00368 int eloop_is_timeout_registered(eloop_timeout_handler handler,
00369 void *eloop_data, void *user_data)
00370 {
00371 struct eloop_timeout *tmp;
00372
00373 dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
00374 if (tmp->handler == handler &&
00375 tmp->eloop_data == eloop_data &&
00376 tmp->user_data == user_data)
00377 return 1;
00378 }
00379
00380 return 0;
00381 }
00382
00383
00384 #ifndef CONFIG_NATIVE_WINDOWS
00385 static void eloop_handle_alarm(int sig)
00386 {
00387 wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
00388 "two seconds. Looks like there\n"
00389 "is a bug that ends up in a busy loop that "
00390 "prevents clean shutdown.\n"
00391 "Killing program forcefully.\n");
00392 exit(1);
00393 }
00394 #endif
00395
00396
00397 static void eloop_handle_signal(int sig)
00398 {
00399 int i;
00400
00401 #ifndef CONFIG_NATIVE_WINDOWS
00402 if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
00403
00404
00405 eloop.pending_terminate = 1;
00406 signal(SIGALRM, eloop_handle_alarm);
00407 alarm(2);
00408 }
00409 #endif
00410
00411 eloop.signaled++;
00412 for (i = 0; i < eloop.signal_count; i++) {
00413 if (eloop.signals[i].sig == sig) {
00414 eloop.signals[i].signaled++;
00415 break;
00416 }
00417 }
00418 }
00419
00420
00421 static void eloop_process_pending_signals(void)
00422 {
00423 int i;
00424
00425 if (eloop.signaled == 0)
00426 return;
00427 eloop.signaled = 0;
00428
00429 if (eloop.pending_terminate) {
00430 #ifndef CONFIG_NATIVE_WINDOWS
00431 alarm(0);
00432 #endif
00433 eloop.pending_terminate = 0;
00434 }
00435
00436 for (i = 0; i < eloop.signal_count; i++) {
00437 if (eloop.signals[i].signaled) {
00438 eloop.signals[i].signaled = 0;
00439 eloop.signals[i].handler(eloop.signals[i].sig,
00440 eloop.signals[i].user_data);
00441 }
00442 }
00443 }
00444
00445
00446 int eloop_register_signal(int sig, eloop_signal_handler handler,
00447 void *user_data)
00448 {
00449 struct eloop_signal *tmp;
00450
00451 tmp = (struct eloop_signal *)
00452 os_realloc(eloop.signals,
00453 (eloop.signal_count + 1) *
00454 sizeof(struct eloop_signal));
00455 if (tmp == NULL)
00456 return -1;
00457
00458 tmp[eloop.signal_count].sig = sig;
00459 tmp[eloop.signal_count].user_data = user_data;
00460 tmp[eloop.signal_count].handler = handler;
00461 tmp[eloop.signal_count].signaled = 0;
00462 eloop.signal_count++;
00463 eloop.signals = tmp;
00464 signal(sig, eloop_handle_signal);
00465
00466 return 0;
00467 }
00468
00469
00470 int eloop_register_signal_terminate(eloop_signal_handler handler,
00471 void *user_data)
00472 {
00473 int ret = eloop_register_signal(SIGINT, handler, user_data);
00474 if (ret == 0)
00475 ret = eloop_register_signal(SIGTERM, handler, user_data);
00476 return ret;
00477 }
00478
00479
00480 int eloop_register_signal_reconfig(eloop_signal_handler handler,
00481 void *user_data)
00482 {
00483 #ifdef CONFIG_NATIVE_WINDOWS
00484 return 0;
00485 #else
00486 return eloop_register_signal(SIGHUP, handler, user_data);
00487 #endif
00488 }
00489
00490
00491 void eloop_run(void)
00492 {
00493 fd_set *rfds, *wfds, *efds;
00494 int res;
00495 struct timeval _tv;
00496 struct os_time tv, now;
00497
00498 rfds = os_malloc(sizeof(*rfds));
00499 wfds = os_malloc(sizeof(*wfds));
00500 efds = os_malloc(sizeof(*efds));
00501 if (rfds == NULL || wfds == NULL || efds == NULL)
00502 goto out;
00503
00504 while (!eloop.terminate &&
00505 (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
00506 eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
00507 struct eloop_timeout *timeout;
00508 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
00509 list);
00510 if (timeout) {
00511 os_get_time(&now);
00512 if (os_time_before(&now, &timeout->time))
00513 os_time_sub(&timeout->time, &now, &tv);
00514 else
00515 tv.sec = tv.usec = 0;
00516 _tv.tv_sec = tv.sec;
00517 _tv.tv_usec = tv.usec;
00518 }
00519
00520 eloop_sock_table_set_fds(&eloop.readers, rfds);
00521 eloop_sock_table_set_fds(&eloop.writers, wfds);
00522 eloop_sock_table_set_fds(&eloop.exceptions, efds);
00523 res = select(eloop.max_sock + 1, rfds, wfds, efds,
00524 timeout ? &_tv : NULL);
00525 if (res < 0 && errno != EINTR && errno != 0) {
00526 perror("select");
00527 goto out;
00528 }
00529 eloop_process_pending_signals();
00530
00531
00532 if (timeout) {
00533 os_get_time(&now);
00534 if (!os_time_before(&now, &timeout->time)) {
00535 void *eloop_data = timeout->eloop_data;
00536 void *user_data = timeout->user_data;
00537 eloop_timeout_handler handler =
00538 timeout->handler;
00539 eloop_remove_timeout(timeout);
00540 handler(eloop_data, user_data);
00541 }
00542
00543 }
00544
00545 if (res <= 0)
00546 continue;
00547
00548 eloop_sock_table_dispatch(&eloop.readers, rfds);
00549 eloop_sock_table_dispatch(&eloop.writers, wfds);
00550 eloop_sock_table_dispatch(&eloop.exceptions, efds);
00551 }
00552
00553 out:
00554 os_free(rfds);
00555 os_free(wfds);
00556 os_free(efds);
00557 }
00558
00559
00560 void eloop_terminate(void)
00561 {
00562 eloop.terminate = 1;
00563 }
00564
00565
00566 void eloop_destroy(void)
00567 {
00568 struct eloop_timeout *timeout, *prev;
00569 struct os_time now;
00570
00571 os_get_time(&now);
00572 dl_list_for_each_safe(timeout, prev, &eloop.timeout,
00573 struct eloop_timeout, list) {
00574 int sec, usec;
00575 sec = timeout->time.sec - now.sec;
00576 usec = timeout->time.usec - now.usec;
00577 if (timeout->time.usec < now.usec) {
00578 sec--;
00579 usec += 1000000;
00580 }
00581 wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
00582 "eloop_data=%p user_data=%p handler=%p",
00583 sec, usec, timeout->eloop_data, timeout->user_data,
00584 timeout->handler);
00585 wpa_trace_dump_funcname("eloop unregistered timeout handler",
00586 timeout->handler);
00587 wpa_trace_dump("eloop timeout", timeout);
00588 eloop_remove_timeout(timeout);
00589 }
00590 eloop_sock_table_destroy(&eloop.readers);
00591 eloop_sock_table_destroy(&eloop.writers);
00592 eloop_sock_table_destroy(&eloop.exceptions);
00593 os_free(eloop.signals);
00594 }
00595
00596
00597 int eloop_terminated(void)
00598 {
00599 return eloop.terminate;
00600 }
00601
00602
00603 void eloop_wait_for_read_sock(int sock)
00604 {
00605 fd_set rfds;
00606
00607 if (sock < 0)
00608 return;
00609
00610 FD_ZERO(&rfds);
00611 FD_SET(sock, &rfds);
00612 select(sock + 1, &rfds, NULL, NULL, NULL);
00613 }