Add timeout queues
This commit is contained in:
parent
8e810f5fd8
commit
bc9f976d7f
6 changed files with 162 additions and 33 deletions
|
@ -5,6 +5,7 @@ add_executable(ffd
|
|||
ffd.c
|
||||
neigh.c
|
||||
netif.c
|
||||
queue.c
|
||||
send.c
|
||||
tlv.c
|
||||
util.c
|
||||
|
|
74
ffd/ffd.c
74
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;
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
@ -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){})
|
||||
|
|
42
ffd/queue.c
Normal file
42
ffd/queue.c
Normal file
|
@ -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;
|
||||
}
|
69
ffd/queue.h
Normal file
69
ffd/queue.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
|
|
Reference in a new issue