From c662193fa4e44d5ceaa60a7c00d5c0f45b43ab69 Mon Sep 17 00:00:00 2001 From: darkcoven Date: Sat, 12 Oct 2013 00:18:54 +0200 Subject: [PATCH] Use portable way to handle timeouts --- configure.ac | 13 ++++++- lib/src/lib.h | 2 +- lib/src/libconf.c | 12 ++---- lib/src/network.c | 17 --------- lib/src/network.h | 3 -- raw/include/nsdp/net.h | 2 +- raw/src/Makefile.am | 1 + raw/src/net.c | 87 +++++++++++++++++++++++++++++++++++++----- 8 files changed, 95 insertions(+), 42 deletions(-) diff --git a/configure.ac b/configure.ac index 8a06021..8e7c5a2 100644 --- a/configure.ac +++ b/configure.ac @@ -86,7 +86,18 @@ AC_TYPE_SIZE_T # check for library functions AC_FUNC_MALLOC -AC_CHECK_FUNCS([inet_ntoa memchr memset select socket strcasecmp strdup strtol strtoul]) +AC_CHECK_FUNCS([inet_ntoa memchr memset socket poll strcasecmp strdup strtol strtoul]) + +AC_CHECK_FUNC([clock_gettime], [ + AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Define if you have clock_gettime]) +], [ + AC_CHECK_LIB([rt], [clock_gettime], [ + AC_SUBST([RT_LIBS], [-lrt]) + AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Define if you have clock_gettime]) + ], [ + AC_CHECK_FUNCS([gettimeofday]) + ]) +]) AC_CONFIG_FILES([ diff --git a/lib/src/lib.h b/lib/src/lib.h index 5cea87f..84152ae 100644 --- a/lib/src/lib.h +++ b/lib/src/lib.h @@ -21,7 +21,7 @@ struct ngadmin { struct sockaddr_in local; /* local address & port */ struct in_addr brd; /* broadcast address */ char iface[IFNAMSIZ]; /* interface */ - struct timeval timeout; /* timeout */ + struct timespec timeout; /* timeout */ struct ether_addr localmac; /* local MAC address */ bool keepbroad; /* keep broadcasting */ bool globalbroad; /* use global broadcast address (255.255.255.255) */ diff --git a/lib/src/libconf.c b/lib/src/libconf.c index f94fcca..e691f07 100644 --- a/lib/src/libconf.c +++ b/lib/src/libconf.c @@ -8,7 +8,7 @@ #include "network.h" -static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0}; +static const struct timespec default_timeout = {.tv_sec = 4, .tv_nsec = 0}; struct ngadmin* ngadmin_init (const char *iface) @@ -29,10 +29,6 @@ struct ngadmin* ngadmin_init (const char *iface) } nga->timeout = default_timeout; - if (updateTimeout(nga) < 0) { - free(nga); - return NULL; - } return nga; @@ -103,10 +99,8 @@ int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) if (nga == NULL || tv == NULL) return ERR_INVARG; - nga->timeout = *tv; - if (updateTimeout(nga) < 0) - ret = ERR_NET; - + nga->timeout.tv_sec = tv->tv_sec; + nga->timeout.tv_nsec = tv->tv_usec * 1000; return ret; } diff --git a/lib/src/network.c b/lib/src/network.c index 09dcd60..0ad9056 100644 --- a/lib/src/network.c +++ b/lib/src/network.c @@ -144,23 +144,6 @@ int forceInterface (struct ngadmin *nga) } -int updateTimeout (struct ngadmin *nga) -{ - int ret; - - - /* specify receive timeout */ - ret = setsockopt(nga->sock, SOL_SOCKET, SO_RCVTIMEO, &nga->timeout, sizeof(struct timeval)); - if (ret < 0) { - perror("setsockopt(SO_RCVTIMEO)"); - return ret; - } - - - return 0; -} - - static int checkErrorCode (const struct nsdp_cmd *nc) { switch (nc->error) { diff --git a/lib/src/network.h b/lib/src/network.h index 58b643d..ca80cb6 100644 --- a/lib/src/network.h +++ b/lib/src/network.h @@ -20,9 +20,6 @@ int stopNetwork (struct ngadmin *nga); int forceInterface (struct ngadmin *nga); -int updateTimeout (struct ngadmin *nga); - - void prepareSend (struct ngadmin *nga, struct nsdp_cmd *nc, unsigned char code); diff --git a/raw/include/nsdp/net.h b/raw/include/nsdp/net.h index 4e2dbb5..401a1fb 100644 --- a/raw/include/nsdp/net.h +++ b/raw/include/nsdp/net.h @@ -26,7 +26,7 @@ struct nsdp_cmd { int sendNsdpPacket (int sock, const struct nsdp_cmd *nc, const List *attr); -int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct timeval *timeout); +int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct timespec *timeout); #endif diff --git a/raw/src/Makefile.am b/raw/src/Makefile.am index f7f9b1f..b0ca5db 100644 --- a/raw/src/Makefile.am +++ b/raw/src/Makefile.am @@ -4,4 +4,5 @@ noinst_LTLIBRARIES = librawnsdp.la librawnsdp_la_SOURCES = attr.c encoding.c encoding_attr.c list.c misc.c net.c librawnsdp_la_CPPFLAGS = -I$(top_srcdir)/raw/include/ -I$(top_srcdir)/lib/include/ librawnsdp_la_CFLAGS = -fno-strict-aliasing +librawnsdp_la_LIBADD = $(RT_LIBS) diff --git a/raw/src/net.c b/raw/src/net.c index cc619ef..f92b48e 100644 --- a/raw/src/net.c +++ b/raw/src/net.c @@ -1,11 +1,47 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include +#include #include #include "encoding.h" +static inline void timespec_add (struct timespec *tsa, const struct timespec *tsb) +{ + tsa->tv_sec += tsb->tv_sec; + tsa->tv_nsec += tsb->tv_nsec; + while (tsa->tv_nsec >= 1000000000) { + tsa->tv_nsec -= 1000000000; + tsa->tv_sec++; + } +} + + +static inline int timespec_diff_ms (const struct timespec *tsa, const struct timespec *tsb) +{ + int diff = (tsb->tv_sec - tsa->tv_sec) * 1000; + + if (tsb->tv_sec > tsa->tv_sec) + diff += (tsb->tv_nsec - tsa->tv_nsec) / 1000000; + else + diff -= (tsb->tv_nsec - tsa->tv_nsec) / 1000000; + + return diff; +} + + +static inline void timeval_to_timespec (struct timespec *ts, const struct timeval *tv) +{ + ts->tv_sec = tv->tv_sec; + ts->tv_nsec = tv->tv_usec * 1000; +} + + int sendNsdpPacket (int sock, const struct nsdp_cmd *nc, const List *attr) { unsigned char buffer[1500]; @@ -34,15 +70,18 @@ int sendNsdpPacket (int sock, const struct nsdp_cmd *nc, const List *attr) } -int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct timeval *timeout) +int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct timespec *timeout) { unsigned char buffer[1500]; struct nsdp_packet np; socklen_t slen = sizeof(struct sockaddr_in); - struct timeval rem; - fd_set fs; - int len = -1; + int len = -1, timewait; struct sockaddr_in remote; + struct timespec timecurrent, timeend; +#ifndef HAVE_CLOCK_GETTIME + struct timeval tv; +#endif + struct pollfd fds; if (sock < 0 || nc == NULL || attr == NULL) @@ -50,16 +89,44 @@ int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct time np.buffer = buffer; - if (timeout != NULL) - rem = *timeout; - memset(&remote, 0, sizeof(struct sockaddr_in)); remote.sin_family = AF_INET; + if (timeout == NULL) { + timewait = -1; + } else { +#ifdef HAVE_CLOCK_GETTIME + clock_gettime(CLOCK_MONOTONIC, &timeend); +#else + gettimeofday(&tv, NULL); + timeval_to_timespec(&timeend, &tv); +#endif + timespec_add(&timeend, timeout); + } + fds.fd = sock; + fds.events = POLLIN; + fds.revents = 0; + while (1) { - FD_ZERO(&fs); - FD_SET(sock, &fs); - select(sock + 1, &fs, NULL, NULL, timeout == NULL ? NULL : &rem); /* FIXME: non portable */ + if (timeout != NULL) { +#ifdef HAVE_CLOCK_GETTIME + clock_gettime(CLOCK_MONOTONIC, &timecurrent); +#else + gettimeofday(&tv, NULL); + timeval_to_timespec(&timeend, &tv); +#endif + timewait = timespec_diff_ms(&timecurrent, &timeend); + if (timewait <= 0) + break; + } + + len = poll(&fds, 1, timewait); + if (len < 0) { + break; + } else if (len == 0) { + len = -ETIMEDOUT; + break; + } len = recvfrom(sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&remote, &slen); if (len < 0) -- 2.39.5