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 os_free(table->table);
00174 }
00175
00176
00177 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
00178 void *eloop_data, void *user_data)
00179 {
00180 return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
00181 eloop_data, user_data);
00182 }
00183
00184
00185 void eloop_unregister_read_sock(int sock)
00186 {
00187 eloop_unregister_sock(sock, EVENT_TYPE_READ);
00188 }
00189
00190
00191 static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
00192 {
00193 switch (type) {
00194 case EVENT_TYPE_READ:
00195 return &eloop.readers;
00196 case EVENT_TYPE_WRITE:
00197 return &eloop.writers;
00198 case EVENT_TYPE_EXCEPTION:
00199 return &eloop.exceptions;
00200 }
00201
00202 return NULL;
00203 }
00204
00205
00206 int eloop_register_sock(int sock, eloop_event_type type,
00207 eloop_sock_handler handler,
00208 void *eloop_data, void *user_data)
00209 {
00210 struct eloop_sock_table *table;
00211
00212 table = eloop_get_sock_table(type);
00213 return eloop_sock_table_add_sock(table, sock, handler,
00214 eloop_data, user_data);
00215 }
00216
00217
00218 void eloop_unregister_sock(int sock, eloop_event_type type)
00219 {
00220 struct eloop_sock_table *table;
00221
00222 table = eloop_get_sock_table(type);
00223 eloop_sock_table_remove_sock(table, sock);
00224 }
00225
00226
00227 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
00228 eloop_timeout_handler handler,
00229 void *eloop_data, void *user_data)
00230 {
00231 struct eloop_timeout *timeout, *tmp, *prev;
00232
00233 timeout = os_malloc(sizeof(*timeout));
00234 if (timeout == NULL)
00235 return -1;
00236 os_get_time(&timeout->time);
00237 timeout->time.sec += secs;
00238 timeout->time.usec += usecs;
00239 while (timeout->time.usec >= 1000000) {
00240 timeout->time.sec++;
00241 timeout->time.usec -= 1000000;
00242 }
00243 timeout->eloop_data = eloop_data;
00244 timeout->user_data = user_data;
00245 timeout->handler = handler;
00246 timeout->next = NULL;
00247
00248 if (eloop.timeout == NULL) {
00249 eloop.timeout = timeout;
00250 return 0;
00251 }
00252
00253 prev = NULL;
00254 tmp = eloop.timeout;
00255 while (tmp != NULL) {
00256 if (os_time_before(&timeout->time, &tmp->time))
00257 break;
00258 prev = tmp;
00259 tmp = tmp->next;
00260 }
00261
00262 if (prev == NULL) {
00263 timeout->next = eloop.timeout;
00264 eloop.timeout = timeout;
00265 } else {
00266 timeout->next = prev->next;
00267 prev->next = timeout;
00268 }
00269
00270 return 0;
00271 }
00272
00273
00274 int eloop_cancel_timeout(eloop_timeout_handler handler,
00275 void *eloop_data, void *user_data)
00276 {
00277 struct eloop_timeout *timeout, *prev, *next;
00278 int removed = 0;
00279
00280 prev = NULL;
00281 timeout = eloop.timeout;
00282 while (timeout != NULL) {
00283 next = timeout->next;
00284
00285 if (timeout->handler == handler &&
00286 (timeout->eloop_data == eloop_data ||
00287 eloop_data == ELOOP_ALL_CTX) &&
00288 (timeout->user_data == user_data ||
00289 user_data == ELOOP_ALL_CTX)) {
00290 if (prev == NULL)
00291 eloop.timeout = next;
00292 else
00293 prev->next = next;
00294 os_free(timeout);
00295 removed++;
00296 } else
00297 prev = timeout;
00298
00299 timeout = next;
00300 }
00301
00302 return removed;
00303 }
00304
00305
00306 #ifndef CONFIG_NATIVE_WINDOWS
00307 static void eloop_handle_alarm(int sig)
00308 {
00309 fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
00310 "seconds. Looks like there\n"
00311 "is a bug that ends up in a busy loop that "
00312 "prevents clean shutdown.\n"
00313 "Killing program forcefully.\n");
00314 exit(1);
00315 }
00316 #endif
00317
00318
00319 static void eloop_handle_signal(int sig)
00320 {
00321 int i;
00322
00323 #ifndef CONFIG_NATIVE_WINDOWS
00324 if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
00325
00326
00327 eloop.pending_terminate = 1;
00328 signal(SIGALRM, eloop_handle_alarm);
00329 alarm(2);
00330 }
00331 #endif
00332
00333 eloop.signaled++;
00334 for (i = 0; i < eloop.signal_count; i++) {
00335 if (eloop.signals[i].sig == sig) {
00336 eloop.signals[i].signaled++;
00337 break;
00338 }
00339 }
00340 }
00341
00342
00343 static void eloop_process_pending_signals(void)
00344 {
00345 int i;
00346
00347 if (eloop.signaled == 0)
00348 return;
00349 eloop.signaled = 0;
00350
00351 if (eloop.pending_terminate) {
00352 #ifndef CONFIG_NATIVE_WINDOWS
00353 alarm(0);
00354 #endif
00355 eloop.pending_terminate = 0;
00356 }
00357
00358 for (i = 0; i < eloop.signal_count; i++) {
00359 if (eloop.signals[i].signaled) {
00360 eloop.signals[i].signaled = 0;
00361 eloop.signals[i].handler(eloop.signals[i].sig,
00362 eloop.user_data,
00363 eloop.signals[i].user_data);
00364 }
00365 }
00366 }
00367
00368
00369 int eloop_register_signal(int sig, eloop_signal_handler handler,
00370 void *user_data)
00371 {
00372 struct eloop_signal *tmp;
00373
00374 tmp = (struct eloop_signal *)
00375 os_realloc(eloop.signals,
00376 (eloop.signal_count + 1) *
00377 sizeof(struct eloop_signal));
00378 if (tmp == NULL)
00379 return -1;
00380
00381 tmp[eloop.signal_count].sig = sig;
00382 tmp[eloop.signal_count].user_data = user_data;
00383 tmp[eloop.signal_count].handler = handler;
00384 tmp[eloop.signal_count].signaled = 0;
00385 eloop.signal_count++;
00386 eloop.signals = tmp;
00387 signal(sig, eloop_handle_signal);
00388
00389 return 0;
00390 }
00391
00392
00393 int eloop_register_signal_terminate(eloop_signal_handler handler,
00394 void *user_data)
00395 {
00396 int ret = eloop_register_signal(SIGINT, handler, user_data);
00397 if (ret == 0)
00398 ret = eloop_register_signal(SIGTERM, handler, user_data);
00399 return ret;
00400 }
00401
00402
00403 int eloop_register_signal_reconfig(eloop_signal_handler handler,
00404 void *user_data)
00405 {
00406 #ifdef CONFIG_NATIVE_WINDOWS
00407 return 0;
00408 #else
00409 return eloop_register_signal(SIGHUP, handler, user_data);
00410 #endif
00411 }
00412
00413
00414 void eloop_run(void)
00415 {
00416 fd_set *rfds, *wfds, *efds;
00417 int res;
00418 struct timeval _tv;
00419 struct os_time tv, now;
00420
00421 rfds = os_malloc(sizeof(*rfds));
00422 wfds = os_malloc(sizeof(*wfds));
00423 efds = os_malloc(sizeof(*efds));
00424 if (rfds == NULL || wfds == NULL || efds == NULL) {
00425 printf("eloop_run - malloc failed\n");
00426 goto out;
00427 }
00428
00429 while (!eloop.terminate &&
00430 (eloop.timeout || eloop.readers.count > 0 ||
00431 eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
00432 if (eloop.timeout) {
00433 os_get_time(&now);
00434 if (os_time_before(&now, &eloop.timeout->time))
00435 os_time_sub(&eloop.timeout->time, &now, &tv);
00436 else
00437 tv.sec = tv.usec = 0;
00438 #if 0
00439 printf("next timeout in %lu.%06lu sec\n",
00440 tv.sec, tv.usec);
00441 #endif
00442 _tv.tv_sec = tv.sec;
00443 _tv.tv_usec = tv.usec;
00444 }
00445
00446 eloop_sock_table_set_fds(&eloop.readers, rfds);
00447 eloop_sock_table_set_fds(&eloop.writers, wfds);
00448 eloop_sock_table_set_fds(&eloop.exceptions, efds);
00449 res = select(eloop.max_sock + 1, rfds, wfds, efds,
00450 eloop.timeout ? &_tv : NULL);
00451 if (res < 0 && errno != EINTR && errno != 0) {
00452 perror("select");
00453 goto out;
00454 }
00455 eloop_process_pending_signals();
00456
00457
00458 if (eloop.timeout) {
00459 struct eloop_timeout *tmp;
00460
00461 os_get_time(&now);
00462 if (!os_time_before(&now, &eloop.timeout->time)) {
00463 tmp = eloop.timeout;
00464 eloop.timeout = eloop.timeout->next;
00465 tmp->handler(tmp->eloop_data,
00466 tmp->user_data);
00467 os_free(tmp);
00468 }
00469
00470 }
00471
00472 if (res <= 0)
00473 continue;
00474
00475 eloop_sock_table_dispatch(&eloop.readers, rfds);
00476 eloop_sock_table_dispatch(&eloop.writers, wfds);
00477 eloop_sock_table_dispatch(&eloop.exceptions, efds);
00478 }
00479
00480 out:
00481 os_free(rfds);
00482 os_free(wfds);
00483 os_free(efds);
00484 }
00485
00486
00487 void eloop_terminate(void)
00488 {
00489 eloop.terminate = 1;
00490 }
00491
00492
00493 void eloop_destroy(void)
00494 {
00495 struct eloop_timeout *timeout, *prev;
00496
00497 timeout = eloop.timeout;
00498 while (timeout != NULL) {
00499 prev = timeout;
00500 timeout = timeout->next;
00501 os_free(prev);
00502 }
00503 eloop_sock_table_destroy(&eloop.readers);
00504 eloop_sock_table_destroy(&eloop.writers);
00505 eloop_sock_table_destroy(&eloop.exceptions);
00506 os_free(eloop.signals);
00507 }
00508
00509
00510 int eloop_terminated(void)
00511 {
00512 return eloop.terminate;
00513 }
00514
00515
00516 void eloop_wait_for_read_sock(int sock)
00517 {
00518 fd_set rfds;
00519
00520 if (sock < 0)
00521 return;
00522
00523 FD_ZERO(&rfds);
00524 FD_SET(sock, &rfds);
00525 select(sock + 1, &rfds, NULL, NULL, NULL);
00526 }
00527
00528
00529 void * eloop_get_user_data(void)
00530 {
00531 return eloop.user_data;
00532 }
00533