summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-10-13 20:01:48 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-10-13 20:01:48 +0200
commitbc9f976d7fe70176aac4bc9c87205d6ac1f530cc (patch)
tree538690a93e5a2282710bc623ec8b23312998c605
parent8e810f5fd809bad3047ea9224dd058edd20a64ac (diff)
downloadffd-bc9f976d7fe70176aac4bc9c87205d6ac1f530cc.tar
ffd-bc9f976d7fe70176aac4bc9c87205d6ac1f530cc.zip
Add timeout queues
-rw-r--r--ffd/CMakeLists.txt1
-rw-r--r--ffd/ffd.c74
-rw-r--r--ffd/ffd.h1
-rw-r--r--ffd/queue.c42
-rw-r--r--ffd/queue.h69
-rw-r--r--ffd/util.h8
6 files changed, 162 insertions, 33 deletions
diff --git a/ffd/CMakeLists.txt b/ffd/CMakeLists.txt
index 1571580..432ac61 100644
--- a/ffd/CMakeLists.txt
+++ b/ffd/CMakeLists.txt
@@ -5,6 +5,7 @@ add_executable(ffd
ffd.c
neigh.c
netif.c
+ queue.c
send.c
tlv.c
util.c
diff --git a/ffd/ffd.c b/ffd/ffd.c
index 7af9b29..9351476 100644
--- a/ffd/ffd.c
+++ b/ffd/ffd.c
@@ -28,6 +28,7 @@
#include "neigh.h"
#include "netif.h"
#include "packet.h"
+#include "queue.h"
#include "tlv.h"
#include "tlv_types.h"
@@ -51,10 +52,10 @@ static char *mesh = "bat0";
int sockfd;
struct timespec now;
-ffd_node_id_t self;
+static ffd_queue_head *tasks;
+ffd_node_id_t self;
ffd_iface_t *iface_list = NULL;
-
ffd_announce_t *announce_list = NULL;
@@ -489,6 +490,8 @@ static void receive_packet(void) {
}
static void send_updates(void) {
+ fprintf(stderr, "debug: sending periodic updates.\n");
+
ffd_iface_t *iface;
for (iface = iface_list; iface; iface = iface->next) {
ffd_send_update(iface, NULL, NULL, false);
@@ -558,6 +561,36 @@ static void maintenance(void) {
}
}
+
+typedef struct _periodic_task_info {
+ void (*handle)(void);
+ unsigned delay;
+ unsigned interval;
+} periodic_task_info;
+
+
+static const periodic_task_info periodic_tasks [] = {
+ {maintenance, 0, FFD_MAINTENANCE_INTERVAL},
+ {ffd_send_hellos, FFD_HELLO_INTERVAL, FFD_HELLO_INTERVAL},
+ {send_updates, 1, FFD_UPDATE_INTERVAL},
+ {NULL}
+};
+
+
+static void handle_periodic_task(const struct timespec *timeout, void *arg) {
+ const periodic_task_info *info = arg;
+
+ info->handle();
+ ffd_queue_put_delayed(&tasks, handle_periodic_task, timeout, info->interval, arg);
+}
+
+static void register_periodic_tasks(void) {
+ const periodic_task_info *info;
+ for (info = periodic_tasks; info->handle; info++)
+ ffd_queue_put_delayed(&tasks, handle_periodic_task, &now, info->delay, (void*)info);
+}
+
+
int main() {
if (!check_config())
return 1;
@@ -569,44 +602,21 @@ int main() {
return 1;
update_time();
-
- struct timespec next_hello = now;
- struct timespec next_update = now;
- struct timespec next_maintenance = now;
+ register_periodic_tasks();
while (true) {
- int maintenance_timeout = timespec_diff(&next_maintenance, &now);
- if (maintenance_timeout <= 0) {
- maintenance();
-
- add_interval(&next_maintenance, FFD_MAINTENANCE_INTERVAL);
- }
-
- int hello_timeout = timespec_diff(&next_hello, &now);
- if (hello_timeout <= 0) {
- ffd_send_hellos();
-
- add_interval(&next_hello, FFD_HELLO_INTERVAL);
- }
-
- int update_timeout = timespec_diff(&next_update, &now);
- if (update_timeout <= 0) {
- fprintf(stderr, "Sending periodic update.\n");
- send_updates();
-
- add_interval(&next_update, FFD_UPDATE_INTERVAL);
- }
-
- int timeout = min(min(hello_timeout, update_timeout), maintenance_timeout);
- if (timeout <= 0)
- continue;
+ ffd_queue_run(&tasks);
struct pollfd fds[1];
+ int timeout = 10*ffd_queue_timeout(&tasks);
+ if (timeout < 0)
+ timeout = -1;
+
fds[0].fd = sockfd;
fds[0].events = POLLIN;
- poll(fds, 1, 10*timeout);
+ poll(fds, 1, timeout);
update_time();
diff --git a/ffd/ffd.h b/ffd/ffd.h
index bf00984..edba710 100644
--- a/ffd/ffd.h
+++ b/ffd/ffd.h
@@ -145,7 +145,6 @@ extern ffd_iface_t *iface_list;
extern ffd_announce_t *announce_list;
extern int sockfd;
-extern struct timespec now;
#define FFD_NODE_ID_UNSPEC ((ffd_node_id_t){})
diff --git a/ffd/queue.c b/ffd/queue.c
new file mode 100644
index 0000000..3729e50
--- /dev/null
+++ b/ffd/queue.c
@@ -0,0 +1,42 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "queue.h"
+
+
+void ffd_queue_put(ffd_queue_head **queue, ffd_queue_cb cb, const struct timespec *timeout, void *arg) {
+ while (*queue && timespec_after(timeout, &(*queue)->timeout))
+ queue = &(*queue)->next;
+
+ ffd_queue_head *entry = malloc(sizeof(ffd_queue_head));
+
+ entry->cb = cb;
+ entry->timeout = *timeout;
+ entry->arg = arg;
+
+ entry->next = *queue;
+ *queue = entry;
+}
diff --git a/ffd/queue.h b/ffd/queue.h
new file mode 100644
index 0000000..9fae53d
--- /dev/null
+++ b/ffd/queue.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _FFD_QUEUE_H_
+#define _FFD_QUEUE_H_
+
+#include "util.h"
+
+
+typedef void (*ffd_queue_cb)(const struct timespec *timeout, void *arg);
+
+typedef struct _ffd_queue_head {
+ struct _ffd_queue_head *next;
+ ffd_queue_cb cb;
+ struct timespec timeout;
+ void *arg;
+} ffd_queue_head;
+
+
+void ffd_queue_put(ffd_queue_head **queue, ffd_queue_cb cb, const struct timespec *timeout, void *arg);
+
+
+static inline void ffd_queue_put_delayed(ffd_queue_head **queue, ffd_queue_cb cb, const struct timespec *timeout, int delay, void *arg) {
+ struct timespec timeout_delayed = *timeout;
+ add_interval(&timeout_delayed, delay);
+ ffd_queue_put(queue, cb, &timeout_delayed, arg);
+}
+
+static inline void ffd_queue_run(ffd_queue_head **queue) {
+ while (*queue && timespec_after(&now, &(*queue)->timeout)) {
+ ffd_queue_head *entry = *queue;
+ *queue = (*queue)->next;
+
+ entry->cb(&entry->timeout, entry->arg);
+ free(entry);
+ }
+}
+
+static inline int ffd_queue_timeout(ffd_queue_head *const *queue) {
+ if (!*queue)
+ return -1;
+
+ return max(timespec_diff(&(*queue)->timeout, &now), 0);
+}
+
+#endif /* _FFD_QUEUE_H_ */
diff --git a/ffd/util.h b/ffd/util.h
index 9d481cb..0660b94 100644
--- a/ffd/util.h
+++ b/ffd/util.h
@@ -34,6 +34,9 @@
#include <time.h>
+extern struct timespec now;
+
+
bool file_readv(const char *file, const char *format, va_list ap);
void random_bytes(void *buffer, size_t len);
@@ -53,6 +56,11 @@ static inline bool are_eth_addrs_equal(const eth_addr_t *address1, const eth_add
return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]);
}
+static inline bool timespec_after(const struct timespec *tp1, const struct timespec *tp2) {
+ return (tp1->tv_sec > tp2->tv_sec ||
+ (tp1->tv_sec == tp2->tv_sec && tp1->tv_nsec > tp2->tv_nsec));
+}
+
/* returns (tp1 - tp2) in centiseconds */
static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) {
return ((tp1->tv_sec - tp2->tv_sec))*100 + (tp1->tv_nsec - tp2->tv_nsec)/1e7;