]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/selectmplexer.cc
rec: Don't account chained queries more than once
[thirdparty/pdns.git] / pdns / selectmplexer.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include "mplexer.hh"
5 #include "sstuff.hh"
6 #include <iostream>
7 #include "misc.hh"
8
9 #include "namespaces.hh"
10
11 static FDMultiplexer* make()
12 {
13 return new SelectFDMultiplexer();
14 }
15
16 static struct RegisterOurselves
17 {
18 RegisterOurselves() {
19 FDMultiplexer::getMultiplexerMap().insert(make_pair(1, &make));
20 }
21 } doIt;
22
23 void SelectFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter)
24 {
25 Callback cb;
26 cb.d_callback=toDo;
27 cb.d_parameter=parameter;
28 memset(&cb.d_ttd, 0, sizeof(cb.d_ttd));
29 if(cbmap.count(fd))
30 throw FDMultiplexerException("Tried to add fd "+std::to_string(fd)+ " to multiplexer twice");
31 cbmap[fd]=cb;
32 }
33
34 void SelectFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
35 {
36 if(d_inrun && d_iter->first==fd) // trying to remove us!
37 d_iter++;
38
39 if(!cbmap.erase(fd))
40 throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
41 }
42
43 int SelectFDMultiplexer::run(struct timeval* now, int timeout)
44 {
45 if(d_inrun) {
46 throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
47 }
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 }
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 }
63
64 struct timeval tv={timeout / 1000 , (timeout % 1000) * 1000};
65 int ret=select(fdmax + 1, &readfds, &writefds, 0, &tv);
66 gettimeofday(now, 0); // MANDATORY!
67
68 if(ret < 0 && errno!=EINTR)
69 throw FDMultiplexerException("select returned error: "+stringerror());
70
71 if(ret < 1) // nothing - thanks AB
72 return 0;
73
74 d_iter=d_readCallbacks.end();
75 d_inrun=true;
76
77 int got = 0;
78 for(callbackmap_t::iterator i=d_readCallbacks.begin(); i != d_readCallbacks.end() && i->first <= fdmax; ) {
79 d_iter=i++;
80
81 if(FD_ISSET(d_iter->first, &readfds)) {
82 d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
83 got++;
84 continue; // so we don't refind ourselves as writable
85 }
86 }
87
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);
92 got++;
93 }
94 }
95
96 d_inrun=false;
97 return got;
98 }
99
100 #if 0
101
102 void 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
112
113 int main()
114 {
115 Socket s(AF_INET, SOCK_DGRAM);
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