]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Auth: add waitForMultiData function
authorPieter Lexis <pieter.lexis@powerdns.com>
Tue, 23 Jan 2018 15:14:40 +0000 (16:14 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 23 Jan 2018 15:15:24 +0000 (16:15 +0100)
And use this function in CommunicatorClass::doNotifications.

pdns/mastercommunicator.cc
pdns/misc.cc
pdns/misc.hh

index 2b6e25047ad6d6e854220d68c65f7c4999462217..ce227c7dd1b98480f1723e68fa15bab8a67b6d64 100644 (file)
@@ -162,9 +162,10 @@ time_t CommunicatorClass::doNotifications()
   char buffer[1500];
   int sock;
   ssize_t size;
+  set<int> fds = {d_nsock4, d_nsock6};
 
   // receive incoming notifications on the nonblocking socket and take them off the list
-  while(waitFor2Data(d_nsock4, d_nsock6, 0, 0, &sock) > 0) {
+  while(waitForMultiData(fds, 0, 0, &sock) > 0) {
     fromlen=sizeof(from);
     size=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen);
     if(size < 0)
index 8dc5d4b360e3db1d1dca0a59c65c1ee24689cd19..25a8c001fbfd93c507f9ae68430313ebeea35b20 100644 (file)
@@ -353,6 +353,46 @@ int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* err
   return ret;
 }
 
+// returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
+int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fd) {
+  set<int> realFDs;
+  for (const auto& fd : fds) {
+    if (fd >= 0 && realFDs.count(fd) == 0) {
+      realFDs.insert(fd);
+    }
+  }
+
+  struct pollfd pfds[realFDs.size()];
+  memset(&pfds[0], 0, realFDs.size()*sizeof(struct pollfd));
+  int ctr = 0;
+  for (const auto& fd : realFDs) {
+    pfds[ctr].fd = fd;
+    pfds[ctr].events = POLLIN;
+    ctr++;
+  }
+
+  int ret;
+  if(seconds >= 0)
+    ret = poll(pfds, realFDs.size(), seconds * 1000 + useconds/1000);
+  else
+    ret = poll(pfds, realFDs.size(), -1);
+  if(ret <= 0)
+    return ret;
+
+  set<int> pollinFDs;
+  ctr = 0;
+  for (const auto& fd : realFDs) {
+    if (pfds[ctr].revents & POLLIN) {
+      pollinFDs.insert(pfds[ctr].fd);
+    }
+    ctr++;
+  }
+  set<int>::const_iterator it(pollinFDs.begin());
+  advance(it, random() % pollinFDs.size());
+  *fd = *it;
+  return 1;
+}
+
 // returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
 int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd)
 {
index f9db931a7cf0ae1260eb8d6f03f18b6ca8a3b737..6aff9ebc7b012b4b2337798cc0b6311a1b951325 100644 (file)
@@ -63,6 +63,7 @@ string getHostname();
 string urlEncode(const string &text);
 int waitForData(int fd, int seconds, int useconds=0);
 int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd);
+int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fd);
 int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr);
 uint16_t getShort(const unsigned char *p);
 uint16_t getShort(const char *p);