2011-12-16 18:37:05 +01:00
|
|
|
#include <stdint.h>
|
2011-12-19 23:18:06 +01:00
|
|
|
#include <math.h>
|
2011-12-16 18:37:05 +01:00
|
|
|
|
|
|
|
#include <set>
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
#include <deque>
|
|
|
|
|
|
|
|
#include "netbase.h"
|
|
|
|
#include "protocol.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2011-12-19 23:18:06 +01:00
|
|
|
#define TAU 86400.0
|
2011-12-20 05:20:50 +01:00
|
|
|
#define MIN_RETRY 1000
|
2011-12-19 23:18:06 +01:00
|
|
|
|
2011-12-16 18:37:05 +01:00
|
|
|
class CAddrInfo {
|
|
|
|
private:
|
2011-12-19 23:18:06 +01:00
|
|
|
CIPPort ip;
|
2011-12-16 18:37:05 +01:00
|
|
|
uint64_t services;
|
2011-12-20 08:35:22 +01:00
|
|
|
int64 lastTry;
|
|
|
|
int64 ourLastTry;
|
2011-12-19 23:18:06 +01:00
|
|
|
double reliability;
|
|
|
|
double timing;
|
2011-12-16 18:37:05 +01:00
|
|
|
double weight;
|
2011-12-19 23:18:06 +01:00
|
|
|
double count;
|
|
|
|
int total;
|
|
|
|
int success;
|
|
|
|
public:
|
|
|
|
bool IsGood() {
|
2011-12-20 05:20:50 +01:00
|
|
|
return (weight > 0 && reliability/weight > 0.8 && timing/weight < 86400) && ip.GetPort() == 8333;
|
2011-12-19 23:18:06 +01:00
|
|
|
}
|
|
|
|
bool IsTerrible() {
|
|
|
|
return (weight > 0.5 & reliability/weight < 0.2 && timing/weight < 86400 && count/weight > 2.0);
|
|
|
|
}
|
2011-12-19 23:45:18 +01:00
|
|
|
void Update(bool good);
|
2011-12-19 23:18:06 +01:00
|
|
|
|
|
|
|
friend class CAddrDb;
|
2011-12-20 08:35:22 +01:00
|
|
|
|
|
|
|
IMPLEMENT_SERIALIZE (
|
|
|
|
int version = 0;
|
|
|
|
READWRITE(version);
|
|
|
|
READWRITE(ip);
|
|
|
|
READWRITE(services);
|
|
|
|
READWRITE(lastTry);
|
|
|
|
READWRITE(ourLastTry);
|
|
|
|
READWRITE(reliability);
|
|
|
|
READWRITE(timing);
|
|
|
|
READWRITE(weight);
|
|
|
|
READWRITE(count);
|
|
|
|
READWRITE(total);
|
|
|
|
READWRITE(success);
|
|
|
|
)
|
2011-12-19 23:18:06 +01:00
|
|
|
};
|
2011-12-16 18:37:05 +01:00
|
|
|
|
2011-12-16 18:51:45 +01:00
|
|
|
// seen nodes
|
|
|
|
// / \
|
|
|
|
// (a) banned nodes tracked nodes
|
|
|
|
// / \
|
|
|
|
// tried nodes (b) unknown nodes
|
|
|
|
// / \
|
|
|
|
// (d) good nodes (c) non-good nodes
|
|
|
|
|
2011-12-16 18:37:05 +01:00
|
|
|
class CAddrDb {
|
|
|
|
private:
|
2011-12-20 08:35:22 +01:00
|
|
|
mutable CCriticalSection cs;
|
2011-12-16 18:37:05 +01:00
|
|
|
int nId; // number of address id's
|
2011-12-19 23:18:06 +01:00
|
|
|
std::map<int, CAddrInfo> idToInfo; // map address id to address info (b,c,d)
|
|
|
|
std::map<CIPPort, int> ipToId; // map ip to id (b,c,d)
|
|
|
|
std::deque<int> ourId; // sequence of tried nodes, in order we have tried connecting to them (c,d)
|
|
|
|
std::set<int> unkId; // set of nodes not yet tried (b)
|
|
|
|
std::set<int> goodId; // set of good nodes (d)
|
|
|
|
std::map<CIPPort, time_t> banned; // nodes that are banned, with their unban time (a)
|
2011-12-16 18:37:05 +01:00
|
|
|
|
2011-12-19 23:18:06 +01:00
|
|
|
protected:
|
|
|
|
void Add_(const CAddress &addr);
|
|
|
|
void Good_(const CIPPort &ip);
|
|
|
|
void Bad_(const CIPPort &ip, int ban);
|
|
|
|
void Skipped_(const CIPPort &ip);
|
2011-12-20 06:42:48 +01:00
|
|
|
bool Get_(CIPPort &ip, int& wait);
|
2011-12-19 23:18:06 +01:00
|
|
|
int Lookup_(const CIPPort &ip);
|
|
|
|
void GetIPs_(std::set<CIP>& ips, int max, bool fOnlyIPv4);
|
2011-12-16 18:37:05 +01:00
|
|
|
|
2011-12-19 23:18:06 +01:00
|
|
|
public:
|
2011-12-20 08:35:22 +01:00
|
|
|
|
|
|
|
IMPLEMENT_SERIALIZE (({
|
|
|
|
int nVersion = 0;
|
|
|
|
READWRITE(nVersion);
|
|
|
|
CRITICAL_BLOCK(cs) {
|
|
|
|
if (fWrite) {
|
|
|
|
CAddrDb *db = const_cast<CAddrDb*>(this);
|
|
|
|
int nOur = ourId.size();
|
|
|
|
int nUnk = unkId.size();
|
|
|
|
READWRITE(nOur);
|
|
|
|
READWRITE(nUnk);
|
|
|
|
for (std::deque<int>::const_iterator it = ourId.begin(); it != ourId.end(); it++) {
|
|
|
|
std::map<int, CAddrInfo>::iterator ci = db->idToInfo.find(*it);
|
|
|
|
READWRITE((*ci).second);
|
|
|
|
}
|
|
|
|
for (std::set<int>::const_iterator it = unkId.begin(); it != unkId.end(); it++) {
|
|
|
|
std::map<int, CAddrInfo>::iterator ci = db->idToInfo.find(*it);
|
|
|
|
READWRITE((*ci).second);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
CAddrDb *db = const_cast<CAddrDb*>(this);
|
|
|
|
db->nId = 0;
|
|
|
|
int nOur, nUnk;
|
|
|
|
READWRITE(nOur);
|
|
|
|
READWRITE(nUnk);
|
|
|
|
for (int i=0; i<nOur; i++) {
|
|
|
|
CAddrInfo info;
|
|
|
|
READWRITE(info);
|
|
|
|
int id = db->nId++;
|
|
|
|
db->idToInfo[id] = info;
|
|
|
|
db->ipToId[info.ip] = id;
|
|
|
|
db->ourId.push_back(id);
|
|
|
|
if (info.IsGood()) db->goodId.insert(id);
|
|
|
|
}
|
|
|
|
for (int i=0; i<nUnk; i++) {
|
|
|
|
CAddrInfo info;
|
|
|
|
READWRITE(info);
|
|
|
|
int id = db->nId++;
|
|
|
|
db->idToInfo[id] = info;
|
|
|
|
db->ipToId[info.ip] = id;
|
|
|
|
db->unkId.insert(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
READWRITE(banned);
|
|
|
|
}
|
|
|
|
});)
|
|
|
|
|
2011-12-20 05:20:50 +01:00
|
|
|
void Stats() {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
printf("**** %i good, %lu our, %i unk, %i banned; %i known ips\n", (int)goodId.size(), (unsigned long)ourId.size(), (int)unkId.size(), (int)banned.size(), (int)ipToId.size());
|
|
|
|
}
|
2011-12-19 23:18:06 +01:00
|
|
|
void Add(const CAddress &addr) {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
Add_(addr);
|
|
|
|
}
|
|
|
|
void Add(const std::vector<CAddress> &vAddr) {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
for (int i=0; i<vAddr.size(); i++)
|
|
|
|
Add_(vAddr[i]);
|
|
|
|
}
|
|
|
|
void Good(const CIPPort &addr) {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
Good_(addr);
|
|
|
|
}
|
|
|
|
void Skipped(const CIPPort &addr) {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
Skipped_(addr);
|
|
|
|
}
|
|
|
|
void Bad(const CIPPort &addr, int ban = 0) {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
Bad_(addr, ban);
|
|
|
|
}
|
2011-12-20 06:42:48 +01:00
|
|
|
bool Get(CIPPort &ip, int& wait) {
|
2011-12-19 23:18:06 +01:00
|
|
|
CRITICAL_BLOCK(cs)
|
2011-12-20 06:42:48 +01:00
|
|
|
return Get_(ip, wait);
|
2011-12-19 23:18:06 +01:00
|
|
|
}
|
|
|
|
void GetIPs(std::set<CIP>& ips, int max, bool fOnlyIPv4 = true) {
|
|
|
|
CRITICAL_BLOCK(cs)
|
|
|
|
GetIPs_(ips, max, fOnlyIPv4);
|
|
|
|
}
|
|
|
|
};
|