]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Use poll() instead of select() to remove limits on open file descriptors.
authorSimon Kelley <simon@thekelleys.org.uk>
Sun, 12 Jul 2015 20:09:11 +0000 (21:09 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Sun, 12 Jul 2015 20:09:11 +0000 (21:09 +0100)
Makefile
bld/Android.mk
src/dbus.c
src/dnsmasq.c
src/dnsmasq.h
src/forward.c
src/log.c
src/poll.c [new file with mode: 0644]
src/tftp.c
src/util.c

index 59750bcb744257362c38c67f415a33f1b1a7806a..4c87ea9c1a0af56bcaab8a17fe67145e7a6b5a6c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -73,7 +73,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
        dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
        helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
        dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
-       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
+       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o poll.o
 
 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
        dns-protocol.h radv-protocol.h ip6addr.h
index d627796e8edc235cf72d4f65ee5a5e55cf20efd4..5364ee72d7f322d3b36cde803b36c68259b86dc7 100644 (file)
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES :=  bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
                    dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
                    radv.c slaac.c auth.c ipset.c domain.c \
                    dnssec.c dnssec-openssl.c blockdata.c tables.c \
-                   loop.c inotify.c
+                   loop.c inotify.c poll.c
 
 LOCAL_MODULE := dnsmasq
 
index 1384ccffff18210b0dcd971401cd16590b8fe831..3555f49a7c5f237cc83a1e6eaa5ae5d712671a6d 100644 (file)
@@ -749,8 +749,7 @@ char *dbus_init(void)
 }
  
 
-void set_dbus_listeners(int *maxfdp,
-                       fd_set *rset, fd_set *wset, fd_set *eset)
+void set_dbus_listeners(void)
 {
   struct watch *w;
   
@@ -761,16 +760,16 @@ void set_dbus_listeners(int *maxfdp,
        int fd = dbus_watch_get_unix_fd(w->watch);
        
        if (flags & DBUS_WATCH_READABLE)
-         bump_maxfd(rset, fd, maxfdp);
+         poll_listen(fd, POLLIN);
        
        if (flags & DBUS_WATCH_WRITABLE)
-         bump_maxfd(wset, fd, maxfdp);
+         poll_listen(fd, POLLOUT);
        
-       bump_maxfd(eset, fd, maxfdp);
+       poll_listen(fd, POLLERR);
       }
 }
 
