From: Pieter Lexis Date: Tue, 23 Jan 2018 15:14:40 +0000 (+0100) Subject: Auth: add waitForMultiData function X-Git-Tag: dnsdist-1.3.0~84^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d529011fee51367391f66be4a14015044fbe1e55;p=thirdparty%2Fpdns.git Auth: add waitForMultiData function And use this function in CommunicatorClass::doNotifications. --- diff --git a/pdns/mastercommunicator.cc b/pdns/mastercommunicator.cc index 2b6e25047a..ce227c7dd1 100644 --- a/pdns/mastercommunicator.cc +++ b/pdns/mastercommunicator.cc @@ -162,9 +162,10 @@ time_t CommunicatorClass::doNotifications() char buffer[1500]; int sock; ssize_t size; + set 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) diff --git a/pdns/misc.cc b/pdns/misc.cc index 8dc5d4b360..25a8c001fb 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -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& fds, const int seconds, const int useconds, int* fd) { + set 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 pollinFDs; + ctr = 0; + for (const auto& fd : realFDs) { + if (pfds[ctr].revents & POLLIN) { + pollinFDs.insert(pfds[ctr].fd); + } + ctr++; + } + set::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) { diff --git a/pdns/misc.hh b/pdns/misc.hh index f9db931a7c..6aff9ebc7b 100644 --- a/pdns/misc.hh +++ b/pdns/misc.hh @@ -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& 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);