]>
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"
35 #include "namespaces.hh"
37 class EpollFDMultiplexer
: public FDMultiplexer
41 virtual ~EpollFDMultiplexer()
46 virtual int run(struct timeval
* tv
);
48 virtual void addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
);
49 virtual void removeFD(callbackmap_t
& cbmap
, int fd
);
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!
74 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
)
99 accountingAddFD(cbmap
, fd
, toDo
, parameter
);
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 int EpollFDMultiplexer::run(struct timeval
* now
)
130 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
133 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, 500);
134 gettimeofday(now
,0); // MANDATORY
136 if(ret
< 0 && errno
!=EINTR
)
137 throw FDMultiplexerException("epoll returned error: "+stringerror());
139 if(ret
< 1) // thanks AB!
143 for(int n
=0; n
< ret
; ++n
) {
144 d_iter
=d_readCallbacks
.find(d_eevents
[n
].data
.fd
);
146 if(d_iter
!= d_readCallbacks
.end()) {
147 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
148 continue; // so we don't refind ourselves as writable!
150 d_iter
=d_writeCallbacks
.find(d_eevents
[n
].data
.fd
);
152 if(d_iter
!= d_writeCallbacks
.end()) {
153 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
161 void acceptData(int fd
, funcparam_t
& parameter
)
163 cout
<<"Have data on fd "<<fd
<<endl
;
164 Socket
* sock
=funcparam_t_cast
<Socket
*>(parameter
);
167 sock
->recvFrom(packet
, rem
);
168 cout
<<"Received "<<packet
.size()<<" bytes!\n";
174 Socket
s(AF_INET
, SOCK_DGRAM
);
176 IPEndpoint
loc("0.0.0.0", 2000);
179 EpollFDMultiplexer sfm
;
181 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
183 for(int n
=0; n
< 100 ; ++n
) {
186 sfm
.removeReadFD(s
.getHandle());
187 sfm
.removeReadFD(s
.getHandle());