diff --git a/src/seeder/bitcoin.cpp b/src/seeder/bitcoin.cpp --- a/src/seeder/bitcoin.cpp +++ b/src/seeder/bitcoin.cpp @@ -10,12 +10,14 @@ #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL +static const uint32_t allones(-1); + class CNode { SOCKET sock; CDataStream vSend; CDataStream vRecv; - unsigned int nHeaderStart; - unsigned int nMessageStart; + uint32_t nHeaderStart; + uint32_t nMessageStart; int nVersion; std::string strSubVer; int nStartingHeight; @@ -27,7 +29,9 @@ int GetTimeout() { return you.IsTor() ? 120 : 30; } void BeginMessage(const char *pszCommand) { - if (nHeaderStart != -1) AbortMessage(); + if (nHeaderStart != allones) { + AbortMessage(); + } nHeaderStart = vSend.size(); vSend << CMessageHeader(pszCommand, 0); nMessageStart = vSend.size(); @@ -35,15 +39,19 @@ } void AbortMessage() { - if (nHeaderStart == -1) return; + if (nHeaderStart == allones) { + return; + } vSend.resize(nHeaderStart); - nHeaderStart = -1; - nMessageStart = -1; + nHeaderStart = allones; + nMessageStart = allones; } void EndMessage() { - if (nHeaderStart == -1) return; - unsigned int nSize = vSend.size() - nMessageStart; + if (nHeaderStart == allones) { + return; + } + uint32_t nSize = vSend.size() - nMessageStart; memcpy((char *)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); @@ -57,13 +65,17 @@ offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum)); } - nHeaderStart = -1; - nMessageStart = -1; + nHeaderStart = allones; + nMessageStart = allones; } void Send() { - if (sock == INVALID_SOCKET) return; - if (vSend.empty()) return; + if (sock == INVALID_SOCKET) { + return; + } + if (vSend.empty()) { + return; + } int nBytes = send(sock, &vSend[0], vSend.size(), 0); if (nBytes > 0) { vSend.erase(vSend.begin(), vSend.begin() + nBytes); @@ -162,12 +174,15 @@ } bool ProcessMessages() { - if (vRecv.empty()) return false; + if (vRecv.empty()) { + return false; + } + do { CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart)); - int nHeaderSize = GetSerializeSize( + uint32_t nHeaderSize = GetSerializeSize( CMessageHeader(), vRecv.GetType(), vRecv.GetVersion()); if (vRecv.end() - pstart < nHeaderSize) { if (vRecv.size() > nHeaderSize) { @@ -217,9 +232,9 @@ public: CNode(const CService &ip, std::vector *vAddrIn) - : vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), you(ip), - nHeaderStart(-1), nMessageStart(-1), vAddr(vAddrIn), ban(0), - doneAfter(0), nVersion(0) { + : vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), nHeaderStart(-1), + nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0), doneAfter(0), + you(ip) { if (time(nullptr) > 1329696000) { vSend.SetVersion(209); vRecv.SetVersion(209); diff --git a/src/seeder/db.h b/src/seeder/db.h --- a/src/seeder/db.h +++ b/src/seeder/db.h @@ -24,8 +24,9 @@ static inline std::string ToString(const CService &ip) { std::string str = ip.ToString(); - while (str.size() < 22) + while (str.size() < 22) { str += ' '; + } return str; } @@ -128,8 +129,11 @@ return false; } + int GetBanTime() const { - if (IsGood()) return 0; + if (IsGood()) { + return 0; + } if (clientVersion && clientVersion < 31900) { return 604800; } @@ -147,8 +151,11 @@ } return 0; } + int GetIgnoreTime() const { - if (IsGood()) return 0; + if (IsGood()) { + return 0; + } if (stat1M.reliability - stat1M.weight + 1.0 < 0.20 && stat1M.count > 2) { return 10 * 86400; @@ -183,25 +190,27 @@ READWRITE(lastTry); uint8_t tried = ourLastTry != 0; READWRITE(tried); - if (tried) { - READWRITE(ourLastTry); - READWRITE(ignoreTill); - READWRITE(stat2H); - READWRITE(stat8H); - READWRITE(stat1D); - READWRITE(stat1W); - if (version >= 1) { - READWRITE(stat1M); - } else if (!ser_action.ForRead()) { - *((CAddrStat *)(&stat1M)) = stat1W; - } - READWRITE(total); - READWRITE(success); - READWRITE(clientVersion); - if (version >= 2) READWRITE(clientSubVersion); - if (version >= 3) READWRITE(blocks); - if (version >= 4) READWRITE(ourLastSuccess); + if (!tried) { + return; + } + + READWRITE(ourLastTry); + READWRITE(ignoreTill); + READWRITE(stat2H); + READWRITE(stat8H); + READWRITE(stat1D); + READWRITE(stat1W); + if (version >= 1) { + READWRITE(stat1M); + } else if (!ser_action.ForRead()) { + *((CAddrStat *)(&stat1M)) = stat1W; } + READWRITE(total); + READWRITE(success); + READWRITE(clientVersion); + if (version >= 2) READWRITE(clientSubVersion); + if (version >= 3) READWRITE(blocks); + if (version >= 4) READWRITE(ourLastSuccess); } }; @@ -225,14 +234,15 @@ int64_t ourLastSuccess; }; -// seen nodes -// / \ -// (a) banned nodes available nodes-------------- -// / | \ -// tracked nodes (b) unknown nodes (e) active nodes -// / \ -// (d) good nodes (c) non-good nodes - +/** + * seen nodes + * / \ + * (a) banned nodes available nodes-------------- + * / | \ + * tracked nodes (b) unknown nodes (e) active nodes + * / \ + * (d) good nodes (c) non-good nodes + */ class CAddrDb { private: mutable CCriticalSection cs; @@ -269,7 +279,7 @@ // look up id of an IP int Lookup_(const CService &ip); // get a random set of IPs (shared lock only) - void GetIPs_(std::set &ips, uint64_t requestedFlags, int max, + void GetIPs_(std::set &ips, uint64_t requestedFlags, uint32_t max, const bool *nets); public: @@ -313,9 +323,8 @@ // CAddrInfo[n] // banned // acquires a shared lock (this does not suffice for read mode, but we - // assume that only happens at startup, single-threaded) - // this way, dumping does not interfere with GetIPs_, which is called from - // the DNS thread + // assume that only happens at startup, single-threaded) this way, dumping + // does not interfere with GetIPs_, which is called from the DNS thread template void Serialize(Stream &s) const { LOCK(cs); @@ -372,41 +381,50 @@ LOCK(cs); Add_(addr, fForce); } + void Add(const std::vector &vAddr, bool fForce = false) { LOCK(cs); for (size_t i = 0; i < vAddr.size(); i++) { Add_(vAddr[i], fForce); } } + void Good(const CService &addr, int clientVersion, std::string clientSubVersion, int blocks) { LOCK(cs); Good_(addr, clientVersion, clientSubVersion, blocks); } + void Skipped(const CService &addr) { LOCK(cs); Skipped_(addr); } + void Bad(const CService &addr, int ban = 0) { LOCK(cs); Bad_(addr, ban); } + bool Get(CServiceResult &ip, int &wait) { LOCK(cs); return Get_(ip, wait); } + void GetMany(std::vector &ips, int max, int &wait) { LOCK(cs); while (max > 0) { CServiceResult ip = {}; - if (!Get_(ip, wait)) return; + if (!Get_(ip, wait)) { + return; + } ips.push_back(ip); max--; } } + void ResultMany(const std::vector &ips) { LOCK(cs); - for (int i = 0; i < ips.size(); i++) { + for (size_t i = 0; i < ips.size(); i++) { if (ips[i].fGood) { Good_(ips[i].service, ips[i].nClientV, ips[i].strClientV, ips[i].nHeight); @@ -415,7 +433,8 @@ } } } - void GetIPs(std::set &ips, uint64_t requestedFlags, int max, + + void GetIPs(std::set &ips, uint64_t requestedFlags, uint32_t max, const bool *nets) { LOCK(cs); GetIPs_(ips, requestedFlags, max, nets); diff --git a/src/seeder/db.cpp b/src/seeder/db.cpp --- a/src/seeder/db.cpp +++ b/src/seeder/db.cpp @@ -36,14 +36,14 @@ bool CAddrDb::Get_(CServiceResult &ip, int &wait) { int64_t now = time(nullptr); - int cont = 0; - int tot = unkId.size() + ourId.size(); + size_t tot = unkId.size() + ourId.size(); if (tot == 0) { wait = 5; return false; } + do { - int rnd = rand() % tot; + size_t rnd = rand() % tot; int ret; if (rnd < unkId.size()) { std::set::iterator it = unkId.end(); @@ -52,10 +52,12 @@ unkId.erase(it); } else { ret = ourId.front(); - if (time(nullptr) - idToInfo[ret].ourLastTry < MIN_RETRY) + if (time(nullptr) - idToInfo[ret].ourLastTry < MIN_RETRY) { return false; + } ourId.pop_front(); } + if (idToInfo[ret].ignoreTill && idToInfo[ret].ignoreTill < now) { ourId.push_back(ret); idToInfo[ret].ourLastTry = now; @@ -65,6 +67,7 @@ break; } } while (1); + nDirty++; return true; } @@ -133,14 +136,17 @@ } void CAddrDb::Add_(const CAddress &addr, bool force) { - if (!force && !addr.IsRoutable()) return; + if (!force && !addr.IsRoutable()) { + return; + } CService ipp(addr); if (banned.count(ipp)) { time_t bantime = banned[ipp]; - if (force || (bantime < time(nullptr) && addr.nTime > bantime)) + if (force || (bantime < time(nullptr) && addr.nTime > bantime)) { banned.erase(ipp); - else + } else { return; + } } if (ipToId.count(ipp)) { CAddrInfo &ai = idToInfo[ipToId[ipp]]; @@ -154,6 +160,7 @@ } return; } + CAddrInfo ai; ai.ip = ipp; ai.services = addr.nServices; @@ -169,41 +176,54 @@ nDirty++; } -void CAddrDb::GetIPs_(std::set &ips, uint64_t requestedFlags, int max, - const bool *nets) { +void CAddrDb::GetIPs_(std::set &ips, uint64_t requestedFlags, + uint32_t max, const bool *nets) { if (goodId.size() == 0) { int id = -1; if (ourId.size() == 0) { - if (unkId.size() == 0) return; + if (unkId.size() == 0) { + return; + } id = *unkId.begin(); } else { id = *ourId.begin(); } + if (id >= 0 && (idToInfo[id].services & requestedFlags) == requestedFlags) { ips.insert(idToInfo[id].ip); } return; } + std::vector goodIdFiltered; - for (std::set::const_iterator it = goodId.begin(); it != goodId.end(); - it++) { - if ((idToInfo[*it].services & requestedFlags) == requestedFlags) - goodIdFiltered.push_back(*it); + for (auto &id : goodId) { + if ((idToInfo[id].services & requestedFlags) == requestedFlags) { + goodIdFiltered.push_back(id); + } } - if (!goodIdFiltered.size()) return; + if (!goodIdFiltered.size()) { + return; + } - if (max > goodIdFiltered.size() / 2) max = goodIdFiltered.size() / 2; - if (max < 1) max = 1; + if (max > goodIdFiltered.size() / 2) { + max = goodIdFiltered.size() / 2; + } + + if (max < 1) { + max = 1; + } std::set ids; while (ids.size() < max) { ids.insert(goodIdFiltered[rand() % goodIdFiltered.size()]); } - for (std::set::const_iterator it = ids.begin(); it != ids.end(); - it++) { - CService &ip = idToInfo[*it].ip; - if (nets[ip.GetNetwork()]) ips.insert(ip); + + for (auto &id : ids) { + CService &ip = idToInfo[id].ip; + if (nets[ip.GetNetwork()]) { + ips.insert(ip); + } } } diff --git a/src/seeder/dns.h b/src/seeder/dns.h --- a/src/seeder/dns.h +++ b/src/seeder/dns.h @@ -18,8 +18,8 @@ const char *host; const char *ns; const char *mbox; - int (*cb)(void *opt, char *requested_hostname, addr_t *addr, int max, - int ipv4, int ipv6); + uint32_t (*cb)(void *opt, char *requested_hostname, addr_t *addr, + uint32_t max, uint32_t ipv4, uint32_t ipv6); // stats uint64_t nRequests; } dns_opt_t; diff --git a/src/seeder/main.cpp b/src/seeder/main.cpp --- a/src/seeder/main.cpp +++ b/src/seeder/main.cpp @@ -33,9 +33,10 @@ std::set filter_whitelist; CDnsSeedOpts() - : nThreads(96), nDnsThreads(4), nPort(53), mbox(nullptr), ns(nullptr), - host(nullptr), tor(nullptr), fUseTestNet(false), fWipeBan(false), - fWipeIgnore(false), ipv4_proxy(nullptr), ipv6_proxy(nullptr) {} + : nThreads(96), nPort(53), nDnsThreads(4), fUseTestNet(false), + fWipeBan(false), fWipeIgnore(false), mbox(nullptr), ns(nullptr), + host(nullptr), tor(nullptr), ipv4_proxy(nullptr), + ipv6_proxy(nullptr) {} void ParseCommandLine(int argc, char **argv) { static const char *help = @@ -185,8 +186,9 @@ Sleep(wait); continue; } + std::vector addr; - for (int i = 0; i < ips.size(); i++) { + for (size_t i = 0; i < ips.size(); i++) { CServiceResult &res = ips[i]; res.nBanTime = 0; res.nClientV = 0; @@ -197,14 +199,16 @@ res.strClientV, res.nHeight, getaddr ? &addr : nullptr); } + db.ResultMany(ips); db.Add(addr); } while (1); return nullptr; } -extern "C" int GetIPList(void *thread, char *requestedHostname, addr_t *addr, - int max, int ipv4, int ipv6); +extern "C" uint32_t GetIPList(void *thread, char *requestedHostname, + addr_t *addr, uint32_t max, uint32_t ipv4, + uint32_t ipv6); class CDnsThread { public: @@ -283,8 +287,8 @@ void run() { dnsserver(&dns_opt); } }; -extern "C" int GetIPList(void *data, char *requestedHostname, addr_t *addr, - int max, int ipv4, int ipv6) { +extern "C" uint32_t GetIPList(void *data, char *requestedHostname, addr_t *addr, + uint32_t max, uint32_t ipv4, uint32_t ipv6) { CDnsThread *thread = (CDnsThread *)data; uint64_t requestedFlags = 0; @@ -296,28 +300,37 @@ if (*pEnd == '.' && pEnd <= requestedHostname + 17 && std::find(thread->filterWhitelist.begin(), thread->filterWhitelist.end(), - flags) != thread->filterWhitelist.end()) + flags) != thread->filterWhitelist.end()) { requestedFlags = flags; - else + } else { return 0; - } else if (strcasecmp(requestedHostname, thread->dns_opt.host)) + } + } else if (strcasecmp(requestedHostname, thread->dns_opt.host)) { return 0; + } thread->cacheHit(requestedFlags); auto &thisflag = thread->perflag[requestedFlags]; - unsigned int size = thisflag.cache.size(); - unsigned int maxmax = - (ipv4 ? thisflag.nIPv4 : 0) + (ipv6 ? thisflag.nIPv6 : 0); - if (max > size) max = size; - if (max > maxmax) max = maxmax; - int i = 0; + uint32_t size = thisflag.cache.size(); + uint32_t maxmax = (ipv4 ? thisflag.nIPv4 : 0) + (ipv6 ? thisflag.nIPv6 : 0); + if (max > size) { + max = size; + } + if (max > maxmax) { + max = maxmax; + } + uint32_t i = 0; while (i < max) { - int j = i + (rand() % (size - i)); + uint32_t j = i + (rand() % (size - i)); do { bool ok = (ipv4 && thisflag.cache[j].v == 4) || (ipv6 && thisflag.cache[j].v == 6); - if (ok) break; + if (ok) { + break; + } j++; - if (j == size) j = i; + if (j == size) { + j = i; + } } while (1); addr[i] = thisflag.cache[j]; thisflag.cache[j] = thisflag.cache[i]; diff --git a/src/seeder/protocol.cpp b/src/seeder/protocol.cpp --- a/src/seeder/protocol.cpp +++ b/src/seeder/protocol.cpp @@ -99,15 +99,18 @@ } CInv::CInv(const std::string &strType, const uint256 &hashIn) { - int i; + size_t i; for (i = 1; i < ARRAYLEN(ppszTypeName); i++) { if (strType == ppszTypeName[i]) { type = i; break; } } - if (i == ARRAYLEN(ppszTypeName)) + + if (i == ARRAYLEN(ppszTypeName)) { throw std::out_of_range("CInv::CInv(string, uint256) : unknown type"); + } + hash = hashIn; }