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