-void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
+void check_dbus_listeners()
 {
   DBusConnection *connection = (DBusConnection *)daemon->dbus;
   struct watch *w;
@@ -781,13 +780,13 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
        unsigned int flags = 0;
        int fd = dbus_watch_get_unix_fd(w->watch);
        
-       if (FD_ISSET(fd, rset))
+       if (poll_check(fd, POLLIN))
          flags |= DBUS_WATCH_READABLE;
        
-       if (FD_ISSET(fd, wset))
+       if (poll_check(fd, POLLOUT))
          flags |= DBUS_WATCH_WRITABLE;
        
-       if (FD_ISSET(fd, eset))
+       if (poll_check(fd, POLLERR))
          flags |= DBUS_WATCH_ERROR;
 
        if (flags != 0)
index fd24f63df9ec350ea19f2bfdeeb143df0a16bc5c..514e10bdf206cb966d1dc41fe63e15429794c61e 100644 (file)
@@ -24,8 +24,8 @@ struct daemon *daemon;
 static volatile pid_t pid = 0;
 static volatile int pipewrite;
 
-static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
-static void check_dns_listeners(fd_set *set, time_t now);
+static int set_dns_listeners(time_t now);
+static void check_dns_listeners(time_t now);
 static void sig_handler(int sig);
 static void async_event(int pipe, time_t now);
 static void fatal_event(struct event_desc *ev, char *msg);
@@ -799,10 +799,6 @@ int main (int argc, char **argv)
   if (option_bool(OPT_TFTP))
     {
       struct tftp_prefix *p;
-#ifdef FD_SETSIZE
-      if (FD_SETSIZE < (unsigned)max_fd)
-       max_fd = FD_SETSIZE;
-#endif
 
       my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s", 
                daemon->tftp_prefix ? _("root is ") : _("enabled"),
@@ -862,72 +858,58 @@ int main (int argc, char **argv)
   
   while (1)
     {
-      int maxfd = -1;
-      struct timeval t, *tp = NULL;
-      fd_set rset, wset, eset;
+      int t, timeout = -1;
       
-      FD_ZERO(&rset);
-      FD_ZERO(&wset);
-      FD_ZERO(&eset);
+      poll_reset();
       
       /* if we are out of resources, find how long we have to wait
         for some to come free, we'll loop around then and restart
         listening for queries */
-      if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
-       {
-         t.tv_usec = 0;
-         tp = &t;
-       }
+      if ((t = set_dns_listeners(now)) != 0)
+       timeout = t * 1000;
 
       /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
       if (daemon->tftp_trans ||
          (option_bool(OPT_DBUS) && !daemon->dbus))
-       {
-         t.tv_sec = 0;
-         t.tv_usec = 250000;
-         tp = &t;
-       }
+       timeout = 250;
+
       /* Wake every second whilst waiting for DAD to complete */
       else if (is_dad_listeners())
-       {
-         t.tv_sec = 1;
-         t.tv_usec = 0;
-         tp = &t;
-       }
+       timeout = 1000;
 
 #ifdef HAVE_DBUS
-      set_dbus_listeners(&maxfd, &rset, &wset, &eset);
+      set_dbus_listeners();
 #endif 
   
 #ifdef HAVE_DHCP
       if (daemon->dhcp || daemon->relay4)
        {
-         bump_maxfd(&rset, daemon->dhcpfd, &maxfd);
+         poll_listen(daemon->dhcpfd, POLLIN);
          if (daemon->pxefd != -1)
-           bump_maxfd(&rset, daemon->pxefd, &maxfd);
+           poll_listen(daemon->pxefd, POLLIN);
        }
 #endif
 
 #ifdef HAVE_DHCP6
       if (daemon->doing_dhcp6 || daemon->relay6)
-       bump_maxfd(&rset, daemon->dhcp6fd, &maxfd);
+       poll_listen(daemon->dhcp6fd, POLLIN);
        
       if (daemon->doing_ra)
-       bump_maxfd(&rset, daemon->icmp6fd, &maxfd); 
+       poll_listen(daemon->icmp6fd, POLLIN); 
 #endif
     
 #ifdef HAVE_INOTIFY
       if (daemon->inotifyfd != -1)
-       bump_maxfd(&rset, daemon->inotifyfd, &maxfd);
+       poll_listen(daemon->inotifyfd, POLLIN);
 #endif
 
 #if defined(HAVE_LINUX_NETWORK)
-      bump_maxfd(&rset, daemon->netlinkfd, &maxfd);
+      poll_listen(daemon->netlinkfd, POLLIN);
 #elif defined(HAVE_BSD_NETWORK)
-      bump_maxfd(&rset, daemon->routefd, &maxfd);
+      poll_listen(daemon->routefd, POLLIN);
 #endif
       
-      bump_maxfd(&rset, piperead, &maxfd);
+      poll_listen(piperead, POLLIN);
 
 #ifdef HAVE_DHCP
 #  ifdef HAVE_SCRIPT
@@ -938,7 +920,7 @@ int main (int argc, char **argv)
 #    endif
 
       if (!helper_buf_empty())
-       bump_maxfd(&wset, daemon->helperfd, &maxfd);
+       poll_listen(daemon->helperfd, POLLOUT);
 #  else
       /* need this for other side-effects */
       while (do_script_run(now));
@@ -952,17 +934,14 @@ int main (int argc, char **argv)
    
       /* must do this just before select(), when we know no
         more calls to my_syslog() can occur */
-      set_log_writer(&wset, &maxfd);
+      set_log_writer();
+      
+      if (do_poll(timeout) < 0)
+       continue;
       
-      if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
-       {
-         /* otherwise undefined after error */
-         FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
-       }
-
       now = dnsmasq_time();
 
-      check_log_writer(&wset);
+      check_log_writer(0);
 
       /* prime. */
       enumerate_interfaces(1);
@@ -978,15 +957,15 @@ int main (int argc, char **argv)
        }
 
 #if defined(HAVE_LINUX_NETWORK)
-      if (FD_ISSET(daemon->netlinkfd, &rset))
+      if (poll_check(daemon->netlinkfd, POLLIN))
        netlink_multicast();
 #elif defined(HAVE_BSD_NETWORK)
-      if (FD_ISSET(daemon->routefd, &rset))
+      if (poll_check(daemon->routefd, POLLIN))
        route_sock();
 #endif
 
 #ifdef HAVE_INOTIFY
-      if  (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now))
+      if  (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
        {
          if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
            poll_resolv(1, 1, now);
@@ -1006,7 +985,7 @@ int main (int argc, char **argv)
        }
 #endif
 
-      if (FD_ISSET(piperead, &rset))
+      if (poll_check(piperead, POLLIN))
        async_event(piperead, now);
       
 #ifdef HAVE_DBUS
@@ -1019,34 +998,34 @@ int main (int argc, char **argv)
          if (daemon->dbus)
            my_syslog(LOG_INFO, _("connected to system DBus"));
        }
-      check_dbus_listeners(&rset, &wset, &eset);
+      check_dbus_listeners();
 #endif
       
-      check_dns_listeners(&rset, now);
+      check_dns_listeners(now);
 
 #ifdef HAVE_TFTP
-      check_tftp_listeners(&rset, now);
+      check_tftp_listeners(now);
 #endif      
 
 #ifdef HAVE_DHCP
       if (daemon->dhcp || daemon->relay4)
        {
-         if (FD_ISSET(daemon->dhcpfd, &rset))
+         if (poll_check(daemon->dhcpfd, POLLIN))
            dhcp_packet(now, 0);
-         if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset))
+         if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
            dhcp_packet(now, 1);
        }
 
 #ifdef HAVE_DHCP6
