summaryrefslogtreecommitdiffstats
path: root/contrib/wpa_supplicant/eloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa_supplicant/eloop.c')
-rw-r--r--contrib/wpa_supplicant/eloop.c332
1 files changed, 237 insertions, 95 deletions
diff --git a/contrib/wpa_supplicant/eloop.c b/contrib/wpa_supplicant/eloop.c
index 39fccb8..232e753 100644
--- a/contrib/wpa_supplicant/eloop.c
+++ b/contrib/wpa_supplicant/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;
+}
OpenPOWER on IntegriCloud