]>
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.
32 #include <sys/epoll.h>
35 #include "namespaces.hh"
36 #include "namespaces.hh"
38 class EpollFDMultiplexer
: public FDMultiplexer
42 virtual ~EpollFDMultiplexer()
47 virtual int run(struct timeval
* tv
);
49 virtual void addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
);
50 virtual void removeFD(callbackmap_t
& cbmap
, int fd
);
57 boost::shared_array
<epoll_event
> d_eevents
;
58 static int s_maxevents
; // not a hard maximum
62 static FDMultiplexer
* makeEpoll()
64 return new EpollFDMultiplexer();
67 static struct EpollRegisterOurselves
69 EpollRegisterOurselves() {
70 FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeEpoll
)); // priority 0!
75 int EpollFDMultiplexer::s_maxevents
=1024;
76 EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event
[s_maxevents
])
78 d_epollfd
=epoll_create(s_maxevents
); // not hard max
80 throw FDMultiplexerException("Setting up epoll: "+stringerror());
81 int fd
=socket(AF_INET
, SOCK_DGRAM
, 0); // for self-test
90 catch(FDMultiplexerException
&fe
) {
93 throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe
.what()));
98 void EpollFDMultiplexer::addFD(callbackmap_t
& cbmap
, int fd
, callbackfunc_t toDo
, const funcparam_t
& parameter
)
100 accountingAddFD(cbmap
, fd
, toDo
, parameter
);
102 struct epoll_event eevent
;
104 eevent
.events
= (&cbmap
== &d_readCallbacks
) ? EPOLLIN
: EPOLLOUT
;
106 eevent
.data
.u64
=0; // placate valgrind (I love it so much)
109 if(epoll_ctl(d_epollfd
, EPOLL_CTL_ADD
, fd
, &eevent
) < 0) {
111 throw FDMultiplexerException("Adding fd to epoll set: "+stringerror());
115 void EpollFDMultiplexer::removeFD(callbackmap_t
& cbmap
, int fd
)
118 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd
)+ " from multiplexer");
120 struct epoll_event dummy
;
124 if(epoll_ctl(d_epollfd
, EPOLL_CTL_DEL
, fd
, &dummy
) < 0)
125 throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
128 int EpollFDMultiplexer::run(struct timeval
* now
)
131 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
134 int ret
=epoll_wait(d_epollfd
, d_eevents
.get(), s_maxevents
, 500);
135 gettimeofday(now
,0); // MANDATORY
137 if(ret
< 0 && errno
!=EINTR
)
138 throw FDMultiplexerException("epoll returned error: "+stringerror());
140 if(ret
< 1) // thanks AB!
144 for(int n
=0; n
< ret
; ++n
) {
145 d_iter
=d_readCallbacks
.find(d_eevents
[n
].data
.fd
);
147 if(d_iter
!= d_readCallbacks
.end()) {
148 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
149 continue; // so we don't refind ourselves as writable!
151 d_iter
=d_writeCallbacks
.find(d_eevents
[n
].data
.fd
);
153 if(d_iter
!= d_writeCallbacks
.end()) {
154 d_iter
->second
.d_callback(d_iter
->first
, d_iter
->second
.d_parameter
);
162 void acceptData(int fd
, funcparam_t
& parameter
)
164 cout
<<"Have data on fd "<<fd
<<endl
;
165 Socket
* sock
=funcparam_t_cast
<Socket
*>(parameter
);
168 sock
->recvFrom(packet
, rem
);
169 cout
<<"Received "<<packet
.size()<<" bytes!\n";
175 Socket
s(AF_INET
, SOCK_DGRAM
);
177 IPEndpoint
loc("0.0.0.0", 2000);
180 EpollFDMultiplexer sfm
;
182 sfm
.addReadFD(s
.getHandle(), &acceptData
, &s
);
184 for(int n
=0; n
< 100 ; ++n
) {
187 sfm
.removeReadFD(s
.getHandle());
188 sfm
.removeReadFD(s
.getHandle());