]> git.sur5r.net Git - ngadmin/commitdiff
Use portable way to handle timeouts
authordarkcoven <admin@darkcoven.tk>
Fri, 11 Oct 2013 22:18:54 +0000 (00:18 +0200)
committerdarkcoven <admin@darkcoven.tk>
Fri, 11 Oct 2013 22:51:40 +0000 (00:51 +0200)
configure.ac
lib/src/lib.h
lib/src/libconf.c
lib/src/network.c
lib/src/network.h
raw/include/nsdp/net.h
raw/src/Makefile.am
raw/src/net.c

index 8a060218fbdfa55a5706f15197e096905abe2d3d..8e7c5a27c48455581f84ee4d6d424c99dfcd7de3 100644 (file)
@@ -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([
index 5cea87f48350078ecaae900d04da07924cdfb755..84152aeed803c058508682041f752dd6848655e3 100644 (file)
@@ -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) */
index f94fcca04811f23354cc7bc75b6a3b92b0f0904c..e691f07acb3d4e6c3f5ef26766baf5167f9498ee 100644 (file)
@@ -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;
 }
index 09dcd6043142eea70b46c326cab5917c6a7d8891..0ad90561c9eb70443ff5357cf928793d03b9e674 100644 (file)
@@ -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) {
index 58b643d372206765a2b838af96686a223d8884b2..ca80cb68f969169a219fca0dca77b2a2880607fb 100644 (file)
@@ -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);
 
 
index 4e2dbb537d2cb9d83501943ee5035bc6a6243675..401a1fbb886a0501a48688530e244b8c04192900 100644 (file)
@@ -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
index f7f9b1fba9af33d5430a4a2b0d04d5895eb79c4a..b0ca5db32196de11cb4f69aa33c5e8e863eace66 100644 (file)
@@ -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)
 
index cc619efdd94b8fe51334ffffd97c6a61318cd711..f92b48eee648d6aae1b8430816f664fc318f97bf 100644 (file)
@@ -1,11 +1,47 @@
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 #include <errno.h>
+#include <poll.h>
 
 #include <nsdp/net.h>
 #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)