]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/selectmplexer.cc
auth 4.1 build: Switch to devtoolset 7 for el6
[thirdparty/pdns.git] / pdns / selectmplexer.cc
CommitLineData
870a0fe4
AT
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
ab3e8a6c
BH
4#include "mplexer.hh"
5#include "sstuff.hh"
6#include <iostream>
ab3e8a6c 7#include "misc.hh"
ab3e8a6c 8
10f4eea8 9#include "namespaces.hh"
ab3e8a6c 10
1f4abb20 11static FDMultiplexer* make()
a1dfcec8
BH
12{
13 return new SelectFDMultiplexer();
14}
15
1f4abb20
BH
16static struct RegisterOurselves
17{
18 RegisterOurselves() {
19 FDMultiplexer::getMultiplexerMap().insert(make_pair(1, &make));
20 }
21} doIt;
a1dfcec8 22
c454d11b 23void SelectFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter)
ab3e8a6c
BH
24{
25 Callback cb;
26 cb.d_callback=toDo;
27 cb.d_parameter=parameter;
0bff046b 28 memset(&cb.d_ttd, 0, sizeof(cb.d_ttd));
ab3e8a6c 29 if(cbmap.count(fd))
335da0ba 30 throw FDMultiplexerException("Tried to add fd "+std::to_string(fd)+ " to multiplexer twice");
ab3e8a6c
BH
31 cbmap[fd]=cb;
32}
33
34void SelectFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
35{
a1dfcec8
BH
36 if(d_inrun && d_iter->first==fd) // trying to remove us!
37 d_iter++;
38
ab3e8a6c 39 if(!cbmap.erase(fd))
335da0ba 40 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
ab3e8a6c
BH
41}
42
0e663c3b 43int SelectFDMultiplexer::run(struct timeval* now, int timeout)
ab3e8a6c 44{
a1dfcec8
BH
45 if(d_inrun) {
46 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
47 }
ab3e8a6c
BH
48 fd_set readfds, writefds;
49 FD_ZERO(&readfds);
50 FD_ZERO(&writefds);
51
52 int fdmax=0;
53
54 for(callbackmap_t::const_iterator i=d_readCallbacks.begin(); i != d_readCallbacks.end(); ++i) {
55 FD_SET(i->first, &readfds);
56 fdmax=max(i->first, fdmax);
57 }
a1dfcec8
BH
58
59 for(callbackmap_t::const_iterator i=d_writeCallbacks.begin(); i != d_writeCallbacks.end(); ++i) {
60 FD_SET(i->first, &writefds);
61 fdmax=max(i->first, fdmax);
62 }
ab3e8a6c 63
0e663c3b 64 struct timeval tv={timeout / 1000 , (timeout % 1000) * 1000};
ab3e8a6c 65 int ret=select(fdmax + 1, &readfds, &writefds, 0, &tv);
0e663c3b 66 gettimeofday(now, 0); // MANDATORY!
ab3e8a6c
BH
67
68 if(ret < 0 && errno!=EINTR)
69 throw FDMultiplexerException("select returned error: "+stringerror());
70
f3c5773b 71 if(ret < 1) // nothing - thanks AB
ab3e8a6c
BH
72 return 0;
73
a1dfcec8 74 d_iter=d_readCallbacks.end();
ab3e8a6c 75 d_inrun=true;
0e663c3b
RG
76
77 int got = 0;
a1dfcec8
BH
78 for(callbackmap_t::iterator i=d_readCallbacks.begin(); i != d_readCallbacks.end() && i->first <= fdmax; ) {
79 d_iter=i++;
ab3e8a6c 80
a1dfcec8
BH
81 if(FD_ISSET(d_iter->first, &readfds)) {
82 d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
0e663c3b 83 got++;
abbd6830 84 continue; // so we don't refind ourselves as writable
a1dfcec8 85 }
ab3e8a6c
BH
86 }
87
a1dfcec8
BH
88 for(callbackmap_t::iterator i=d_writeCallbacks.begin(); i != d_writeCallbacks.end() && i->first <= fdmax; ) {
89 d_iter=i++;
90 if(FD_ISSET(d_iter->first, &writefds)) {
91 d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
0e663c3b 92 got++;
a1dfcec8
BH
93 }
94 }
ab3e8a6c
BH
95
96 d_inrun=false;
0e663c3b 97 return got;
ab3e8a6c
BH
98}
99
a1dfcec8
BH
100#if 0
101
ab3e8a6c
BH
102void acceptData(int fd, boost::any& parameter)
103{
104 cout<<"Have data on fd "<<fd<<endl;
105 Socket* sock=boost::any_cast<Socket*>(parameter);
106 string packet;
107 IPEndpoint rem;
108 sock->recvFrom(packet, rem);
109 cout<<"Received "<<packet.size()<<" bytes!\n";
110}
111
a1dfcec8 112
ab3e8a6c
BH
113int main()
114{
a5794017 115 Socket s(AF_INET, SOCK_DGRAM);
ab3e8a6c
BH
116
117 IPEndpoint loc("0.0.0.0", 2000);
118 s.bind(loc);
119
120 SelectFDMultiplexer sfm;
121
122 sfm.addReadFD(s.getHandle(), &acceptData, &s);
123
124 for(int n=0; n < 100 ; ++n) {
125 sfm.run();
126 }
127 sfm.removeReadFD(s.getHandle());
128 sfm.removeReadFD(s.getHandle());
129}
130#endif
131