]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/pollmplexer.cc
8 #include <unordered_map>
10 #include "namespaces.hh"
12 FDMultiplexer
* FDMultiplexer::getMultiplexerSilent(unsigned int maxEventsHint
)
14 FDMultiplexer
* ret
= nullptr;
15 for (const auto& i
: FDMultiplexer::getMultiplexerMap()) {
17 ret
= i
.second(std::min(maxEventsHint
, FDMultiplexer::s_maxevents
));
20 catch (const FDMultiplexerException
& fe
) {
28 class PollFDMultiplexer
: public FDMultiplexer
31 PollFDMultiplexer(unsigned int /* maxEventsHint */)
34 int run(struct timeval
* tv
, int timeout
= 500) override
;
35 void getAvailableFDs(std::vector
<int>& fds
, int timeout
) override
;
37 void addFD(int fd
, FDMultiplexer::EventKind
) override
;
38 void removeFD(int fd
, FDMultiplexer::EventKind
) override
;
40 string
getName() const override
46 std::unordered_map
<int, struct pollfd
> d_pollfds
;
47 vector
<struct pollfd
> preparePollFD() const;
50 static FDMultiplexer
* make(unsigned int maxEventsHint
)
52 return new PollFDMultiplexer(maxEventsHint
);
55 static struct RegisterOurselves
59 FDMultiplexer::getMultiplexerMap().emplace(2, &make
);
63 static int convertEventKind(FDMultiplexer::EventKind kind
)
66 case FDMultiplexer::EventKind::Read
:
68 case FDMultiplexer::EventKind::Write
:
70 case FDMultiplexer::EventKind::Both
:
71 return POLLIN
| POLLOUT
;
73 throw std::runtime_error("Unhandled event kind in the ports multiplexer");
76 void PollFDMultiplexer::addFD(int fd
, FDMultiplexer::EventKind kind
)
78 if (d_pollfds
.count(fd
) == 0) {
79 auto& pollfd
= d_pollfds
[fd
];
83 auto& pollfd
= d_pollfds
.at(fd
);
84 pollfd
.events
|= convertEventKind(kind
);
87 void PollFDMultiplexer::removeFD(int fd
, FDMultiplexer::EventKind
)
92 vector
<struct pollfd
> PollFDMultiplexer::preparePollFD() const
94 std::vector
<struct pollfd
> result
;
95 result
.reserve(d_pollfds
.size());
96 for (const auto& entry
: d_pollfds
) {
97 result
.push_back(entry
.second
);
103 void PollFDMultiplexer::getAvailableFDs(std::vector
<int>& fds
, int timeout
)
105 auto pollfds
= preparePollFD();
106 if (pollfds
.empty()) {
110 int ret
= poll(&pollfds
[0], pollfds
.size(), timeout
);
112 if (ret
< 0 && errno
!= EINTR
) {
113 throw FDMultiplexerException("poll returned error: " + stringerror());
116 for (const auto& pollfd
: pollfds
) {
117 if (pollfd
.revents
& POLLIN
|| pollfd
.revents
& POLLOUT
|| pollfd
.revents
& POLLERR
|| pollfd
.revents
& POLLHUP
) {
118 fds
.push_back(pollfd
.fd
);
123 int PollFDMultiplexer::run(struct timeval
* now
, int timeout
)
125 InRun
guard(d_inrun
);
127 auto pollfds
= preparePollFD();
128 if (pollfds
.empty()) {
129 gettimeofday(now
, nullptr); // MANDATORY!
133 int ret
= poll(&pollfds
[0], pollfds
.size(), timeout
);
134 gettimeofday(now
, nullptr); // MANDATORY!
136 if (ret
< 0 && errno
!= EINTR
) {
137 throw FDMultiplexerException("poll returned error: " + stringerror());
141 for (const auto& pollfd
: pollfds
) {
142 if (pollfd
.revents
& POLLIN
|| pollfd
.revents
& POLLERR
|| pollfd
.revents
& POLLHUP
) {
143 const auto& iter
= d_readCallbacks
.find(pollfd
.fd
);
144 if (iter
!= d_readCallbacks
.end()) {
145 iter
->d_callback(iter
->d_fd
, iter
->d_parameter
);
150 if (pollfd
.revents
& POLLOUT
|| pollfd
.revents
& POLLERR
) {
151 const auto& iter
= d_writeCallbacks
.find(pollfd
.fd
);
152 if (iter
!= d_writeCallbacks
.end()) {
153 iter
->d_callback(iter
->d_fd
, iter
->d_parameter
);
164 void acceptData(int fd
, boost::any
& parameter
)
166 cout
<<"Have data on fd "<<fd
<<endl
;
167 Socket
* sock
=boost::any_cast
<Socket
*>(parameter
);
170 sock
->recvFrom(packet
, rem
);
171 cout
<<"Received "<<packet
.size()<<" bytes!\n";
177 Socket
s(AF_INET
, SOCK_DGRAM
);
179 IPEndpoint
loc("0.0.0.0", 2000);
182 PollFDMultiplexer sfm
;
184 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
186 for(int n
=0; n
< 100 ; ++n
) {
189 sfm
.removeReadFD(s
.getHandle());
190 sfm
.removeReadFD(s
.getHandle());