diff options
author | sam <sam@FreeBSD.org> | 2007-07-09 16:15:06 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2007-07-09 16:15:06 +0000 |
commit | 1bf2fd00c50865c26197a0fb9ce70f417b9fa121 (patch) | |
tree | c6f336fc28b042f00efc2373c71fceadfa394e52 /contrib/hostapd/eloop.c | |
parent | 620bfba12034be7d2ad4a357063d609ff5b6e63a (diff) | |
download | FreeBSD-src-1bf2fd00c50865c26197a0fb9ce70f417b9fa121.zip FreeBSD-src-1bf2fd00c50865c26197a0fb9ce70f417b9fa121.tar.gz |
Import of hostapd 0.5.8
Diffstat (limited to 'contrib/hostapd/eloop.c')
-rw-r--r-- | contrib/hostapd/eloop.c | 332 |
1 files changed, 237 insertions, 95 deletions
diff --git a/contrib/hostapd/eloop.c b/contrib/hostapd/eloop.c index 39fccb8..232e753 100644 --- a/contrib/hostapd/eloop.c +++ b/contrib/hostapd/eloop.c @@ -1,6 +1,6 @@ /* * Event loop based on select() loop - * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> + * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,19 +12,9 @@ * See README and COPYING for more details. */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <errno.h> -#include <signal.h> +#include "includes.h" -#ifdef CONFIG_NATIVE_WINDOWS #include "common.h" -#endif /* CONFIG_NATIVE_WINDOWS */ - #include "eloop.h" @@ -32,29 +22,38 @@ struct eloop_sock { int sock; void *eloop_data; void *user_data; - void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); + eloop_sock_handler handler; }; struct eloop_timeout { - struct timeval time; + struct os_time time; void *eloop_data; void *user_data; - void (*handler)(void *eloop_ctx, void *sock_ctx); + eloop_timeout_handler handler; struct eloop_timeout *next; }; struct eloop_signal { int sig; void *user_data; - void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); + eloop_signal_handler handler; int signaled; }; +struct eloop_sock_table { + int count; + struct eloop_sock *table; + int changed; +}; + struct eloop_data { void *user_data; - int max_sock, reader_count; - struct eloop_sock *readers; + int max_sock; + + struct eloop_sock_table readers; + struct eloop_sock_table writers; + struct eloop_sock_table exceptions; struct eloop_timeout *timeout; @@ -64,81 +63,181 @@ struct eloop_data { int pending_terminate; int terminate; + int reader_table_changed; }; static struct eloop_data eloop; -void eloop_init(void *user_data) +int eloop_init(void *user_data) { - memset(&eloop, 0, sizeof(eloop)); + os_memset(&eloop, 0, sizeof(eloop)); eloop.user_data = user_data; + return 0; } -int eloop_register_read_sock(int sock, - void (*handler)(int sock, void *eloop_ctx, - void *sock_ctx), - void *eloop_data, void *user_data) +static int eloop_sock_table_add_sock(struct eloop_sock_table *table, + int sock, eloop_sock_handler handler, + void *eloop_data, void *user_data) { struct eloop_sock *tmp; + if (table == NULL) + return -1; + tmp = (struct eloop_sock *) - realloc(eloop.readers, - (eloop.reader_count + 1) * sizeof(struct eloop_sock)); + os_realloc(table->table, + (table->count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) return -1; - tmp[eloop.reader_count].sock = sock; - tmp[eloop.reader_count].eloop_data = eloop_data; - tmp[eloop.reader_count].user_data = user_data; - tmp[eloop.reader_count].handler = handler; - eloop.reader_count++; - eloop.readers = tmp; + tmp[table->count].sock = sock; + tmp[table->count].eloop_data = eloop_data; + tmp[table->count].user_data = user_data; + tmp[table->count].handler = handler; + table->count++; + table->table = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; + table->changed = 1; return 0; } -void eloop_unregister_read_sock(int sock) +static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, + int sock) { int i; - if (eloop.readers == NULL || eloop.reader_count == 0) + if (table == NULL || table->table == NULL || table->count == 0) return; - for (i = 0; i < eloop.reader_count; i++) { - if (eloop.readers[i].sock == sock) + for (i = 0; i < table->count; i++) { + if (table->table[i].sock == sock) break; } - if (i == eloop.reader_count) + if (i == table->count) return; - if (i != eloop.reader_count - 1) { - memmove(&eloop.readers[i], &eloop.readers[i + 1], - (eloop.reader_count - i - 1) * - sizeof(struct eloop_sock)); + if (i != table->count - 1) { + os_memmove(&table->table[i], &table->table[i + 1], + (table->count - i - 1) * + sizeof(struct eloop_sock)); + } + table->count--; + table->changed = 1; +} + + +static void eloop_sock_table_set_fds(struct eloop_sock_table *table, + fd_set *fds) +{ + int i; + + FD_ZERO(fds); + + if (table->table == NULL) + return; + + for (i = 0; i < table->count; i++) + FD_SET(table->table[i].sock, fds); +} + + +static void eloop_sock_table_dispatch(struct eloop_sock_table *table, + fd_set *fds) +{ + int i; + + if (table == NULL || table->table == NULL) + return; + + table->changed = 0; + for (i = 0; i < table->count; i++) { + if (FD_ISSET(table->table[i].sock, fds)) { + table->table[i].handler(table->table[i].sock, + table->table[i].eloop_data, + table->table[i].user_data); + if (table->changed) + break; + } + } +} + + +static void eloop_sock_table_destroy(struct eloop_sock_table *table) +{ + if (table) + os_free(table->table); +} + + +int eloop_register_read_sock(int sock, eloop_sock_handler handler, + void *eloop_data, void *user_data) +{ + return eloop_register_sock(sock, EVENT_TYPE_READ, handler, + eloop_data, user_data); +} + + +void eloop_unregister_read_sock(int sock) +{ + eloop_unregister_sock(sock, EVENT_TYPE_READ); +} + + +static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) +{ + switch (type) { + case EVENT_TYPE_READ: + return &eloop.readers; + case EVENT_TYPE_WRITE: + return &eloop.writers; + case EVENT_TYPE_EXCEPTION: + return &eloop.exceptions; } - eloop.reader_count--; + + return NULL; +} + + +int eloop_register_sock(int sock, eloop_event_type type, + eloop_sock_handler handler, + void *eloop_data, void *user_data) +{ + struct eloop_sock_table *table; + + table = eloop_get_sock_table(type); + return eloop_sock_table_add_sock(table, sock, handler, + eloop_data, user_data); +} + + +void eloop_unregister_sock(int sock, eloop_event_type type) +{ + struct eloop_sock_table *table; + + table = eloop_get_sock_table(type); + eloop_sock_table_remove_sock(table, sock); } int eloop_register_timeout(unsigned int secs, unsigned int usecs, - void (*handler)(void *eloop_ctx, void *timeout_ctx), + eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp, *prev; - timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); + timeout = os_malloc(sizeof(*timeout)); if (timeout == NULL) return -1; - gettimeofday(&timeout->time, NULL); - timeout->time.tv_sec += secs; - timeout->time.tv_usec += usecs; - while (timeout->time.tv_usec >= 1000000) { - timeout->time.tv_sec++; - timeout->time.tv_usec -= 1000000; + os_get_time(&timeout->time); + timeout->time.sec += secs; + timeout->time.usec += usecs; + while (timeout->time.usec >= 1000000) { + timeout->time.sec++; + timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; @@ -153,7 +252,7 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs, prev = NULL; tmp = eloop.timeout; while (tmp != NULL) { - if (timercmp(&timeout->time, &tmp->time, <)) + if (os_time_before(&timeout->time, &tmp->time)) break; prev = tmp; tmp = tmp->next; @@ -171,7 +270,7 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs, } -int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), +int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev, *next; @@ -191,7 +290,7 @@ int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), eloop.timeout = next; else prev->next = next; - free(timeout); + os_free(timeout); removed++; } else prev = timeout; @@ -266,17 +365,15 @@ static void eloop_process_pending_signals(void) } -int eloop_register_signal(int sig, - void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), +int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data) { struct eloop_signal *tmp; tmp = (struct eloop_signal *) - realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); + os_realloc(eloop.signals, + (eloop.signal_count + 1) * + sizeof(struct eloop_signal)); if (tmp == NULL) return -1; @@ -292,41 +389,67 @@ int eloop_register_signal(int sig, } -void eloop_run(void) +int eloop_register_signal_terminate(eloop_signal_handler handler, + void *user_data) { - fd_set *rfds; - int i, res; - struct timeval tv, now; + int ret = eloop_register_signal(SIGINT, handler, user_data); + if (ret == 0) + ret = eloop_register_signal(SIGTERM, handler, user_data); + return ret; +} + - rfds = malloc(sizeof(*rfds)); - if (rfds == NULL) { +int eloop_register_signal_reconfig(eloop_signal_handler handler, + void *user_data) +{ +#ifdef CONFIG_NATIVE_WINDOWS + return 0; +#else /* CONFIG_NATIVE_WINDOWS */ + return eloop_register_signal(SIGHUP, handler, user_data); +#endif /* CONFIG_NATIVE_WINDOWS */ +} + + +void eloop_run(void) +{ + fd_set *rfds, *wfds, *efds; + int res; + struct timeval _tv; + struct os_time tv, now; + + rfds = os_malloc(sizeof(*rfds)); + wfds = os_malloc(sizeof(*wfds)); + efds = os_malloc(sizeof(*efds)); + if (rfds == NULL || wfds == NULL || efds == NULL) { printf("eloop_run - malloc failed\n"); - return; + goto out; } while (!eloop.terminate && - (eloop.timeout || eloop.reader_count > 0)) { + (eloop.timeout || eloop.readers.count > 0 || + eloop.writers.count > 0 || eloop.exceptions.count > 0)) { if (eloop.timeout) { - gettimeofday(&now, NULL); - if (timercmp(&now, &eloop.timeout->time, <)) - timersub(&eloop.timeout->time, &now, &tv); + os_get_time(&now); + if (os_time_before(&now, &eloop.timeout->time)) + os_time_sub(&eloop.timeout->time, &now, &tv); else - tv.tv_sec = tv.tv_usec = 0; + tv.sec = tv.usec = 0; #if 0 printf("next timeout in %lu.%06lu sec\n", - tv.tv_sec, tv.tv_usec); + tv.sec, tv.usec); #endif + _tv.tv_sec = tv.sec; + _tv.tv_usec = tv.usec; } - FD_ZERO(rfds); - for (i = 0; i < eloop.reader_count; i++) - FD_SET(eloop.readers[i].sock, rfds); - res = select(eloop.max_sock + 1, rfds, NULL, NULL, - eloop.timeout ? &tv : NULL); - if (res < 0 && errno != EINTR) { + eloop_sock_table_set_fds(&eloop.readers, rfds); + eloop_sock_table_set_fds(&eloop.writers, wfds); + eloop_sock_table_set_fds(&eloop.exceptions, efds); + res = select(eloop.max_sock + 1, rfds, wfds, efds, + eloop.timeout ? &_tv : NULL); + if (res < 0 && errno != EINTR && errno != 0) { perror("select"); - free(rfds); - return; + goto out; } eloop_process_pending_signals(); @@ -334,13 +457,13 @@ void eloop_run(void) if (eloop.timeout) { struct eloop_timeout *tmp; - gettimeofday(&now, NULL); - if (!timercmp(&now, &eloop.timeout->time, <)) { + os_get_time(&now); + if (!os_time_before(&now, &eloop.timeout->time)) { tmp = eloop.timeout; eloop.timeout = eloop.timeout->next; tmp->handler(tmp->eloop_data, tmp->user_data); - free(tmp); + os_free(tmp); } } @@ -348,17 +471,15 @@ void eloop_run(void) if (res <= 0) continue; - for (i = 0; i < eloop.reader_count; i++) { - if (FD_ISSET(eloop.readers[i].sock, rfds)) { - eloop.readers[i].handler( - eloop.readers[i].sock, - eloop.readers[i].eloop_data, - eloop.readers[i].user_data); - } - } + eloop_sock_table_dispatch(&eloop.readers, rfds); + eloop_sock_table_dispatch(&eloop.writers, wfds); + eloop_sock_table_dispatch(&eloop.exceptions, efds); } - free(rfds); +out: + os_free(rfds); + os_free(wfds); + os_free(efds); } @@ -376,10 +497,12 @@ void eloop_destroy(void) while (timeout != NULL) { prev = timeout; timeout = timeout->next; - free(prev); + os_free(prev); } - free(eloop.readers); - free(eloop.signals); + eloop_sock_table_destroy(&eloop.readers); + eloop_sock_table_destroy(&eloop.writers); + eloop_sock_table_destroy(&eloop.exceptions); + os_free(eloop.signals); } @@ -387,3 +510,22 @@ int eloop_terminated(void) { return eloop.terminate; } + + +void eloop_wait_for_read_sock(int sock) +{ + fd_set rfds; + + if (sock < 0) + return; + + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + select(sock + 1, &rfds, NULL, NULL, NULL); +} + + +void * eloop_get_user_data(void) +{ + return eloop.user_data; +} |