]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/devpollmplexer.cc
dnsdist: Add HTTPStatusAction to return a specific HTTP response
[thirdparty/pdns.git] / pdns / devpollmplexer.cc
CommitLineData
12471842
PL
1/*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
e22156da
JJS
25/*
26 * NOTE: sys/devpoll.h relies on sigset_t being already defined so we need
27 * to include sys/signal.h *before* including sys/devpoll.h.
28 */
29#include <sys/signal.h>
781d550a
BH
30#include <sys/devpoll.h>
31#include "mplexer.hh"
32#include "sstuff.hh"
33#include <iostream>
34#include <unistd.h>
35#include "misc.hh"
781d550a 36
10f4eea8 37#include "namespaces.hh"
781d550a
BH
38
39class DevPollFDMultiplexer : public FDMultiplexer
40{
41public:
42 DevPollFDMultiplexer();
43 virtual ~DevPollFDMultiplexer()
44 {
45 close(d_devpollfd);
46 }
47
5bdbb83d
RG
48 virtual int run(struct timeval* tv, int timeout=500) override;
49 virtual void getAvailableFDs(std::vector<int>& fds, int timeout) override;
781d550a 50
27ae2e3c 51 virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override;
5bdbb83d
RG
52 virtual void removeFD(callbackmap_t& cbmap, int fd) override;
53 string getName() const override
781d550a
BH
54 {
55 return "/dev/poll";
56 }
57private:
58 int d_devpollfd;
59};
60
61
62static FDMultiplexer* makeDevPoll()
63{
64 return new DevPollFDMultiplexer();
65}
66
67static struct DevPollRegisterOurselves
68{
69 DevPollRegisterOurselves() {
70 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeDevPoll)); // priority 0!
71 }
72} doItDevPoll;
73
74
75//int DevPollFDMultiplexer::s_maxevents=1024;
76DevPollFDMultiplexer::DevPollFDMultiplexer()
77{
78 d_devpollfd=open("/dev/poll", O_RDWR);
79 if(d_devpollfd < 0)
80 throw FDMultiplexerException("Setting up /dev/poll: "+stringerror());
81
82}
83
27ae2e3c 84void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd)
781d550a 85{
27ae2e3c 86 accountingAddFD(cbmap, fd, toDo, parameter, ttd);
781d550a
BH
87
88 struct pollfd devent;
89 devent.fd=fd;
90 devent.events= (&cbmap == &d_readCallbacks) ? POLLIN : POLLOUT;
91 devent.revents = 0;
92
93 if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) {
94 cbmap.erase(fd);
95 throw FDMultiplexerException("Adding fd to /dev/poll/ set: "+stringerror());
96 }
97}
98
99void DevPollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
100{
101 if(!cbmap.erase(fd))
335da0ba 102 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
781d550a
BH
103
104 struct pollfd devent;
105 devent.fd=fd;
106 devent.events= POLLREMOVE;
107 devent.revents = 0;
108
109 if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) {
110 cbmap.erase(fd);
111 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
112 }
113}
114
5bdbb83d
RG
115void DevPollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
116{
117 struct dvpoll dvp;
118 dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size();
119 dvp.dp_fds = new pollfd[dvp.dp_nfds];
120 dvp.dp_timeout = timeout;
121 int ret=ioctl(d_devpollfd, DP_POLL, &dvp);
122
123 if(ret < 0 && errno!=EINTR) {
124 delete[] dvp.dp_fds;
125 throw FDMultiplexerException("/dev/poll returned error: "+stringerror());
126 }
127
128 for(int n=0; n < ret; ++n) {
129 fds.push_back(dvp.dp_fds[n].fd);
130 }
131
132 delete[] dvp.dp_fds;
133}
134
0e663c3b 135int DevPollFDMultiplexer::run(struct timeval* now, int timeout)
781d550a
BH
136{
137 if(d_inrun) {
138 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
139 }
140 struct dvpoll dvp;
141 dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size();
142 dvp.dp_fds = new pollfd[dvp.dp_nfds];
0e663c3b 143 dvp.dp_timeout = timeout;
5bdbb83d 144 int ret=ioctl(d_devpollfd, DP_POLL, &dvp);
55df795b 145 gettimeofday(now,0); // MANDATORY!
5bdbb83d 146
6b1933ac
JJS
147 if(ret < 0 && errno!=EINTR) {
148 delete[] dvp.dp_fds;
781d550a 149 throw FDMultiplexerException("/dev/poll returned error: "+stringerror());
6b1933ac 150 }
781d550a 151
6b1933ac
JJS
152 if(ret < 1) { // thanks AB!
153 delete[] dvp.dp_fds;
781d550a 154 return 0;
6b1933ac 155 }
781d550a
BH
156
157 d_inrun=true;
158 for(int n=0; n < ret; ++n) {
159 d_iter=d_readCallbacks.find(dvp.dp_fds[n].fd);
160
161 if(d_iter != d_readCallbacks.end()) {
ac3da0c2 162 d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
781d550a
BH
163 continue; // so we don't refind ourselves as writable!
164 }
165 d_iter=d_writeCallbacks.find(dvp.dp_fds[n].fd);
166
167 if(d_iter != d_writeCallbacks.end()) {
ac3da0c2 168 d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
781d550a
BH
169 }
170 }
171 delete[] dvp.dp_fds;
172 d_inrun=false;
0e663c3b 173 return ret;
781d550a
BH
174}
175
176#if 0
177void acceptData(int fd, funcparam_t& parameter)
178{
179 cout<<"Have data on fd "<<fd<<endl;
180 Socket* sock=funcparam_t_cast<Socket*>(parameter);
181 string packet;
182 IPEndpoint rem;
183 sock->recvFrom(packet, rem);
184 cout<<"Received "<<packet.size()<<" bytes!\n";
185}
186
187
188int main()
189{
a5794017 190 Socket s(AF_INET, SOCK_DGRAM);
781d550a
BH
191
192 IPEndpoint loc("0.0.0.0", 2000);
193 s.bind(loc);
194
195 DevPollFDMultiplexer sfm;
196
197 sfm.addReadFD(s.getHandle(), &acceptData, &s);
198
199 for(int n=0; n < 100 ; ++n) {
200 sfm.run();
201 }
202 sfm.removeReadFD(s.getHandle());
203 sfm.removeReadFD(s.getHandle());
204}
205#endif
206
207