]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pollmplexer.cc
cleanup poll event bitmask vs. value usage in two more places
[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>
8#include "misc.hh"
10f4eea8 9#include "namespaces.hh"
cfa2996a 10
4226cfd0 11FDMultiplexer* FDMultiplexer::getMultiplexerSilent()
12{
13 FDMultiplexer* ret = nullptr;
14 for(const auto& i : FDMultiplexer::getMultiplexerMap()) {
15 try {
16 ret = i.second();
17 return ret;
18 }
19 catch(const FDMultiplexerException& fe) {
20 }
21 catch(...) {
22 }
23 }
24 return ret;
25}
26
27
926444e2 28class PollFDMultiplexer : public FDMultiplexer
29{
30public:
31 PollFDMultiplexer()
32 {}
33 virtual ~PollFDMultiplexer()
34 {
35 }
36
5bdbb83d
RG
37 virtual int run(struct timeval* tv, int timeout=500) override;
38 virtual void getAvailableFDs(std::vector<int>& fds, int timeout) override;
926444e2 39
27ae2e3c 40 virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override;
5bdbb83d
RG
41 virtual void removeFD(callbackmap_t& cbmap, int fd) override;
42
43 string getName() const override
926444e2 44 {
45 return "poll";
46 }
47private:
5bdbb83d 48 vector<struct pollfd> preparePollFD() const;
926444e2 49};
cfa2996a
BH
50
51static FDMultiplexer* make()
52{
53 return new PollFDMultiplexer();
54}
55
56static struct RegisterOurselves
57{
58 RegisterOurselves() {
59 FDMultiplexer::getMultiplexerMap().insert(make_pair(1, &make));
60 }
61} doIt;
62
27ae2e3c 63void PollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd)
cfa2996a 64{
27ae2e3c 65 accountingAddFD(cbmap, fd, toDo, parameter, ttd);
cfa2996a
BH
66}
67
68void PollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
69{
ac3da0c2 70 if(d_inrun && d_iter->d_fd==fd) // trying to remove us!
4b5da564 71 ++d_iter;
cfa2996a
BH
72
73 if(!cbmap.erase(fd))
335da0ba 74 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
cfa2996a
BH
75}
76
5bdbb83d 77vector<struct pollfd> PollFDMultiplexer::preparePollFD() const
cfa2996a 78{
cfa2996a 79 vector<struct pollfd> pollfds;
5bdbb83d
RG
80 pollfds.reserve(d_readCallbacks.size() + d_writeCallbacks.size());
81
cfa2996a 82 struct pollfd pollfd;
5bdbb83d 83 for(const auto& cb : d_readCallbacks) {
ac3da0c2 84 pollfd.fd = cb.d_fd;
cfa2996a
BH
85 pollfd.events = POLLIN;
86 pollfds.push_back(pollfd);
87 }
88
5bdbb83d 89 for(const auto& cb : d_writeCallbacks) {
ac3da0c2 90 pollfd.fd = cb.d_fd;
cfa2996a
BH
91 pollfd.events = POLLOUT;
92 pollfds.push_back(pollfd);
93 }
94
5bdbb83d
RG
95 return pollfds;
96}
97
98void PollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
99{
100 auto pollfds = preparePollFD();
101 int ret = poll(&pollfds[0], pollfds.size(), timeout);
102
103 if (ret < 0 && errno != EINTR)
104 throw FDMultiplexerException("poll returned error: " + stringerror());
105
106 for(const auto& pollfd : pollfds) {
c1ee10a6 107 if (pollfd.revents & POLLIN || pollfd.revents & POLLOUT) {
5bdbb83d
RG
108 fds.push_back(pollfd.fd);
109 }
110 }
111}
112
113int PollFDMultiplexer::run(struct timeval* now, int timeout)
114{
115 if(d_inrun) {
116 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
117 }
118
119 auto pollfds = preparePollFD();
120
0e663c3b
RG
121 int ret=poll(&pollfds[0], pollfds.size(), timeout);
122 gettimeofday(now, 0); // MANDATORY!
cfa2996a
BH
123
124 if(ret < 0 && errno!=EINTR)
125 throw FDMultiplexerException("poll returned error: "+stringerror());
126
127 d_iter=d_readCallbacks.end();
128 d_inrun=true;
0e663c3b 129
5bdbb83d 130 for(const auto& pollfd : pollfds) {
815986fe 131 if(pollfd.revents & POLLIN) {
5bdbb83d 132 d_iter=d_readCallbacks.find(pollfd.fd);
cfa2996a
BH
133
134 if(d_iter != d_readCallbacks.end()) {
ac3da0c2 135 d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
cfa2996a
BH
136 continue; // so we don't refind ourselves as writable!
137 }
138 }
815986fe 139 else if(pollfd.revents & POLLOUT) {
5bdbb83d 140 d_iter=d_writeCallbacks.find(pollfd.fd);
cfa2996a
BH
141
142 if(d_iter != d_writeCallbacks.end()) {
ac3da0c2 143 d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
cfa2996a
BH
144 }
145 }
146 }
147 d_inrun=false;
0e663c3b 148 return ret;
cfa2996a
BH
149}
150
151#if 0
152
153void acceptData(int fd, boost::any& parameter)
154{
155 cout<<"Have data on fd "<<fd<<endl;
156 Socket* sock=boost::any_cast<Socket*>(parameter);
157 string packet;
158 IPEndpoint rem;
159 sock->recvFrom(packet, rem);
160 cout<<"Received "<<packet.size()<<" bytes!\n";
161}
162
163
164int main()
165{
a5794017 166 Socket s(AF_INET, SOCK_DGRAM);
cfa2996a
BH
167
168 IPEndpoint loc("0.0.0.0", 2000);
169 s.bind(loc);
170
171 PollFDMultiplexer sfm;
172
173 sfm.addReadFD(s.getHandle(), &acceptData, &s);
174
175 for(int n=0; n < 100 ; ++n) {
176 sfm.run();
177 }
178 sfm.removeReadFD(s.getHandle());
179 sfm.removeReadFD(s.getHandle());
180}
181#endif
182