-      if ((daemon->doing_dhcp6 || daemon->relay6) && FD_ISSET(daemon->dhcp6fd, &rset))
+      if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
        dhcp6_packet(now);
 
-      if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
+      if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
        icmp6_packet(now);
 #endif
 
 #  ifdef HAVE_SCRIPT
-      if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
+      if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLIN))
        helper_write();
 #  endif
 #endif
@@ -1451,7 +1430,7 @@ void clear_cache_and_reload(time_t now)
 #endif
 }
 
-static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
+static int set_dns_listeners(time_t now)
 {
   struct serverfd *serverfdp;
   struct listener *listener;
@@ -1463,7 +1442,7 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
   for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
     {
       tftp++;
-      bump_maxfd(set, transfer->sockfd, maxfdp);
+      poll_listen(transfer->sockfd, POLLIN);
     }
 #endif
   
@@ -1472,18 +1451,18 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
     get_new_frec(now, &wait, 0);
   
   for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
-    bump_maxfd(set, serverfdp->fd, maxfdp);
+    poll_listen(serverfdp->fd, POLLIN);
     
   if (daemon->port != 0 && !daemon->osport)
     for (i = 0; i < RANDOM_SOCKS; i++)
       if (daemon->randomsocks[i].refcount != 0)
-       bump_maxfd(set, daemon->randomsocks[i].fd, maxfdp);
+       poll_listen(daemon->randomsocks[i].fd, POLLIN);
          
   for (listener = daemon->listeners; listener; listener = listener->next)
     {
       /* only listen for queries if we have resources */
       if (listener->fd != -1 && wait == 0)
-       bump_maxfd(set, listener->fd, maxfdp);
+       poll_listen(listener->fd, POLLIN);
        
       /* death of a child goes through the select loop, so
         we don't need to explicitly arrange to wake up here */
@@ -1491,13 +1470,13 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
        for (i = 0; i < MAX_PROCS; i++)
          if (daemon->tcp_pids[i] == 0)
            {
-             bump_maxfd(set, listener->tcpfd, maxfdp);
+             poll_listen(listener->tcpfd, POLLIN);
              break;
            }
 
 #ifdef HAVE_TFTP
       if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
-       bump_maxfd(set, listener->tftpfd, maxfdp);
+       poll_listen(listener->tftpfd, POLLIN);
 #endif
 
     }
@@ -1505,33 +1484,33 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
   return wait;
 }
 
