]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/epollmplexer.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
31 #include <sys/epoll.h>
34 #include "namespaces.hh"
36 class EpollFDMultiplexer
: public FDMultiplexer
40 virtual ~EpollFDMultiplexer()
45 virtual int run(struct timeval
* tv
, int timeout
=500) override
;
46 virtual void getAvailableFDs(std::vector
<int>& fds
, int timeout
) override
;
48 virtual void addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
, const struct timeval
* ttd
=nullptr) override
;
49 virtual void removeFD(callbackmap_t
& cbmap
, int fd
) override
;
50 string
getName() const override
56 boost::shared_array
<epoll_event
> d_eevents
;
57 static int s_maxevents
; // not a hard maximum
61 static FDMultiplexer
* makeEpoll()
63 return new EpollFDMultiplexer();
66 static struct EpollRegisterOurselves
68 EpollRegisterOurselves() {
69 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeEpoll
)); // priority 0!
73 int EpollFDMultiplexer::s_maxevents
=1024;
75 EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event
[s_maxevents
])
77 d_epollfd
=epoll_create(s_maxevents
); // not hard max
79 throw FDMultiplexerException("Setting up epoll: "+stringerror());
80 int fd
=socket(AF_INET
, SOCK_DGRAM
, 0); // for self-test
89 catch(FDMultiplexerException
&fe
) {
92 throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe
.what()));
97 void EpollFDMultiplexer::addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
, const struct timeval
* ttd
)
99 accountingAddFD(cbmap
, fd
, toDo
, parameter
, ttd
);
101 struct epoll_event eevent
;
103 eevent
.events
= (&cbmap
== &d_readCallbacks
) ? EPOLLIN
: EPOLLOUT
;
105 eevent
.data
.u64
=0; // placate valgrind (I love it so much)
108 if(epoll_ctl(d_epollfd
, EPOLL_CTL_ADD
, fd
, &eevent
) < 0) {
110 throw FDMultiplexerException("Adding fd to epoll set: "+stringerror());
114 void EpollFDMultiplexer::removeFD(callbackmap_t
& cbmap
, int fd
)
117 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd
)+ " from multiplexer");
119 struct epoll_event dummy
;
123 if(epoll_ctl(d_epollfd
, EPOLL_CTL_DEL
, fd
, &dummy
) < 0)
124 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
127 void EpollFDMultiplexer::getAvailableFDs(std::vector
<int>& fds
, int timeout
)
129 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, timeout
);
131 if(ret
< 0 && errno
!=EINTR
)
132 throw FDMultiplexerException("epoll returned error: "+stringerror());
134 for(int n
=0; n
< ret
; ++n
) {
135 fds
.push_back(d_eevents
[n
].data
.fd
);
139 int EpollFDMultiplexer::run(struct timeval
* now
, int timeout
)
142 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
145 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, timeout
);
146 gettimeofday(now
,0); // MANDATORY
148 if(ret
< 0 && errno
!=EINTR
)
149 throw FDMultiplexerException("epoll returned error: "+stringerror());
151 if(ret
< 1) // thanks AB!
155 for(int n
=0; n
< ret
; ++n
) {
156 d_iter
=d_readCallbacks
.find(d_eevents
[n
].data
.fd
);
158 if(d_iter
!= d_readCallbacks
.end()) {
159 d_iter
->d_callback(d_iter
->d_fd
, d_iter
->d_parameter
);
160 continue; // so we don't refind ourselves as writable!
162 d_iter
=d_writeCallbacks
.find(d_eevents
[n
].data
.fd
);
164 if(d_iter
!= d_writeCallbacks
.end()) {
165 d_iter
->d_callback(d_iter
->d_fd
, d_iter
->d_parameter
);
173 void acceptData(int fd
, funcparam_t
& parameter
)
175 cout
<<"Have data on fd "<<fd
<<endl
;
176 Socket
* sock
=funcparam_t_cast
<Socket
*>(parameter
);
179 sock
->recvFrom(packet
, rem
);
180 cout
<<"Received "<<packet
.size()<<" bytes!\n";
186 Socket
s(AF_INET
, SOCK_DGRAM
);
188 IPEndpoint
loc("0.0.0.0", 2000);
191 EpollFDMultiplexer sfm
;
193 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
195 for(int n
=0; n
< 100 ; ++n
) {
198 sfm
.removeReadFD(s
.getHandle());
199 sfm
.removeReadFD(s
.getHandle());