From fa504dae8d9901da0fff7fa79ac50de915084935 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 13 Dec 2015 19:08:37 +0100 Subject: [PATCH] gluon-neighbour-info: simplify and fix timeout calculation The timeout was calculated incorrectly (in each iteration the span between the start time and the current time was substracted from the timeout again), and would often become negative, causing warnings in the kernel log. --- .../src/gluon-neighbour-info.c | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/package/gluon-neighbour-info/src/gluon-neighbour-info.c b/package/gluon-neighbour-info/src/gluon-neighbour-info.c index d9862368..c1dd162a 100644 --- a/package/gluon-neighbour-info/src/gluon-neighbour-info.c +++ b/package/gluon-neighbour-info/src/gluon-neighbour-info.c @@ -58,7 +58,7 @@ void getclock(struct timeval *tv) { } /* Assumes a and b are normalized */ -void tv_subtract (struct timeval *r, struct timeval *a, struct timeval *b) { +void tv_subtract (struct timeval *r, const struct timeval *a, const struct timeval *b) { r->tv_usec = a->tv_usec - b->tv_usec; r->tv_sec = a->tv_sec - b->tv_sec; @@ -68,18 +68,17 @@ void tv_subtract (struct timeval *r, struct timeval *a, struct timeval *b) { } } -ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, struct timeval *timeout, struct timeval *offset) { - struct timeval now, delta; - ssize_t ret; - - setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, timeout, sizeof(*timeout)); - ret = recv(socket, buffer, length, flags); +ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const struct timeval *timeout) { + struct timeval now, timeout_left; getclock(&now); - tv_subtract(&delta, &now, offset); - tv_subtract(timeout, timeout, &delta); + tv_subtract(&timeout_left, timeout, &now); - return ret; + if (timeout_left.tv_sec < 0) + return -1; + + setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left)); + return recv(socket, buffer, length, flags); } int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) { @@ -94,14 +93,18 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char * exit(EXIT_FAILURE); } - struct timeval tv_timeout, tv_offset; - tv_timeout.tv_sec = (int) timeout; - tv_timeout.tv_usec = ((int) (timeout * 1000000)) % 1000000; + struct timeval tv_timeout; + getclock(&tv_timeout); - getclock(&tv_offset); + tv_timeout.tv_sec += (int) timeout; + tv_timeout.tv_usec += ((int) (timeout * 1000000)) % 1000000; + if (tv_timeout.tv_usec >= 1000000) { + tv_timeout.tv_usec -= 1000000; + tv_timeout.tv_sec += 1; + } do { - ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout, &tv_offset); + ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout); if (ret < 0) break; @@ -176,6 +179,10 @@ int main(int argc, char **argv) { break; case 't': timeout = atof(optarg); + if (timeout < 0) { + perror("Negative timeout not supported"); + exit(EXIT_FAILURE); + } break; case 's': sse = optarg;