-static void check_dns_listeners(fd_set *set, time_t now)
+static void check_dns_listeners(time_t now)
 {
   struct serverfd *serverfdp;
   struct listener *listener;
   int i;
 
   for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
-    if (FD_ISSET(serverfdp->fd, set))
+    if (poll_check(serverfdp->fd, POLLIN))
       reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
   
   if (daemon->port != 0 && !daemon->osport)
     for (i = 0; i < RANDOM_SOCKS; i++)
       if (daemon->randomsocks[i].refcount != 0 && 
-         FD_ISSET(daemon->randomsocks[i].fd, set))
+         poll_check(daemon->randomsocks[i].fd, POLLIN))
        reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
   
   for (listener = daemon->listeners; listener; listener = listener->next)
     {
-      if (listener->fd != -1 && FD_ISSET(listener->fd, set))
+      if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
        receive_query(listener, now); 
       
 #ifdef HAVE_TFTP     
-      if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
+      if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
        tftp_request(listener, now);
 #endif
 
-      if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
+      if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
        {
          int confd, client_ok = 1;
          struct irec *iface = NULL;
@@ -1772,51 +1751,41 @@ int icmp_ping(struct in_addr addr)
   for (now = start = dnsmasq_time(), timeout_count = 0; 
        (difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
     {
-      struct timeval tv;
-      fd_set rset, wset;
       struct sockaddr_in faddr;
-      int maxfd = fd; 
       socklen_t len = sizeof(faddr);
       
-      tv.tv_usec = 250000;
-      tv.tv_sec = 0; 
-      
-      FD_ZERO(&rset);
-      FD_ZERO(&wset);
-      FD_SET(fd, &rset);
-      set_dns_listeners(now, &rset, &maxfd);
-      set_log_writer(&wset, &maxfd);
+      poll_reset();
+      poll_listen(fd, POLLIN);
+      set_dns_listeners(now);
+      set_log_writer();
       
 #ifdef HAVE_DHCP6
       if (daemon->doing_ra)
-       bump_maxfd(&rset, daemon->icmp6fd, &maxfd); 
+       poll_listen(daemon->icmp6fd, POLLIN); 
 #endif
       
-      rc = select(maxfd+1, &rset, &wset, NULL, &tv);
+      rc = do_poll(250);
       
       if (rc < 0)
-       {
-         FD_ZERO(&rset);
-         FD_ZERO(&wset);
-       }
+       continue;
       else if (rc == 0)
        timeout_count++;
 
       now = dnsmasq_time();
 
-      check_log_writer(&wset);
-      check_dns_listeners(&rset, now);
+      check_log_writer(0);
+      check_dns_listeners(now);
 
 #ifdef HAVE_DHCP6
-      if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
+      if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
        icmp6_packet(now);
 #endif
       
 #ifdef HAVE_TFTP
-      check_tftp_listeners(&rset, now);
+      check_tftp_listeners(now);
 #endif
 
-      if (FD_ISSET(fd, &rset) &&
+      if (poll_check(fd, POLLIN) &&
          recvfrom(fd, &packet, sizeof(packet), 0,
                   (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
          saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
index 2be27f190446d30ea7ef015903c9ac240ea03e3a..de146c649491c9f44b9c7b39b0d4b89c7ebb5607 100644 (file)
@@ -82,7 +82,7 @@ typedef unsigned long long u64;
 #if defined(HAVE_SOLARIS_NETWORK)
 #  include <sys/sockio.h>
 #endif
-#include <sys/select.h>
+#include <sys/poll.h>
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <sys/un.h>
@@ -1191,7 +1191,6 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
                  unsigned int mask);
 int expand_buf(struct iovec *iov, size_t size);
 char *print_mac(char *buff, unsigned char *mac, int len);
-void bump_maxfd(fd_set *set, int fd, int *max);
 int read_write(int fd, unsigned char *packet, int size, int rw);
 
 int wildcard_match(const char* wildcard, const char* match);
@@ -1202,8 +1201,8 @@ void die(char *message, char *arg1, int exit_code);
 int log_start(struct passwd *ent_pw, int errfd);
 int log_reopen(char *log_file);
 void my_syslog(int priority, const char *format, ...);
-void set_log_writer(fd_set *set, int *maxfdp);
-void check_log_writer(fd_set *set);
+void set_log_writer(void);
+void check_log_writer(int force);
 void flush_log(void);
 
 /* option.c */
@@ -1366,8 +1365,8 @@ int iface_enumerate(int family, void *parm, int (callback)());
 /* dbus.c */
 #ifdef HAVE_DBUS
 char *dbus_init(void);
-void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
-void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
+void check_dbus_listeners(void);
+void set_dbus_listeners(void);
 #  ifdef HAVE_DHCP
 void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
 #  endif
@@ -1394,7 +1393,7 @@ int helper_buf_empty(void);
 /* tftp.c */
 #ifdef HAVE_TFTP
 void tftp_request(struct listener *listen, time_t now);
-void check_tftp_listeners(fd_set *rset, time_t now);
+void check_tftp_listeners(time_t now);
 int do_tftp_script_run(void);
 #endif
 
@@ -1511,3 +1510,10 @@ void inotify_dnsmasq_init();
 int inotify_check(time_t now);
 void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
 #endif
+
+/* poll.c */
+void poll_reset(void);
+int poll_check(int fd, short event);
+void poll_listen(int fd, short event);
+int do_poll(int timeout);
+
index b40dda37eca239d40017344960a8404f546bd5d8..de00ca0b9bd43ce53c9c528c94a0223732bd55e6 100644 (file)
@@ -1887,7 +1887,7 @@ unsigned char *tcp_request(int confd, time_t now,
                             dst_addr_4, netmask, now, &ad_question, &do_bit);
          
          /* Do this by steam now we're not in the select() loop */
-         check_log_writer(NULL); 
+         check_log_writer(1); 
          
          if (m == 0)
            {
@@ -2108,7 +2108,7 @@ unsigned char *tcp_request(int confd, time_t now,
            }
        }
          
-      check_log_writer(NULL);
+      check_log_writer(1);
       
       *length = htons(m);
            
index 8e2f9303ead933ae502ed00f49cbae7d142e5546..27b2e596e7190e1d4a5ab7fe8ec59b8d04b1bf37 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -421,15 +421,15 @@ void my_syslog(int priority, const char *format, ...)
     } 
 }
 
-void set_log_writer(fd_set *set, int *maxfdp)
+void set_log_writer(void)
 {
   if (entries && log_fd != -1 && connection_good)
-    bump_maxfd(set, log_fd, maxfdp);
+    poll_listen(log_fd, POLLOUT);
 }
 
-void check_log_writer(fd_set *set)
+void check_log_writer(int force)
 {
-  if (log_fd != -1 && (!set || FD_ISSET(log_fd, set)))
+  if (log_fd != -1 && (force || poll_check(log_fd, POLLOUT)))
     log_write();
 }
 
diff --git a/src/poll.c b/src/poll.c
new file mode 100644 (file)
index 0000000..01b3564
--- /dev/null
@@ -0,0 +1,124 @@
+/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+/* Wrapper for poll(). Allocates and extends array of struct pollfds,
+   keeps them in fd order so that we can set and test conditions on
+   fd using a simple but efficient binary chop. */
+
+/* poll_reset()
+   poll_listen(fd, event)
+   .
+   .
+   poll_listen(fd, event);
+
+   hits = do_poll(timeout);
+
+   if (poll_check(fd, event)
+    .
+    .
+
+   if (poll_check(fd, event)
+    .
+    .
+
+    event is OR of POLLIN, POLLOUT, POLLERR, etc
+*/
+
+static struct pollfd *pollfds = NULL;
+static nfds_t nfds, arrsize = 0;
+
+/* Binary search. Returns either the pollfd with fd, or
+   if the fd doesn't match, or return equals nfds, the entry
+   to the left of which a new record should be inserted. */
+static nfds_t fd_search(int fd)
+{
+  nfds_t left, right, mid;
+  
+  if ((right = nfds) == 0)
+    return 0;
+  
+  left = 0;
+  
+  while (1)
+    {
+      if (right == left + 1)
+       return (pollfds[left].fd >= fd) ? left : right;
+      
+      mid = (left + right)/2;
+      
+      if (pollfds[mid].fd > fd)
+       right = mid;
+      else 
+       left = mid;
+    }
+}
+
+void poll_reset(void)
+{
+  nfds = 0;
+}
+
+int do_poll(int timeout)
+{
+  return poll(pollfds, nfds, timeout);
+}
+
+int poll_check(int fd, short event)
+{
+  nfds_t i = fd_search(fd);
+  
+  if (i < nfds && pollfds[i].fd == fd)
+    return pollfds[i].revents & event;
+
+  return 0;
+}
+
+void poll_listen(int fd, short event)
+{
+   nfds_t i = fd_search(fd);
+  
+   if (i < nfds && pollfds[i].fd == fd)
+     pollfds[i].events |= event;
+   else
+     {
+       if (arrsize != nfds)
+        memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
+       else
+        {
+          /* Array too small, extend. */
+          struct pollfd *new;
+          arrsize += 64;
+          
+          if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
+            return;
+
+          if (pollfds)
+            {
+              memcpy(new, pollfds, i * sizeof(struct pollfd));
+              memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
+              free(pollfds);
+            }
+          
+          pollfds = new;
+        }
+       
+       pollfds[i].fd = fd;
+       pollfds[i].events = event;
+       nfds++;
+     }
+}
index d3fb6d7492e4a789ed12fabd34b03b477cb89a1c..350a587c60834caa6e10d0988dc68870b11b7909 100644 (file)
@@ -502,7 +502,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
   return NULL;
 }
 
-void check_tftp_listeners(fd_set *rset, time_t now)
+void check_tftp_listeners(time_t now)
 {
   struct tftp_transfer *transfer, *tmp, **up;
   ssize_t len;
@@ -518,7 +518,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
       
       prettyprint_addr(&transfer->peer, daemon->addrbuff);
      
-      if (FD_ISSET(transfer->sockfd, rset))
+      if (poll_check(transfer->sockfd, POLLIN))
        {
          /* we overwrote the buffer... */
          daemon->srv_save = NULL;
index 3b7fad8ee5ca095552ba1cd1a5be6904eedde835..469eaed74d51c22cf3cd5da66fdaa53a1277de2a 100644 (file)
@@ -570,25 +570,6 @@ char *print_mac(char *buff, unsigned char *mac, int len)
   return buff;
 }
 
-void bump_maxfd(fd_set *set, int fd, int *max)
-{
-#ifdef FD_SETSIZE
-  if (fd >= FD_SETSIZE)
-    {
-      static int logged = 0;
-      if (!logged)
-       my_syslog(LOG_ERR, _("File descriptor overflows FD_SET"));
-      logged = 1;
-    }
-  else
- #endif
-    {
-      FD_SET(fd, set);
-      if (fd > *max)
-       *max = fd;
-    }
-}
-
 /* rc is return from sendto and friends.
    Return 1 if we should retry.
    Set errno to zero if we succeeded. */