Skip to content

Commit ab0ac73

Browse files
committed
Merge #36: Add support to filter nodes by node flags
c9679dc Add whitelist for service filter, use a map for cacheTime (Jonas Schnelli) 5c8b9e3 IP-Query: Use a vector instead a set and random pick an IP (Jonas Schnelli) 839db15 Add support to filter nodes by node flags (Jonas Schnelli)
2 parents 9c32351 + c9679dc commit ab0ac73

File tree

5 files changed

+68
-39
lines changed

5 files changed

+68
-39
lines changed

Diff for: db.cpp

+15-10
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ void CAddrDb::Add_(const CAddress &addr, bool force) {
166166
nDirty++;
167167
}
168168

169-
void CAddrDb::GetIPs_(set<CNetAddr>& ips, int max, const bool* nets) {
169+
void CAddrDb::GetIPs_(set<CNetAddr>& ips, uint64_t requestedFlags, int max, const bool* nets) {
170170
if (goodId.size() == 0) {
171171
int id = -1;
172172
if (ourId.size() == 0) {
@@ -175,23 +175,28 @@ void CAddrDb::GetIPs_(set<CNetAddr>& ips, int max, const bool* nets) {
175175
} else {
176176
id = *ourId.begin();
177177
}
178-
if (id >= 0) {
178+
if (id >= 0 && idToInfo[id].services & requestedFlags) {
179179
ips.insert(idToInfo[id].ip);
180180
}
181181
return;
182182
}
183-
if (max > goodId.size() / 2)
184-
max = goodId.size() / 2;
183+
std::vector<int> goodIdFiltered;
184+
for (std::set<int>::const_iterator it = goodId.begin(); it != goodId.end(); it++) {
185+
if ((idToInfo[*it].services & requestedFlags) == requestedFlags)
186+
goodIdFiltered.push_back(*it);
187+
}
188+
189+
if (!goodIdFiltered.size())
190+
return;
191+
192+
if (max > goodIdFiltered.size() / 2)
193+
max = goodIdFiltered.size() / 2;
185194
if (max < 1)
186195
max = 1;
187-
int low = *goodId.begin();
188-
int high = *goodId.rbegin();
196+
189197
set<int> ids;
190198
while (ids.size() < max) {
191-
int range = high-low+1;
192-
int pos = low + (rand() % range);
193-
int id = *(goodId.lower_bound(pos));
194-
ids.insert(id);
199+
ids.insert(goodIdFiltered[rand() % goodIdFiltered.size()]);
195200
}
196201
for (set<int>::const_iterator it = ids.begin(); it != ids.end(); it++) {
197202
CService &ip = idToInfo[*it].ip;

Diff for: db.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class CAddrDb {
219219
void Bad_(const CService &ip, int ban); // mark an IP as bad (and optionally ban it) (must have been returned by Get_)
220220
void Skipped_(const CService &ip); // mark an IP as skipped (must have been returned by Get_)
221221
int Lookup_(const CService &ip); // look up id of an IP
222-
void GetIPs_(std::set<CNetAddr>& ips, int max, const bool *nets); // get a random set of IPs (shared lock only)
222+
void GetIPs_(std::set<CNetAddr>& ips, uint64_t requestedFlags, int max, const bool *nets); // get a random set of IPs (shared lock only)
223223

224224
public:
225225
std::map<CService, time_t> banned; // nodes that are banned, with their unban time (a)
@@ -351,8 +351,8 @@ class CAddrDb {
351351
}
352352
}
353353
}
354-
void GetIPs(std::set<CNetAddr>& ips, int max, const bool *nets) {
354+
void GetIPs(std::set<CNetAddr>& ips, uint64_t requestedFlags, int max, const bool *nets) {
355355
SHARED_CRITICAL_BLOCK(cs)
356-
GetIPs_(ips, max, nets);
356+
GetIPs_(ips, requestedFlags, max, nets);
357357
}
358358
};

Diff for: dns.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
327327
// A/AAAA records
328328
if ((typ == TYPE_A || typ == TYPE_AAAA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
329329
addr_t addr[32];
330-
int naddr = opt->cb((void*)opt, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY);
330+
int naddr = opt->cb((void*)opt, name, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY);
331331
int n = 0;
332332
while (n < naddr) {
333333
int ret = 1;

Diff for: dns.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ typedef struct {
1818
const char *host;
1919
const char *ns;
2020
const char *mbox;
21-
int (*cb)(void *opt, addr_t *addr, int max, int ipv4, int ipv6);
21+
int (*cb)(void *opt, char *requested_hostname, addr_t *addr, int max, int ipv4, int ipv6);
2222
// stats
2323
uint64_t nRequests;
2424
} dns_opt_t;

Diff for: main.cpp

+48-24
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ using namespace std;
1515

1616
bool fTestNet = false;
1717

18+
uint64_t filter_whitelist[] = {
19+
0x0000000000000001,
20+
0x0000000000000003,
21+
0x0000000000000005,
22+
0x0000000000000007,
23+
0x0000000000000009,
24+
0x000000000000000B,
25+
0x000000000000000D,
26+
0x000000000000000F,
27+
};
28+
1829
class CDnsSeedOpts {
1930
public:
2031
int nThreads;
@@ -167,53 +178,54 @@ extern "C" void* ThreadCrawler(void* data) {
167178
} while(1);
168179
}
169180

170-
extern "C" int GetIPList(void *thread, addr_t *addr, int max, int ipv4, int ipv6);
181+
extern "C" int GetIPList(void *thread, char *requestedHostname, addr_t *addr, int max, int ipv4, int ipv6);
171182

172183
class CDnsThread {
173184
public:
174185
dns_opt_t dns_opt; // must be first
175186
const int id;
176-
vector<addr_t> cache;
187+
std::map<uint64_t, vector<addr_t> > cache;
177188
int nIPv4, nIPv6;
178-
time_t cacheTime;
189+
std::map<uint64_t, time_t> cacheTime;
179190
unsigned int cacheHits;
180191
uint64_t dbQueries;
192+
std::vector<uint64_t> filterWhitelist;
181193

182-
void cacheHit(bool force = false) {
194+
void cacheHit(uint64_t requestedFlags, bool force = false) {
183195
static bool nets[NET_MAX] = {};
184196
if (!nets[NET_IPV4]) {
185197
nets[NET_IPV4] = true;
186198
nets[NET_IPV6] = true;
187199
}
188200
time_t now = time(NULL);
189201
cacheHits++;
190-
if (force || cacheHits > (cache.size()*cache.size()/400) || (cacheHits*cacheHits > cache.size() / 20 && (now - cacheTime > 5))) {
202+
if (force || cacheHits > (cache[requestedFlags].size()*cache[requestedFlags].size()/400) || (cacheHits*cacheHits > cache[requestedFlags].size() / 20 && (now - cacheTime[requestedFlags] > 5))) {
191203
set<CNetAddr> ips;
192-
db.GetIPs(ips, 1000, nets);
204+
db.GetIPs(ips, requestedFlags, 1000, nets);
193205
dbQueries++;
194-
cache.clear();
206+
cache[requestedFlags].clear();
195207
nIPv4 = 0;
196208
nIPv6 = 0;
197-
cache.reserve(ips.size());
209+
cache[requestedFlags].reserve(ips.size());
198210
for (set<CNetAddr>::iterator it = ips.begin(); it != ips.end(); it++) {
199211
struct in_addr addr;
200212
struct in6_addr addr6;
201213
if ((*it).GetInAddr(&addr)) {
202214
addr_t a;
203215
a.v = 4;
204216
memcpy(&a.data.v4, &addr, 4);
205-
cache.push_back(a);
217+
cache[requestedFlags].push_back(a);
206218
nIPv4++;
207219
} else if ((*it).GetIn6Addr(&addr6)) {
208220
addr_t a;
209221
a.v = 6;
210222
memcpy(&a.data.v6, &addr6, 16);
211-
cache.push_back(a);
223+
cache[requestedFlags].push_back(a);
212224
nIPv6++;
213225
}
214226
}
215227
cacheHits = 0;
216-
cacheTime = now;
228+
cacheTime[requestedFlags] = now;
217229
}
218230
}
219231

@@ -227,24 +239,36 @@ class CDnsThread {
227239
dns_opt.port = opts->nPort;
228240
dns_opt.nRequests = 0;
229241
cache.clear();
230-
cache.reserve(1000);
231-
cacheTime = 0;
242+
cacheTime.clear();
232243
cacheHits = 0;
233244
dbQueries = 0;
234245
nIPv4 = 0;
235246
nIPv6 = 0;
236-
cacheHit(true);
247+
filterWhitelist = std::vector<uint64_t>(filter_whitelist, filter_whitelist + (sizeof filter_whitelist / sizeof filter_whitelist[0]));
237248
}
238249

239250
void run() {
240251
dnsserver(&dns_opt);
241252
}
242253
};
243254

244-
extern "C" int GetIPList(void *data, addr_t* addr, int max, int ipv4, int ipv6) {
255+
extern "C" int GetIPList(void *data, char *requestedHostname, addr_t* addr, int max, int ipv4, int ipv6) {
245256
CDnsThread *thread = (CDnsThread*)data;
246-
thread->cacheHit();
247-
unsigned int size = thread->cache.size();
257+
258+
uint64_t requestedFlags = 0;
259+
int hostlen = strlen(requestedHostname);
260+
if (hostlen > 1 && requestedHostname[0] == 'x' && requestedHostname[1] != '0') {
261+
char *pEnd;
262+
uint64_t flags = (uint64_t)strtoull(requestedHostname+1, &pEnd, 16);
263+
if (*pEnd == '.' && pEnd <= requestedHostname+17 && std::find(thread->filterWhitelist.begin(), thread->filterWhitelist.end(), flags) != thread->filterWhitelist.end())
264+
requestedFlags = flags;
265+
else
266+
return 0;
267+
}
268+
else if (strcasecmp(requestedHostname, thread->dns_opt.host))
269+
return 0;
270+
thread->cacheHit(requestedFlags);
271+
unsigned int size = thread->cache[requestedFlags].size();
248272
unsigned int maxmax = (ipv4 ? thread->nIPv4 : 0) + (ipv6 ? thread->nIPv6 : 0);
249273
if (max > size)
250274
max = size;
@@ -254,16 +278,16 @@ extern "C" int GetIPList(void *data, addr_t* addr, int max, int ipv4, int ipv6)
254278
while (i<max) {
255279
int j = i + (rand() % (size - i));
256280
do {
257-
bool ok = (ipv4 && thread->cache[j].v == 4) ||
258-
(ipv6 && thread->cache[j].v == 6);
281+
bool ok = (ipv4 && thread->cache[requestedFlags][j].v == 4) ||
282+
(ipv6 && thread->cache[requestedFlags][j].v == 6);
259283
if (ok) break;
260284
j++;
261285
if (j==size)
262286
j=i;
263287
} while(1);
264-
addr[i] = thread->cache[j];
265-
thread->cache[j] = thread->cache[i];
266-
thread->cache[i] = addr[i];
288+
addr[i] = thread->cache[requestedFlags][j];
289+
thread->cache[requestedFlags][j] = thread->cache[requestedFlags][i];
290+
thread->cache[requestedFlags][i] = addr[i];
267291
i++;
268292
}
269293
return max;
@@ -306,11 +330,11 @@ extern "C" void* ThreadDumper(void*) {
306330
rename("dnsseed.dat.new", "dnsseed.dat");
307331
}
308332
FILE *d = fopen("dnsseed.dump", "w");
309-
fprintf(d, "# address good lastSuccess %%(2h) %%(8h) %%(1d) %%(7d) %%(30d) blocks svcs version\n");
333+
fprintf(d, "# address servicebits good lastSuccess %%(2h) %%(8h) %%(1d) %%(7d) %%(30d) blocks svcs version\n");
310334
double stat[5]={0,0,0,0,0};
311335
for (vector<CAddrReport>::const_iterator it = v.begin(); it < v.end(); it++) {
312336
CAddrReport rep = *it;
313-
fprintf(d, "%-47s %4d %11"PRId64" %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6i %08"PRIx64" %5i \"%s\"\n", rep.ip.ToString().c_str(), (int)rep.fGood, rep.lastSuccess, 100.0*rep.uptime[0], 100.0*rep.uptime[1], 100.0*rep.uptime[2], 100.0*rep.uptime[3], 100.0*rep.uptime[4], rep.blocks, rep.services, rep.clientVersion, rep.clientSubVersion.c_str());
337+
fprintf(d, "%-47s %8lld %4d %11"PRId64" %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6i %08"PRIx64" %5i \"%s\"\n", rep.ip.ToString().c_str(), (uint64_t)rep.services, (int)rep.fGood, rep.lastSuccess, 100.0*rep.uptime[0], 100.0*rep.uptime[1], 100.0*rep.uptime[2], 100.0*rep.uptime[3], 100.0*rep.uptime[4], rep.blocks, rep.services, rep.clientVersion, rep.clientSubVersion.c_str());
314338
stat[0] += rep.uptime[0];
315339
stat[1] += rep.uptime[1];
316340
stat[2] += rep.uptime[2];

0 commit comments

Comments
 (0)