]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pollmplexer.cc
rec: mention rust compiler in compiling docs
[thirdparty/pdns.git] / pdns / pollmplexer.cc
CommitLineData
870a0fe4
AT
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
cfa2996a
BH
4#include "mplexer.hh"
5#include "sstuff.hh"
6#include <iostream>
7#include <poll.h>
2ee30ed7 8#include <unordered_map>
cfa2996a 9#include "misc.hh"
10f4eea8 10#include "namespaces.hh"
cfa2996a 11
7c58a81f 12FDMultiplexer* FDMultiplexer::getMultiplexerSilent(unsigned int maxEventsHint)
4226cfd0 13{
14 FDMultiplexer* ret = nullptr;
e16e673d 15 for (const auto& i : FDMultiplexer::getMultiplexerMap()) {
4226cfd0 16 try {
7c58a81f 17 ret = i.second(std::min(maxEventsHint, FDMultiplexer::s_maxevents));
4226cfd0 18 return ret;
19 }
e16e673d 20 catch (const FDMultiplexerException& fe) {
4226cfd0 21 }
e16e673d 22 catch (...) {
4226cfd0 23 }
24 }
25 return ret;
26}
27
926444e2 28class PollFDMultiplexer : public FDMultiplexer
29{
30public:
d73de874 31 PollFDMultiplexer(unsigned int /* maxEventsHint */)
926444e2 32 {}
926444e2 33
e16e673d
RG
34 int run(struct timeval* tv, int timeout = 500) override;
35 void getAvailableFDs(std::vector<int>& fds, int timeout) override;
926444e2 36
e16e673d
RG
37 void addFD(int fd, FDMultiplexer::EventKind) override;
38 void removeFD(int fd, FDMultiplexer::EventKind) override;
5bdbb83d
RG
39
40 string getName() const override
926444e2 41 {
42 return "poll";
43 }
e16e673d 44
926444e2 45private:
5efe08a2 46 std::unordered_map<int, struct pollfd> d_pollfds;
5bdbb83d 47 vector<struct pollfd> preparePollFD() const;
926444e2 48};
cfa2996a 49
7c58a81f 50static FDMultiplexer* make(unsigned int maxEventsHint)
cfa2996a 51{
7c58a81f 52 return new PollFDMultiplexer(maxEventsHint);
cfa2996a
BH
53}
54
55static struct RegisterOurselves
56{
e16e673d
RG
57 RegisterOurselves()
58 {
d90323cc 59 FDMultiplexer::getMultiplexerMap().emplace(2, &make);
cfa2996a
BH
60 }
61} doIt;
62
5efe08a2
RG
63static int convertEventKind(FDMultiplexer::EventKind kind)
64{
65 switch (kind) {
66 case FDMultiplexer::EventKind::Read:
67 return POLLIN;
68 case FDMultiplexer::EventKind::Write:
69 return POLLOUT;
70 case FDMultiplexer::EventKind::Both:
71 return POLLIN | POLLOUT;
72 }
73 throw std::runtime_error("Unhandled event kind in the ports multiplexer");
74}
75
e16e673d 76void PollFDMultiplexer::addFD(int fd, FDMultiplexer::EventKind kind)
cfa2996a 77{
5efe08a2
RG
78 if (d_pollfds.count(fd) == 0) {
79 auto& pollfd = d_pollfds[fd];
80 pollfd.fd = fd;
81 pollfd.events = 0;
82 }
83 auto& pollfd = d_pollfds.at(fd);
84 pollfd.events |= convertEventKind(kind);
cfa2996a
BH
85}
86
e16e673d 87void PollFDMultiplexer::removeFD(int fd, FDMultiplexer::EventKind)
cfa2996a 88{
5efe08a2 89 d_pollfds.erase(fd);
cfa2996a
BH
90}
91
5bdbb83d 92vector<struct pollfd> PollFDMultiplexer::preparePollFD() const
cfa2996a 93{
e16e673d 94 std::vector<struct pollfd> result;
5efe08a2
RG
95 result.reserve(d_pollfds.size());
96 for (const auto& entry : d_pollfds) {
e16e673d 97 result.push_back(entry.second);
cfa2996a
BH
98 }
99
e16e673d 100 return result;
5bdbb83d
RG
101}
102
103void PollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
104{
105 auto pollfds = preparePollFD();
e16e673d
RG
106 if (pollfds.empty()) {
107 return;
108 }
109
5bdbb83d
RG
110 int ret = poll(&pollfds[0], pollfds.size(), timeout);
111
e16e673d 112 if (ret < 0 && errno != EINTR) {
5bdbb83d 113 throw FDMultiplexerException("poll returned error: " + stringerror());
e16e673d 114 }
5bdbb83d 115
e16e673d
RG
116 for (const auto& pollfd : pollfds) {
117 if (pollfd.revents & POLLIN || pollfd.revents & POLLOUT || pollfd.revents & POLLERR || pollfd.revents & POLLHUP) {
5bdbb83d
RG
118 fds.push_back(pollfd.fd);
119 }
120 }
121}
122
123int PollFDMultiplexer::run(struct timeval* now, int timeout)
124{
e16e673d 125 if (d_inrun) {
5bdbb83d
RG
126 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
127 }
128
129 auto pollfds = preparePollFD();
e16e673d
RG
130 if (pollfds.empty()) {
131 gettimeofday(now, nullptr); // MANDATORY!
132 return 0;
133 }
5bdbb83d 134
e16e673d
RG
135 int ret = poll(&pollfds[0], pollfds.size(), timeout);
136 gettimeofday(now, nullptr); // MANDATORY!
137
138 if (ret < 0 && errno != EINTR) {
139 throw FDMultiplexerException("poll returned error: " + stringerror());
140 }
141
142 d_inrun = true;
c7a9f1b4 143 int count = 0;
e16e673d 144 for (const auto& pollfd : pollfds) {
e16e673d
RG
145 if (pollfd.revents & POLLIN || pollfd.revents & POLLERR || pollfd.revents & POLLHUP) {
146 const auto& iter = d_readCallbacks.find(pollfd.fd);
147 if (iter != d_readCallbacks.end()) {
148 iter->d_callback(iter->d_fd, iter->d_parameter);
c7a9f1b4 149 count++;
cfa2996a
BH
150 }
151 }
e16e673d
RG
152
153 if (pollfd.revents & POLLOUT || pollfd.revents & POLLERR) {
154 const auto& iter = d_writeCallbacks.find(pollfd.fd);
155 if (iter != d_writeCallbacks.end()) {
156 iter->d_callback(iter->d_fd, iter->d_parameter);
c7a9f1b4 157 count++;
cfa2996a
BH
158 }
159 }
160 }
e16e673d
RG
161
162 d_inrun = false;
c7a9f1b4 163 return count;
cfa2996a
BH
164}
165
166#if 0
167
168void acceptData(int fd, boost::any& parameter)
169{
170 cout<<"Have data on fd "<<fd<<endl;
171 Socket* sock=boost::any_cast<Socket*>(parameter);
172 string packet;
173 IPEndpoint rem;
174 sock->recvFrom(packet, rem);
175 cout<<"Received "<<packet.size()<<" bytes!\n";
176}
177
178
179int main()
180{
a5794017 181 Socket s(AF_INET, SOCK_DGRAM);
e16e673d 182
cfa2996a
BH
183 IPEndpoint loc("0.0.0.0", 2000);
184 s.bind(loc);
185
186 PollFDMultiplexer sfm;
187
188 sfm.addReadFD(s.getHandle(), &acceptData, &s);
189
190 for(int n=0; n < 100 ; ++n) {
191 sfm.run();
192 }
193 sfm.removeReadFD(s.getHandle());
194 sfm.removeReadFD(s.getHandle());
195}
196#endif