From aa15b96d39dd0242c33b7a11c7c02ebdba50f150 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 21 Oct 2012 04:44:20 +0200 Subject: Add infrastructure for ack handling --- ffd/ack.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 ffd/ack.c (limited to 'ffd/ack.c') diff --git a/ffd/ack.c b/ffd/ack.c new file mode 100644 index 0000000..0dbb13c --- /dev/null +++ b/ffd/ack.c @@ -0,0 +1,88 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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 "ffd.h" +#include "queue.h" + + +static uint8_t acks[1 << 13] = {}; +static ffd_queue_t *ack_requests = NULL; +static uint16_t nonce = 0; + + +#define SET_ACK(n) do {acks[n >> 3] |= 1 << (n & 7);} while(0) +#define UNSET_ACK(n) do {acks[n >> 3] &= ~(1 << (n & 7));} while(0) +#define GET_ACK(n) ((acks[n >> 3] & (1 << (n & 7))) != 0) + + +typedef struct _ack_arg_t { + void (*cb)(uint16_t nonce, void *arg); + void *arg; + + uint16_t nonce; + unsigned interval; + unsigned retries; +} ack_arg_t; + + +void ffd_ack_handle(uint16_t n) { + SET_ACK(n); +} + +static void ack_resend(const struct timespec *timeout, void *argp) { + ack_arg_t *arg = argp; + + if (GET_ACK(arg->nonce) || !(--arg->retries)) { + free(arg); + return; + } + + arg->cb(arg->nonce, arg->arg); + + ffd_queue_put_delayed(&ack_requests, ack_resend, timeout, arg->interval, arg); +} + +void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg) { + UNSET_ACK(nonce); + cb(nonce, arg); + + ack_arg_t *ack_arg = malloc(sizeof(ack_arg_t)); + ack_arg->cb = cb; + ack_arg->arg = arg; + ack_arg->nonce = nonce++; + ack_arg->interval = interval; + ack_arg->retries = retries; + + ffd_queue_put_delayed(&ack_requests, ack_resend, &now, interval, ack_arg); +} + +int ffd_ack_timeout(void) { + return ffd_queue_timeout(&ack_requests); +} + +void ffd_ack_run(void) { + ffd_queue_run(&ack_requests); +} -- cgit v1.2.3