]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/syncres.hh
make asyncresolve accept d_now from caller, and use it to seed DTime, and refill...
[thirdparty/pdns.git] / pdns / syncres.hh
CommitLineData
00a19ff7
BH
1#ifndef PDNS_SYNCRES_HH
2#define PDNS_SYNCRES_HH
3#include <string>
4#include "dns.hh"
5#include "qtype.hh"
6#include <vector>
7#include <set>
8#include <map>
eefd15f9
BH
9#include <cmath>
10#include <iostream>
11#include <utility>
c836dc19 12#include "misc.hh"
00a19ff7 13#include "lwres.hh"
d6d5dea7 14#include <boost/utility.hpp>
1d5b3ce6 15#include "sstuff.hh"
9fdf67d5 16#include "recursor_cache.hh"
1d5b3ce6
BH
17#include <boost/tuple/tuple.hpp>
18#include <boost/tuple/tuple_comparison.hpp>
19#include "mtasker.hh"
eefd15f9 20
00a19ff7 21/* external functions, opaque to us */
eefd15f9 22
bdf40704 23void primeHints(void);
00a19ff7 24
38e22b5a
BH
25struct NegCacheEntry
26{
27 string name;
28 time_t ttd;
29};
00a19ff7 30
49f076e8
BH
31
32template<class Thing> class Throttle
33{
34public:
35 Throttle()
36 {
37 d_limit=3;
38 d_ttl=60;
39 d_last_clean=time(0);
40 }
87da00e7 41 bool shouldThrottle(time_t now, const Thing& t)
49f076e8 42 {
49f076e8
BH
43 if(now > d_last_clean + 60 ) {
44 d_last_clean=now;
45 for(typename cont_t::iterator i=d_cont.begin();i!=d_cont.end();)
46 if( i->second.ttd > now) {
47 d_cont.erase(i++);
48 }
49 else
50 ++i;
51 }
52
49f076e8
BH
53 typename cont_t::iterator i=d_cont.find(t);
54 if(i==d_cont.end())
55 return false;
014c60c3 56 if(now > i->second.ttd || i->second.count-- < 0) {
49f076e8 57 d_cont.erase(i);
49f076e8 58 }
014c60c3
BH
59
60 return true; // still listed, still blocked
49f076e8 61 }
87da00e7 62 void throttle(time_t now, const Thing& t, unsigned int ttl=0, unsigned int tries=0)
49f076e8
BH
63 {
64 typename cont_t::iterator i=d_cont.find(t);
87da00e7 65 entry e={ now+(ttl ? ttl : d_ttl), tries ? tries : d_limit};
49f076e8 66
c214232f 67 if(i==d_cont.end()) {
49f076e8 68 d_cont[t]=e;
c214232f
BH
69 }
70 else if(i->second.ttd > e.ttd || (i->second.count) < e.count)
71 d_cont[t]=e;
8a5602d4
BH
72 }
73
74 unsigned int size()
75 {
76 return d_cont.size();
49f076e8
BH
77 }
78private:
79 int d_limit;
80 int d_ttl;
81 time_t d_last_clean;
82 struct entry
83 {
84 time_t ttd;
85 int count;
86 };
87 typedef map<Thing,entry> cont_t;
88 cont_t d_cont;
89};
90
91
eefd15f9 92/** Class that implements a decaying EWMA.
36c5ee42 93 This class keeps an exponentially weighted moving average which, additionally, decays over time.
eefd15f9
BH
94 The decaying is only done on get.
95*/
96class DecayingEwma
97{
98public:
d6d5dea7
BH
99 DecayingEwma() : d_last(getTime()) , d_lastget(d_last), d_val(0.0) {
100
36c5ee42 101 }
d6d5dea7
BH
102
103 DecayingEwma(const DecayingEwma& orig) : d_last(orig.d_last), d_lastget(orig.d_lastget), d_val(orig.d_val)
eefd15f9 104 {
d6d5dea7
BH
105
106 }
107
108 void submit(int val, struct timeval*tv = 0)
109 {
9fdf67d5 110 float now;
d6d5dea7
BH
111 if(tv)
112 now=tv->tv_sec + tv->tv_usec/1000000.0;
113 else
114 now=getTime();
115
9fdf67d5 116 float diff=d_last-now;
36c5ee42 117 d_last=now;
9fdf67d5 118 float factor=exp(diff)/2.0; // might be '0.5', or 0.0001
eefd15f9
BH
119 d_val=(1-factor)*val+ factor*d_val;
120 }
d6d5dea7 121
9fdf67d5 122 float get(struct timeval*tv = 0)
eefd15f9 123 {
9fdf67d5 124 float now;
d6d5dea7
BH
125 if(tv)
126 now=tv->tv_sec + tv->tv_usec/1000000.0;
127 else
128 now=getTime();
129
9fdf67d5 130 float diff=d_lastget-now;
36c5ee42 131 d_lastget=now;
9fdf67d5 132 float factor=exp(diff/60.0); // is 1.0 or less
eefd15f9
BH
133 return d_val*=factor;
134 }
135
9fdf67d5
BH
136 bool stale(time_t limit)
137 {
138 return limit > d_lastget;
139 }
140
eefd15f9 141private:
d6d5dea7 142 DecayingEwma& operator=(const DecayingEwma&);
9fdf67d5
BH
143 float d_last;
144 float d_lastget;
145 float d_val;
eefd15f9
BH
146};
147
148
7b35aa49 149class SyncRes
00a19ff7
BH
150{
151public:
d6d5dea7 152 SyncRes() : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_cacheonly(false), d_nocache(false) { gettimeofday(&d_now, 0); }
00a19ff7 153 int beginResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret);
c836dc19
BH
154 void setId(int id)
155 {
9fdf67d5
BH
156 if(s_log)
157 d_prefix="["+itoa(id)+"] ";
c836dc19
BH
158 }
159 static void setLog(bool log)
160 {
161 s_log=log;
162 }
163 void setCacheOnly(bool state=true)
164 {
165 d_cacheonly=state;
166 }
167 void setNoCache(bool state=true)
168 {
169 d_nocache=state;
170 }
171 static unsigned int s_queries;
7becf07f 172 static unsigned int s_outgoingtimeouts;
3de83124 173 static unsigned int s_throttledqueries;
c836dc19 174 static unsigned int s_outqueries;
5c633640 175 static unsigned int s_tcpoutqueries;
525b8a7c 176 static unsigned int s_nodelegated;
c836dc19 177 unsigned int d_outqueries;
5c633640 178 unsigned int d_tcpoutqueries;
3de83124 179 unsigned int d_throttledqueries;
d77df2e1 180 unsigned int d_timeouts;
9fdf67d5
BH
181 typedef map<string,NegCacheEntry> negcache_t;
182 static negcache_t s_negcache;
183
184 typedef map<string,DecayingEwma> nsspeeds_t;
185 static nsspeeds_t s_nsSpeeds;
186
1d5b3ce6
BH
187 typedef Throttle<string> throttle_t;
188 static throttle_t s_throttle;
00a19ff7
BH
189private:
190 struct GetBestNSAnswer;
191 int doResolveAt(set<string> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
192 int depth, set<GetBestNSAnswer>&beenthere);
193 int doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
194 bool doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
195 bool doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
196 void getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, int depth, set<GetBestNSAnswer>& beenthere);
197 void addCruft(const string &qname, vector<DNSResourceRecord>& ret);
198 string getBestNSNamesFromCache(const string &qname,set<string>& nsset, int depth, set<GetBestNSAnswer>&beenthere);
199 void addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth);
200
d8d0bb8f 201 inline vector<string> shuffle(set<string> &nameservers, const string &prefix);
00a19ff7 202 bool moreSpecificThan(const string& a, const string &b);
bfea0d0b 203 vector<string> getAs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere);
c75a6a9e 204
36c5ee42
BH
205 SyncRes(const SyncRes&);
206 SyncRes& operator=(const SyncRes&);
00a19ff7 207private:
c836dc19
BH
208 string d_prefix;
209 static bool s_log;
210 bool d_cacheonly;
211 bool d_nocache;
7b35aa49 212 LWRes d_lwr;
d6d5dea7 213 struct timeval d_now;
c75a6a9e 214
00a19ff7
BH
215 struct GetBestNSAnswer
216 {
217 string qname;
218 set<DNSResourceRecord> bestns;
219 bool operator<(const GetBestNSAnswer &b) const
220 {
221 if(qname<b.qname)
222 return true;
223 if(qname==b.qname)
224 return bestns<b.bestns;
225 return false;
226 }
227 };
228
229};
5c633640
BH
230class Socket;
231int asendtcp(const string& data, Socket* sock);
232int arecvtcp(string& data, int len, Socket* sock);
1d5b3ce6
BH
233
234
235struct PacketID
236{
237 PacketID() : sock(0), inNeeded(0), outPos(0)
238 {}
239
240 uint16_t id; // wait for a specific id/remote pair
241 struct sockaddr_in remote; // this is the remote
242
243 Socket* sock; // or wait for an event on a TCP fd
244 int inNeeded; // if this is set, we'll read until inNeeded bytes are read
245 string inMSG; // they'll go here
246
247 string outMSG; // the outgoing message that needs to be sent
248 string::size_type outPos; // how far we are along in the outMSG
249
250 bool operator<(const PacketID& b) const
251 {
252 int ourSock= sock ? sock->getHandle() : 0;
253 int bSock = b.sock ? b.sock->getHandle() : 0;
254 return
255 tie(id, remote.sin_addr.s_addr, remote.sin_port, ourSock) <
256 tie(b.id, b.remote.sin_addr.s_addr, b.remote.sin_port, bSock);
257 }
258};
259
260extern MemRecursorCache RC;
261extern uint64_t qcounter;
262extern MTasker<PacketID,string>* MT;
263
264struct RecursorStats
265{
266 uint64_t servFails;
267 uint64_t nxDomains;
268 uint64_t noErrors;
269};
270
271extern RecursorStats g_stats;
00a19ff7 272#endif