Merge branch '1.8.3-dev' into 1.8-maint
This commit is contained in:
commit
66eb58e86c
24
RELEASE_NOTES_1.8.3.md
Normal file
24
RELEASE_NOTES_1.8.3.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Dogecoin Core 1.8.3
|
||||
|
||||
Dogecoin Core 1.8.3 is a security release. It fixes issues in regards to an upcoming announcement of possible DoS vulnerabilities.
|
||||
See [the announcement on the bitcoin-dev mailing list](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-June/009135.html) for reference.
|
||||
It is strongly recommended to upgrade your installation in case you run a node open to inbound connections from the internet.
|
||||
If your installation is not open to incoming connections this update is not mandatory, but we still recommend keeping your client up to date.
|
||||
|
||||
## Dogecoin Core Release Notes
|
||||
|
||||
* Pull in patches from usptream to mitigate the risk of a DoS attack.
|
||||
* Update the DNS seeds for more reliable bootstrapping of the initial peer discovery.
|
||||
* Update the list of fixed nodes, in case all other means of peer discovery fail.
|
||||
|
||||
## Credits
|
||||
|
||||
Listed in strictly alphabetical order, using name listed in Github. This
|
||||
includes those whose contributions to Bitcoin Core have been merged
|
||||
into this Dogecoin Core release:
|
||||
|
||||
* P. Kaufmann
|
||||
* Max K.
|
||||
* Ross Nicoll
|
||||
* Wladimir J. van der Laan
|
||||
* Pieter Wuille
|
|
@ -2,10 +2,10 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
|||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 1)
|
||||
define(_CLIENT_VERSION_MINOR, 8)
|
||||
define(_CLIENT_VERSION_REVISION, 2)
|
||||
define(_CLIENT_VERSION_REVISION, 3)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2014)
|
||||
define(_COPYRIGHT_YEAR, 2015)
|
||||
AC_INIT([Dogecoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@dogecoin.com],[dogecoin])
|
||||
AC_CONFIG_AUX_DIR([src/build-aux])
|
||||
AC_CONFIG_MACRO_DIR([src/m4])
|
||||
|
|
|
@ -10,7 +10,7 @@ touch "$DATADIR/regtest/debug.log"
|
|||
tail -q -n 1 -F "$DATADIR/regtest/debug.log" | grep -m 1 -q "Done loading" &
|
||||
WAITER=$!
|
||||
PORT=`expr $BASHPID + 10000`
|
||||
"@abs_top_builddir@/src/bitcoind@EXEEXT@" -connect=0.0.0.0 -datadir="$DATADIR" -rpcuser=user -rpcpassword=pass -listen -keypool=3 -debug -debug=net -logtimestamps -port=$PORT -regtest -rpcport=`expr $PORT + 1` &
|
||||
"@abs_top_builddir@/src/bitcoind@EXEEXT@" -connect=0.0.0.0 -datadir="$DATADIR" -rpcuser=user -rpcpassword=pass -listen -keypool=3 -debug -debug=net -logtimestamps -port=$PORT -whitelist=127.0.0.1 -regtest -rpcport=`expr $PORT + 1` &
|
||||
BITCOIND=$!
|
||||
|
||||
#Install a watchdog.
|
||||
|
|
324
src/addrman.cpp
324
src/addrman.cpp
|
@ -9,34 +9,27 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const
|
||||
int CAddrInfo::GetTriedBucket(const uint256& nKey) const
|
||||
{
|
||||
CDataStream ss1(SER_GETHASH, 0);
|
||||
std::vector<unsigned char> vchKey = GetKey();
|
||||
ss1 << nKey << vchKey;
|
||||
uint64_t hash1 = Hash(ss1.begin(), ss1.end()).GetLow64();
|
||||
|
||||
CDataStream ss2(SER_GETHASH, 0);
|
||||
std::vector<unsigned char> vchGroupKey = GetGroup();
|
||||
ss2 << nKey << vchGroupKey << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP);
|
||||
uint64_t hash2 = Hash(ss2.begin(), ss2.end()).GetLow64();
|
||||
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetHash().GetLow64();
|
||||
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetHash().GetLow64();
|
||||
return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const
|
||||
int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src) const
|
||||
{
|
||||
CDataStream ss1(SER_GETHASH, 0);
|
||||
std::vector<unsigned char> vchGroupKey = GetGroup();
|
||||
std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
|
||||
ss1 << nKey << vchGroupKey << vchSourceGroupKey;
|
||||
uint64_t hash1 = Hash(ss1.begin(), ss1.end()).GetLow64();
|
||||
|
||||
CDataStream ss2(SER_GETHASH, 0);
|
||||
ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP);
|
||||
uint64_t hash2 = Hash(ss2.begin(), ss2.end()).GetLow64();
|
||||
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetHash().GetLow64();
|
||||
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetHash().GetLow64();
|
||||
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
int CAddrInfo::GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
|
||||
{
|
||||
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << (fNew ? 'N' : 'K') << nBucket << GetKey()).GetHash().GetLow64();
|
||||
return hash1 % ADDRMAN_BUCKET_SIZE;
|
||||
}
|
||||
|
||||
bool CAddrInfo::IsTerrible(int64_t nNow) const
|
||||
{
|
||||
if (nLastTry && nLastTry >= nNow-60) // never remove things tried the last minute
|
||||
|
@ -67,8 +60,6 @@ double CAddrInfo::GetChance(int64_t nNow) const
|
|||
if (nSinceLastSeen < 0) nSinceLastSeen = 0;
|
||||
if (nSinceLastTry < 0) nSinceLastTry = 0;
|
||||
|
||||
fChance *= 600.0 / (600.0 + nSinceLastSeen);
|
||||
|
||||
// deprioritize very recent attempts away
|
||||
if (nSinceLastTry < 60*10)
|
||||
fChance *= 0.01;
|
||||
|
@ -125,93 +116,44 @@ void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
|||
vRandom[nRndPos2] = nId1;
|
||||
}
|
||||
|
||||
int CAddrMan::SelectTried(int nKBucket)
|
||||
void CAddrMan::Delete(int nId)
|
||||
{
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
assert(mapInfo.count(nId) != 0);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
assert(!info.fInTried);
|
||||
assert(info.nRefCount == 0);
|
||||
|
||||
// random shuffle the first few elements (using the entire list)
|
||||
// find the least recently tried among them
|
||||
int64_t nOldest = -1;
|
||||
int nOldestPos = -1;
|
||||
for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++)
|
||||
{
|
||||
int nPos = GetRandInt(vTried.size() - i) + i;
|
||||
int nTemp = vTried[nPos];
|
||||
vTried[nPos] = vTried[i];
|
||||
vTried[i] = nTemp;
|
||||
assert(nOldest == -1 || mapInfo.count(nTemp) == 1);
|
||||
if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) {
|
||||
nOldest = nTemp;
|
||||
nOldestPos = nPos;
|
||||
}
|
||||
}
|
||||
|
||||
return nOldestPos;
|
||||
SwapRandom(info.nRandomPos, vRandom.size() - 1);
|
||||
vRandom.pop_back();
|
||||
mapAddr.erase(info);
|
||||
mapInfo.erase(nId);
|
||||
nNew--;
|
||||
}
|
||||
|
||||
int CAddrMan::ShrinkNew(int nUBucket)
|
||||
void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
|
||||
{
|
||||
assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size());
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// first look for deletable items
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
assert(mapInfo.count(*it));
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (info.IsTerrible())
|
||||
{
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
SwapRandom(info.nRandomPos, vRandom.size()-1);
|
||||
vRandom.pop_back();
|
||||
mapAddr.erase(info);
|
||||
mapInfo.erase(*it);
|
||||
nNew--;
|
||||
}
|
||||
vNew.erase(it);
|
||||
return 0;
|
||||
// if there is an entry in the specified bucket, delete it.
|
||||
if (vvNew[nUBucket][nUBucketPos] != -1) {
|
||||
int nIdDelete = vvNew[nUBucket][nUBucketPos];
|
||||
CAddrInfo& infoDelete = mapInfo[nIdDelete];
|
||||
assert(infoDelete.nRefCount > 0);
|
||||
infoDelete.nRefCount--;
|
||||
vvNew[nUBucket][nUBucketPos] = -1;
|
||||
if (infoDelete.nRefCount == 0) {
|
||||
Delete(nIdDelete);
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, select four randomly, and pick the oldest of those to replace
|
||||
int n[4] = {GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size())};
|
||||
int nI = 0;
|
||||
int nOldest = -1;
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3])
|
||||
{
|
||||
assert(nOldest == -1 || mapInfo.count(*it) == 1);
|
||||
if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime)
|
||||
nOldest = *it;
|
||||
}
|
||||
nI++;
|
||||
}
|
||||
assert(mapInfo.count(nOldest) == 1);
|
||||
CAddrInfo &info = mapInfo[nOldest];
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
SwapRandom(info.nRandomPos, vRandom.size()-1);
|
||||
vRandom.pop_back();
|
||||
mapAddr.erase(info);
|
||||
mapInfo.erase(nOldest);
|
||||
nNew--;
|
||||
}
|
||||
vNew.erase(nOldest);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
||||
{
|
||||
assert(vvNew[nOrigin].count(nId) == 1);
|
||||
|
||||
// remove the entry from all new buckets
|
||||
for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++)
|
||||
{
|
||||
if ((*it).erase(nId))
|
||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
||||
int pos = info.GetBucketPosition(nKey, true, bucket);
|
||||
if (vvNew[bucket][pos] == nId) {
|
||||
vvNew[bucket][pos] = -1;
|
||||
info.nRefCount--;
|
||||
}
|
||||
}
|
||||
nNew--;
|
||||
|
||||
|
@ -219,46 +161,36 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
|||
|
||||
// what tried bucket to move the entry to
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
|
||||
|
||||
// first check whether there is place to just add it
|
||||
if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
|
||||
{
|
||||
vTried.push_back(nId);
|
||||
nTried++;
|
||||
info.fInTried = true;
|
||||
return;
|
||||
// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
|
||||
if (vvTried[nKBucket][nKBucketPos] != -1) {
|
||||
// find an item to evict
|
||||
int nIdEvict = vvTried[nKBucket][nKBucketPos];
|
||||
assert(mapInfo.count(nIdEvict) == 1);
|
||||
CAddrInfo& infoOld = mapInfo[nIdEvict];
|
||||
|
||||
// Remove the to-be-evicted item from the tried set.
|
||||
infoOld.fInTried = false;
|
||||
vvTried[nKBucket][nKBucketPos] = -1;
|
||||
nTried--;
|
||||
|
||||
// find which new bucket it belongs to
|
||||
int nUBucket = infoOld.GetNewBucket(nKey);
|
||||
int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
|
||||
ClearNew(nUBucket, nUBucketPos);
|
||||
assert(vvNew[nUBucket][nUBucketPos] == -1);
|
||||
|
||||
// Enter it into the new set again.
|
||||
infoOld.nRefCount = 1;
|
||||
vvNew[nUBucket][nUBucketPos] = nIdEvict;
|
||||
nNew++;
|
||||
}
|
||||
assert(vvTried[nKBucket][nKBucketPos] == -1);
|
||||
|
||||
// otherwise, find an item to evict
|
||||
int nPos = SelectTried(nKBucket);
|
||||
|
||||
// find which new bucket it belongs to
|
||||
assert(mapInfo.count(vTried[nPos]) == 1);
|
||||
int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey);
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// remove the to-be-replaced tried entry from the tried set
|
||||
CAddrInfo& infoOld = mapInfo[vTried[nPos]];
|
||||
infoOld.fInTried = false;
|
||||
infoOld.nRefCount = 1;
|
||||
// do not update nTried, as we are going to move something else there immediately
|
||||
|
||||
// check whether there is place in that one,
|
||||
if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE)
|
||||
{
|
||||
// if so, move it back there
|
||||
vNew.insert(vTried[nPos]);
|
||||
} else {
|
||||
// otherwise, move it to the new bucket nId came from (there is certainly place there)
|
||||
vvNew[nOrigin].insert(vTried[nPos]);
|
||||
}
|
||||
nNew++;
|
||||
|
||||
vTried[nPos] = nId;
|
||||
// we just overwrote an entry in vTried; no need to update nTried
|
||||
vvTried[nKBucket][nKBucketPos] = nId;
|
||||
nTried++;
|
||||
info.fInTried = true;
|
||||
return;
|
||||
}
|
||||
|
||||
void CAddrMan::Good_(const CService &addr, int64_t nTime)
|
||||
|
@ -279,22 +211,21 @@ void CAddrMan::Good_(const CService &addr, int64_t nTime)
|
|||
// update info
|
||||
info.nLastSuccess = nTime;
|
||||
info.nLastTry = nTime;
|
||||
info.nTime = nTime;
|
||||
info.nAttempts = 0;
|
||||
// nTime is not updated here, to avoid leaking information about
|
||||
// currently-connected peers.
|
||||
|
||||
// if it is already in the tried set, don't do anything else
|
||||
if (info.fInTried)
|
||||
return;
|
||||
|
||||
// find a bucket it is in now
|
||||
int nRnd = GetRandInt(vvNew.size());
|
||||
int nRnd = GetRandInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||
int nUBucket = -1;
|
||||
for (unsigned int n = 0; n < vvNew.size(); n++)
|
||||
{
|
||||
int nB = (n+nRnd) % vvNew.size();
|
||||
std::set<int> &vNew = vvNew[nB];
|
||||
if (vNew.count(nId))
|
||||
{
|
||||
for (unsigned int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
|
||||
int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
int nBpos = info.GetBucketPosition(nKey, true, nB);
|
||||
if (vvNew[nB][nBpos] == nId) {
|
||||
nUBucket = nB;
|
||||
break;
|
||||
}
|
||||
|
@ -307,7 +238,7 @@ void CAddrMan::Good_(const CService &addr, int64_t nTime)
|
|||
LogPrint("addrman", "Moving %s to tried\n", addr.ToString());
|
||||
|
||||
// move nId to the tried tables
|
||||
MakeTried(info, nId, nUBucket);
|
||||
MakeTried(info, nId);
|
||||
}
|
||||
|
||||
bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty)
|
||||
|
@ -356,13 +287,25 @@ bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimeP
|
|||
}
|
||||
|
||||
int nUBucket = pinfo->GetNewBucket(nKey, source);
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
if (!vNew.count(nId))
|
||||
{
|
||||
pinfo->nRefCount++;
|
||||
if (vNew.size() == ADDRMAN_NEW_BUCKET_SIZE)
|
||||
ShrinkNew(nUBucket);
|
||||
vvNew[nUBucket].insert(nId);
|
||||
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
|
||||
if (vvNew[nUBucket][nUBucketPos] != nId) {
|
||||
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
|
||||
if (!fInsert) {
|
||||
CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
|
||||
if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
|
||||
// Overwrite the existing new table entry.
|
||||
fInsert = true;
|
||||
}
|
||||
}
|
||||
if (fInsert) {
|
||||
ClearNew(nUBucket, nUBucketPos);
|
||||
pinfo->nRefCount++;
|
||||
vvNew[nUBucket][nUBucketPos] = nId;
|
||||
} else {
|
||||
if (pinfo->nRefCount == 0) {
|
||||
Delete(nId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fNew;
|
||||
}
|
||||
|
@ -386,44 +329,39 @@ void CAddrMan::Attempt_(const CService &addr, int64_t nTime)
|
|||
info.nAttempts++;
|
||||
}
|
||||
|
||||
CAddress CAddrMan::Select_(int nUnkBias)
|
||||
CAddress CAddrMan::Select_()
|
||||
{
|
||||
if (size() == 0)
|
||||
return CAddress();
|
||||
|
||||
double nCorTried = sqrt(nTried) * (100.0 - nUnkBias);
|
||||
double nCorNew = sqrt(nNew) * nUnkBias;
|
||||
if ((nCorTried + nCorNew)*GetRandInt(1<<30)/(1<<30) < nCorTried)
|
||||
{
|
||||
// Use a 50% chance for choosing between tried and new table entries.
|
||||
if (nTried > 0 && (nNew == 0 || GetRandInt(2) == 0)) {
|
||||
// use a tried node
|
||||
double fChanceFactor = 1.0;
|
||||
while(1)
|
||||
{
|
||||
int nKBucket = GetRandInt(vvTried.size());
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
if (vTried.size() == 0) continue;
|
||||
int nPos = GetRandInt(vTried.size());
|
||||
assert(mapInfo.count(vTried[nPos]) == 1);
|
||||
CAddrInfo &info = mapInfo[vTried[nPos]];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
while (1) {
|
||||
int nKBucket = GetRandInt(ADDRMAN_TRIED_BUCKET_COUNT);
|
||||
int nKBucketPos = GetRandInt(ADDRMAN_BUCKET_SIZE);
|
||||
if (vvTried[nKBucket][nKBucketPos] == -1)
|
||||
continue;
|
||||
int nId = vvTried[nKBucket][nKBucketPos];
|
||||
assert(mapInfo.count(nId) == 1);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
if (GetRandInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
} else {
|
||||
// use a new node
|
||||
double fChanceFactor = 1.0;
|
||||
while(1)
|
||||
{
|
||||
int nUBucket = GetRandInt(vvNew.size());
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
if (vNew.size() == 0) continue;
|
||||
int nPos = GetRandInt(vNew.size());
|
||||
std::set<int>::iterator it = vNew.begin();
|
||||
while (nPos--)
|
||||
it++;
|
||||
assert(mapInfo.count(*it) == 1);
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
while (1) {
|
||||
int nUBucket = GetRandInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||
int nUBucketPos = GetRandInt(ADDRMAN_BUCKET_SIZE);
|
||||
if (vvNew[nUBucket][nUBucketPos] == -1)
|
||||
continue;
|
||||
int nId = vvNew[nUBucket][nUBucketPos];
|
||||
assert(mapInfo.count(nId) == 1);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
if (GetRandInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
|
@ -462,29 +400,37 @@ int CAddrMan::Check_()
|
|||
if (setTried.size() != nTried) return -9;
|
||||
if (mapNew.size() != nNew) return -10;
|
||||
|
||||
for (int n=0; n<vvTried.size(); n++)
|
||||
{
|
||||
std::vector<int> &vTried = vvTried[n];
|
||||
for (std::vector<int>::iterator it = vTried.begin(); it != vTried.end(); it++)
|
||||
{
|
||||
if (!setTried.count(*it)) return -11;
|
||||
setTried.erase(*it);
|
||||
for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) {
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvTried[n][i] != -1) {
|
||||
if (!setTried.count(vvTried[n][i]))
|
||||
return -11;
|
||||
if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey) != n)
|
||||
return -17;
|
||||
if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) != i)
|
||||
return -18;
|
||||
setTried.erase(vvTried[n][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int n=0; n<vvNew.size(); n++)
|
||||
{
|
||||
std::set<int> &vNew = vvNew[n];
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
if (!mapNew.count(*it)) return -12;
|
||||
if (--mapNew[*it] == 0)
|
||||
mapNew.erase(*it);
|
||||
for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvNew[n][i] != -1) {
|
||||
if (!mapNew.count(vvNew[n][i]))
|
||||
return -12;
|
||||
if (mapInfo[vvNew[n][i]].GetBucketPosition(nKey, true, n) != i)
|
||||
return -19;
|
||||
if (--mapNew[vvNew[n][i]] == 0)
|
||||
mapNew.erase(vvNew[n][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setTried.size()) return -13;
|
||||
if (mapNew.size()) return -15;
|
||||
if (nKey.IsNull())
|
||||
return -16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
444
src/addrman.h
444
src/addrman.h
|
@ -8,6 +8,7 @@
|
|||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "sync.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <map>
|
||||
|
@ -75,17 +76,20 @@ public:
|
|||
}
|
||||
|
||||
// Calculate in which "tried" bucket this entry belongs
|
||||
int GetTriedBucket(const std::vector<unsigned char> &nKey) const;
|
||||
int GetTriedBucket(const uint256 &nKey) const;
|
||||
|
||||
// Calculate in which "new" bucket this entry belongs, given a certain source
|
||||
int GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const;
|
||||
int GetNewBucket(const uint256 &nKey, const CNetAddr& src) const;
|
||||
|
||||
// Calculate in which "new" bucket this entry belongs, using its default source
|
||||
int GetNewBucket(const std::vector<unsigned char> &nKey) const
|
||||
int GetNewBucket(const uint256 &nKey) const
|
||||
{
|
||||
return GetNewBucket(nKey, source);
|
||||
}
|
||||
|
||||
//! Calculate in which position of a bucket to store this entry.
|
||||
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
|
||||
|
||||
// Determine whether the statistics about this entry are bad enough so that it can just be deleted
|
||||
bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
|
||||
|
||||
|
@ -94,55 +98,49 @@ public:
|
|||
|
||||
};
|
||||
|
||||
// Stochastic address manager
|
||||
//
|
||||
// Design goals:
|
||||
// * Only keep a limited number of addresses around, so that addr.dat and memory requirements do not grow without bound.
|
||||
// * Keep the address tables in-memory, and asynchronously dump the entire to able in addr.dat.
|
||||
// * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
|
||||
//
|
||||
// To that end:
|
||||
// * Addresses are organized into buckets.
|
||||
// * Address that have not yet been tried go into 256 "new" buckets.
|
||||
// * Based on the address range (/16 for IPv4) of source of the information, 32 buckets are selected at random
|
||||
// * The actual bucket is chosen from one of these, based on the range the address itself is located.
|
||||
// * One single address can occur in up to 4 different buckets, to increase selection chances for addresses that
|
||||
// are seen frequently. The chance for increasing this multiplicity decreases exponentially.
|
||||
// * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
|
||||
// ones) is removed from it first.
|
||||
// * Addresses of nodes that are known to be accessible go into 64 "tried" buckets.
|
||||
// * Each address range selects at random 4 of these buckets.
|
||||
// * The actual bucket is chosen from one of these, based on the full address.
|
||||
// * When adding a new good address to a full bucket, a randomly chosen entry (with a bias favoring less recently
|
||||
// tried ones) is evicted from it, back to the "new" buckets.
|
||||
// * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not
|
||||
// be observable by adversaries.
|
||||
// * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive)
|
||||
// consistency checks for the entire data structure.
|
||||
/** Stochastic address manager
|
||||
*
|
||||
* Design goals:
|
||||
* * Keep the address tables in-memory, and asynchronously dump the entire to able in peers.dat.
|
||||
* * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
|
||||
*
|
||||
* To that end:
|
||||
* * Addresses are organized into buckets.
|
||||
* * Address that have not yet been tried go into 1024 "new" buckets.
|
||||
* * Based on the address range (/16 for IPv4) of source of the information, 64 buckets are selected at random
|
||||
* * The actual bucket is chosen from one of these, based on the range the address itself is located.
|
||||
* * One single address can occur in up to 8 different buckets, to increase selection chances for addresses that
|
||||
* are seen frequently. The chance for increasing this multiplicity decreases exponentially.
|
||||
* * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
|
||||
* ones) is removed from it first.
|
||||
* * Addresses of nodes that are known to be accessible go into 256 "tried" buckets.
|
||||
* * Each address range selects at random 8 of these buckets.
|
||||
* * The actual bucket is chosen from one of these, based on the full address.
|
||||
* * When adding a new good address to a full bucket, a randomly chosen entry (with a bias favoring less recently
|
||||
* tried ones) is evicted from it, back to the "new" buckets.
|
||||
* * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not
|
||||
* be observable by adversaries.
|
||||
* * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive)
|
||||
* consistency checks for the entire data structure.
|
||||
*/
|
||||
|
||||
// total number of buckets for tried addresses
|
||||
#define ADDRMAN_TRIED_BUCKET_COUNT 64
|
||||
|
||||
// maximum allowed number of entries in buckets for tried addresses
|
||||
#define ADDRMAN_TRIED_BUCKET_SIZE 64
|
||||
#define ADDRMAN_TRIED_BUCKET_COUNT 256
|
||||
|
||||
// total number of buckets for new addresses
|
||||
#define ADDRMAN_NEW_BUCKET_COUNT 256
|
||||
#define ADDRMAN_NEW_BUCKET_COUNT 1024
|
||||
|
||||
// maximum allowed number of entries in buckets for new addresses
|
||||
#define ADDRMAN_NEW_BUCKET_SIZE 64
|
||||
// maximum allowed number of entries in buckets for new and tried addresses
|
||||
#define ADDRMAN_BUCKET_SIZE 64
|
||||
|
||||
// over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread
|
||||
#define ADDRMAN_TRIED_BUCKETS_PER_GROUP 4
|
||||
#define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8
|
||||
|
||||
// over how many buckets entries with new addresses originating from a single group are spread
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 32
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64
|
||||
|
||||
// in how many buckets for entries with new addresses a single address may occur
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 4
|
||||
|
||||
// how many entries in a bucket with tried addresses are inspected, when selecting one to replace
|
||||
#define ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT 4
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8
|
||||
|
||||
// how old addresses can maximally be
|
||||
#define ADDRMAN_HORIZON_DAYS 30
|
||||
|
@ -170,7 +168,7 @@ private:
|
|||
mutable CCriticalSection cs;
|
||||
|
||||
// secret key to randomize bucket select with
|
||||
std::vector<unsigned char> nKey;
|
||||
uint256 nKey;
|
||||
|
||||
// last used nId
|
||||
int nIdCount;
|
||||
|
@ -188,13 +186,13 @@ private:
|
|||
int nTried;
|
||||
|
||||
// list of "tried" buckets
|
||||
std::vector<std::vector<int> > vvTried;
|
||||
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
|
||||
|
||||
// number of (unique) "new" entries
|
||||
int nNew;
|
||||
|
||||
// list of "new" buckets
|
||||
std::vector<std::set<int> > vvNew;
|
||||
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -208,17 +206,14 @@ protected:
|
|||
// Swap two elements in vRandom.
|
||||
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
|
||||
|
||||
// Return position in given bucket to replace.
|
||||
int SelectTried(int nKBucket);
|
||||
|
||||
// Remove an element from a "new" bucket.
|
||||
// This is the only place where actual deletes occur.
|
||||
// They are never deleted while in the "tried" table, only possibly evicted back to the "new" table.
|
||||
int ShrinkNew(int nUBucket);
|
||||
|
||||
// Move an entry from the "new" table(s) to the "tried" table
|
||||
// @pre vvUnkown[nOrigin].count(nId) != 0
|
||||
void MakeTried(CAddrInfo& info, int nId, int nOrigin);
|
||||
void MakeTried(CAddrInfo& info, int nId);
|
||||
|
||||
// Delete an entry. It must not be in tried, and have refcount 0.
|
||||
void Delete(int nId);
|
||||
|
||||
// Clear a position in a "new" table. This is the only place where entries are actually deleted.
|
||||
void ClearNew(int nUBucket, int nUBucketPos);
|
||||
|
||||
// Mark an entry "good", possibly moving it from "new" to "tried".
|
||||
void Good_(const CService &addr, int64_t nTime);
|
||||
|
@ -230,8 +225,7 @@ protected:
|
|||
void Attempt_(const CService &addr, int64_t nTime);
|
||||
|
||||
// Select an address to connect to.
|
||||
// nUnkBias determines how much to favor new addresses over tried ones (min=0, max=100)
|
||||
CAddress Select_(int nUnkBias);
|
||||
CAddress Select_();
|
||||
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
// Perform consistency check. Returns an error code or zero.
|
||||
|
@ -245,153 +239,220 @@ protected:
|
|||
void Connected_(const CService &addr, int64_t nTime);
|
||||
|
||||
public:
|
||||
/**
|
||||
* serialized format:
|
||||
* * version byte (currently 1)
|
||||
* * 0x20 + nKey (serialized as if it were a vector, for backward compatibility)
|
||||
* * nNew
|
||||
* * nTried
|
||||
* * number of "new" buckets XOR 2**30
|
||||
* * all nNew addrinfos in vvNew
|
||||
* * all nTried addrinfos in vvTried
|
||||
* * for each bucket:
|
||||
* * number of elements
|
||||
* * for each element: index
|
||||
*
|
||||
* 2**30 is xorred with the number of buckets to make addrman deserializer v0 detect it
|
||||
* as incompatible. This is necessary because it did not check the version number on
|
||||
* deserialization.
|
||||
*
|
||||
* Notice that vvTried, mapAddr and vVector are never encoded explicitly;
|
||||
* they are instead reconstructed from the other information.
|
||||
*
|
||||
* vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
|
||||
* otherwise it is reconstructed as well.
|
||||
*
|
||||
* This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
|
||||
* changes to the ADDRMAN_ parameters without breaking the on-disk structure.
|
||||
*
|
||||
* We don't use ADD_SERIALIZE_METHODS since the serialization and deserialization code has
|
||||
* very little in common.
|
||||
*/
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s, int nType, int nVersionDummy) const
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(({
|
||||
// serialized format:
|
||||
// * version byte (currently 0)
|
||||
// * nKey
|
||||
// * nNew
|
||||
// * nTried
|
||||
// * number of "new" buckets
|
||||
// * all nNew addrinfos in vvNew
|
||||
// * all nTried addrinfos in vvTried
|
||||
// * for each bucket:
|
||||
// * number of elements
|
||||
// * for each element: index
|
||||
//
|
||||
// Notice that vvTried, mapAddr and vVector are never encoded explicitly;
|
||||
// they are instead reconstructed from the other information.
|
||||
//
|
||||
// vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
|
||||
// otherwise it is reconstructed as well.
|
||||
//
|
||||
// This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
|
||||
// changes to the ADDRMAN_ parameters without breaking the on-disk structure.
|
||||
{
|
||||
LOCK(cs);
|
||||
unsigned char nVersion = 0;
|
||||
READWRITE(nVersion);
|
||||
READWRITE(nKey);
|
||||
READWRITE(nNew);
|
||||
READWRITE(nTried);
|
||||
unsigned char nVersion = 1;
|
||||
s << nVersion;
|
||||
s << ((unsigned char)32);
|
||||
s << nKey;
|
||||
s << nNew;
|
||||
s << nTried;
|
||||
|
||||
CAddrMan *am = const_cast<CAddrMan*>(this);
|
||||
if (fWrite)
|
||||
{
|
||||
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
|
||||
READWRITE(nUBuckets);
|
||||
std::map<int, int> mapUnkIds;
|
||||
int nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
|
||||
{
|
||||
if (nIds == nNew) break; // this means nNew was wrong, oh ow
|
||||
mapUnkIds[(*it).first] = nIds;
|
||||
CAddrInfo &info = (*it).second;
|
||||
if (info.nRefCount)
|
||||
{
|
||||
READWRITE(info);
|
||||
nIds++;
|
||||
}
|
||||
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
|
||||
s << nUBuckets;
|
||||
std::map<int, int> mapUnkIds;
|
||||
int nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
|
||||
mapUnkIds[(*it).first] = nIds;
|
||||
const CAddrInfo &info = (*it).second;
|
||||
if (info.nRefCount) {
|
||||
assert(nIds != nNew); // this means nNew was wrong, oh ow
|
||||
s << info;
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
|
||||
const CAddrInfo &info = (*it).second;
|
||||
if (info.fInTried) {
|
||||
assert(nIds != nTried); // this means nTried was wrong, oh ow
|
||||
s << info;
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
||||
int nSize = 0;
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvNew[bucket][i] != -1)
|
||||
nSize++;
|
||||
}
|
||||
s << nSize;
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvNew[bucket][i] != -1) {
|
||||
int nIndex = mapUnkIds[vvNew[bucket][i]];
|
||||
s << nIndex;
|
||||
}
|
||||
nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
|
||||
{
|
||||
if (nIds == nTried) break; // this means nTried was wrong, oh ow
|
||||
CAddrInfo &info = (*it).second;
|
||||
if (info.fInTried)
|
||||
{
|
||||
READWRITE(info);
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
for (std::vector<std::set<int> >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++)
|
||||
{
|
||||
const std::set<int> &vNew = (*it);
|
||||
int nSize = vNew.size();
|
||||
READWRITE(nSize);
|
||||
for (std::set<int>::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
|
||||
{
|
||||
int nIndex = mapUnkIds[*it2];
|
||||
READWRITE(nIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType, int nVersionDummy)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
Clear();
|
||||
|
||||
unsigned char nVersion;
|
||||
s >> nVersion;
|
||||
unsigned char nKeySize;
|
||||
s >> nKeySize;
|
||||
if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
|
||||
s >> nKey;
|
||||
s >> nNew;
|
||||
s >> nTried;
|
||||
int nUBuckets = 0;
|
||||
s >> nUBuckets;
|
||||
if (nVersion != 0) {
|
||||
nUBuckets ^= (1 << 30);
|
||||
}
|
||||
|
||||
// Deserialize entries from the new table.
|
||||
for (int n = 0; n < nNew; n++) {
|
||||
CAddrInfo &info = mapInfo[n];
|
||||
s >> info;
|
||||
mapAddr[info] = n;
|
||||
info.nRandomPos = vRandom.size();
|
||||
vRandom.push_back(n);
|
||||
if (nVersion != 1 || nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) {
|
||||
// In case the new table data cannot be used (nVersion unknown, or bucket count wrong),
|
||||
// immediately try to give them a reference based on their primary source address.
|
||||
int nUBucket = info.GetNewBucket(nKey);
|
||||
int nUBucketPos = info.GetBucketPosition(nKey, true, nUBucket);
|
||||
if (vvNew[nUBucket][nUBucketPos] == -1) {
|
||||
vvNew[nUBucket][nUBucketPos] = n;
|
||||
info.nRefCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
nIdCount = nNew;
|
||||
|
||||
// Deserialize entries from the tried table.
|
||||
int nLost = 0;
|
||||
for (int n = 0; n < nTried; n++) {
|
||||
CAddrInfo info;
|
||||
s >> info;
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
|
||||
if (vvTried[nKBucket][nKBucketPos] == -1) {
|
||||
info.nRandomPos = vRandom.size();
|
||||
info.fInTried = true;
|
||||
vRandom.push_back(nIdCount);
|
||||
mapInfo[nIdCount] = info;
|
||||
mapAddr[info] = nIdCount;
|
||||
vvTried[nKBucket][nKBucketPos] = nIdCount;
|
||||
nIdCount++;
|
||||
} else {
|
||||
int nUBuckets = 0;
|
||||
READWRITE(nUBuckets);
|
||||
am->nIdCount = 0;
|
||||
am->mapInfo.clear();
|
||||
am->mapAddr.clear();
|
||||
am->vRandom.clear();
|
||||
am->vvTried = std::vector<std::vector<int> >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0));
|
||||
am->vvNew = std::vector<std::set<int> >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>());
|
||||
for (int n = 0; n < am->nNew; n++)
|
||||
{
|
||||
CAddrInfo &info = am->mapInfo[n];
|
||||
READWRITE(info);
|
||||
am->mapAddr[info] = n;
|
||||
info.nRandomPos = vRandom.size();
|
||||
am->vRandom.push_back(n);
|
||||
if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
|
||||
{
|
||||
am->vvNew[info.GetNewBucket(am->nKey)].insert(n);
|
||||
nLost++;
|
||||
}
|
||||
}
|
||||
nTried -= nLost;
|
||||
|
||||
// Deserialize positions in the new table (if possible).
|
||||
for (int bucket = 0; bucket < nUBuckets; bucket++) {
|
||||
int nSize = 0;
|
||||
s >> nSize;
|
||||
for (int n = 0; n < nSize; n++) {
|
||||
int nIndex = 0;
|
||||
s >> nIndex;
|
||||
if (nIndex >= 0 && nIndex < nNew) {
|
||||
CAddrInfo &info = mapInfo[nIndex];
|
||||
int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
|
||||
if (nVersion == 1 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) {
|
||||
info.nRefCount++;
|
||||
}
|
||||
}
|
||||
am->nIdCount = am->nNew;
|
||||
int nLost = 0;
|
||||
for (int n = 0; n < am->nTried; n++)
|
||||
{
|
||||
CAddrInfo info;
|
||||
READWRITE(info);
|
||||
std::vector<int> &vTried = am->vvTried[info.GetTriedBucket(am->nKey)];
|
||||
if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
|
||||
{
|
||||
info.nRandomPos = vRandom.size();
|
||||
info.fInTried = true;
|
||||
am->vRandom.push_back(am->nIdCount);
|
||||
am->mapInfo[am->nIdCount] = info;
|
||||
am->mapAddr[info] = am->nIdCount;
|
||||
vTried.push_back(am->nIdCount);
|
||||
am->nIdCount++;
|
||||
} else {
|
||||
nLost++;
|
||||
}
|
||||
}
|
||||
am->nTried -= nLost;
|
||||
for (int b = 0; b < nUBuckets; b++)
|
||||
{
|
||||
std::set<int> &vNew = am->vvNew[b];
|
||||
int nSize = 0;
|
||||
READWRITE(nSize);
|
||||
for (int n = 0; n < nSize; n++)
|
||||
{
|
||||
int nIndex = 0;
|
||||
READWRITE(nIndex);
|
||||
CAddrInfo &info = am->mapInfo[nIndex];
|
||||
if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
|
||||
{
|
||||
info.nRefCount++;
|
||||
vNew.insert(nIndex);
|
||||
}
|
||||
vvNew[bucket][nUBucketPos] = nIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});)
|
||||
|
||||
CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>())
|
||||
// Prune new entries with refcount 0 (as a result of collisions).
|
||||
int nLostUnk = 0;
|
||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
|
||||
if (it->second.fInTried == false && it->second.nRefCount == 0) {
|
||||
std::map<int, CAddrInfo>::const_iterator itCopy = it++;
|
||||
Delete(itCopy->first);
|
||||
nLostUnk++;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (nLost + nLostUnk > 0) {
|
||||
LogPrint("addrman", "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
|
||||
}
|
||||
|
||||
Check();
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const
|
||||
{
|
||||
nKey.resize(32);
|
||||
RAND_bytes(&nKey[0], 32);
|
||||
return (CSizeComputer(nType, nVersion) << *this).size();
|
||||
}
|
||||
|
||||
nIdCount = 0;
|
||||
nTried = 0;
|
||||
nNew = 0;
|
||||
void Clear()
|
||||
{
|
||||
std::vector<int>().swap(vRandom);
|
||||
RAND_bytes((unsigned char *)&nKey, 32);
|
||||
for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
||||
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
|
||||
vvNew[bucket][entry] = -1;
|
||||
}
|
||||
}
|
||||
for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) {
|
||||
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
|
||||
vvTried[bucket][entry] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
nIdCount = 0;
|
||||
nTried = 0;
|
||||
nNew = 0;
|
||||
}
|
||||
|
||||
CAddrMan()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
~CAddrMan()
|
||||
{
|
||||
nKey = uint256(0);
|
||||
}
|
||||
|
||||
// Return the number of (unique) addresses in all tables.
|
||||
int size()
|
||||
int size()
|
||||
{
|
||||
return vRandom.size();
|
||||
}
|
||||
|
@ -462,15 +523,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Choose an address to connect to.
|
||||
// nUnkBias determines how much "new" entries are favored over "tried" ones (0-100).
|
||||
CAddress Select(int nUnkBias = 50)
|
||||
/**
|
||||
* Choose an address to connect to.
|
||||
*/
|
||||
CAddress Select()
|
||||
{
|
||||
CAddress addrRet;
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
addrRet = Select_(nUnkBias);
|
||||
addrRet = Select_();
|
||||
Check();
|
||||
}
|
||||
return addrRet;
|
||||
|
|
|
@ -22,81 +22,62 @@ using namespace boost::assign;
|
|||
|
||||
unsigned int pnSeed[] =
|
||||
{
|
||||
0xdc7fa218, 0xb4b68d18, 0xd286166c, 0xb0bbb052, 0x5d9fe2bc, 0x0256c0ad, 0x4297d23e, 0x2cf5226c,
|
||||
0xa80dfb94, 0xf1a134d0, 0x4215042e, 0x7c51486d, 0x3a51486d, 0xd5c63832, 0xde5b7e02, 0xdb176018,
|
||||
0x332745ad, 0x7172c7c6, 0xfb90b742, 0x134dd9a2, 0x25e238ae, 0xc332ed40, 0x24a0a4c6, 0xcd5e0905,
|
||||
0xcaca87dc, 0xe28ac836, 0xc79c2942, 0x672baa6b, 0xa2012363, 0xf848f160, 0x34747b6d, 0xe6f7f1c0,
|
||||
0xbbc51955, 0x4e106d5b, 0x69e47046, 0x4ca0d54a, 0x6d0a65c6, 0x441d9c32, 0x436d5d81, 0xbdfffbce,
|
||||
0x1cd2f2a2, 0x112daa6b, 0x30b85f47, 0x02100ab9, 0x2e044bad, 0x2071ff45, 0x5f98b54b, 0x55a40905,
|
||||
0x651aaa6b, 0xe99ef2c5, 0x17c35ad0, 0x8db55d41, 0x587921cb, 0x3865ea2e, 0xba0d63c0, 0x8eb88b52,
|
||||
0x7a80a7c7, 0x4d5c5747, 0x3fd4f3a2, 0xf825be43, 0x161eaa6b, 0x43eda52e, 0x03b422b0, 0x5c0e63c0,
|
||||
0x6dfc47d4, 0x1a017ebc, 0xfb65c7c6, 0x535809b0, 0x8b58f181, 0x2454ed5e, 0x68220254, 0x7aaca143,
|
||||
0x91c10a55, 0x8bd74ece, 0xd67ef118, 0x0a15aa46, 0xa0c1b1ad, 0x4052d74a, 0xede8494b, 0xd5c49452,
|
||||
0x8fc97e18, 0x78c01c54, 0x2fbcf1c0, 0x335a046c, 0x3dc8834b, 0x6c550025, 0x278ab5d1, 0xc4422e4e,
|
||||
0x45e2073a, 0xa83fbd41, 0x738d1581, 0x9a3c0cc3, 0xf48d5436, 0x5ba835c6, 0xc63aaa6b, 0xd33328bc,
|
||||
0x9f703ab0, 0xee45ba36, 0x78417244, 0xf9e6e460, 0x288eb06c, 0x22a3e417, 0xdade69c6, 0x8b7bc447,
|
||||
0x7975c244, 0x51ef4cb7, 0x48ecffad, 0x32bf0918, 0xa98baa51, 0xedf5fa60, 0xe0aca658, 0x68fca0d9,
|
||||
0xe762c7c6, 0x1d2bc24e, 0x612d454b, 0x759fd295, 0xc218ef17, 0xb5c0b162, 0x5aaed56c, 0x1b52dc62,
|
||||
0x416c2d05, 0x42fbbfc3, 0xdc63134c, 0xc1b9e2bc, 0x0bd7f74d, 0x5eb9e2bc, 0xaf05a843, 0xafdf2e32,
|
||||
0x7d35bdd5, 0x8feeaa6b, 0x3e9e7d18, 0x47d1079d, 0x4d1d6a57, 0xc6cbffad, 0x0e80a7c7, 0x8dd0e8d8,
|
||||
0x334a066b, 0x31fae3bc, 0x0669e53a, 0x632c784c, 0x30381cb9, 0xaea5d118, 0xb7ee9ade, 0x4c37175e,
|
||||
0x9885f3a2, 0xbde5f6d8, 0xae62f3a2, 0xe276692e, 0xba5d1218, 0x511d5618, 0x7e81d78f, 0x14eb4c90,
|
||||
0x44e5c780, 0xe2708abc, 0xe261d3c6, 0x7aca584a, 0x8c037786, 0x7e3baa6b, 0xb912d8a2, 0x170763c0,
|
||||
0xbed1d23e, 0xdce46ccf, 0x5cdb1748, 0xc215f5ac, 0x99f7cabc, 0x4d658248, 0x3798bacd, 0x2dbb8932,
|
||||
0xe93faa6b, 0x639f534b, 0x43f6754c, 0x0440bd44, 0x4919aa6b, 0x30644aad, 0xc96e9c4e, 0x421daa6b,
|
||||
0x90760248, 0x096a1bc6, 0xba4b40ad, 0x3574fa5b, 0x20fe0732, 0x41535143, 0xdf843944, 0x103b8dd1,
|
||||
0xde76a032, 0xf405e447, 0xcc86bb25, 0xb3b22e6c, 0x12c35ad0, 0xa330aa6b, 0x14e69544, 0x177becd1,
|
||||
0xf32e484b, 0x15b1ce6d, 0x0d2c7662, 0x862d6441, 0xa2c39805, 0xc7eeaa6b, 0xf38f494c, 0x16d5b947,
|
||||
0x9fb8e2bc, 0xe13e175e, 0x656c39ad, 0x7a384946, 0x10460905, 0x9cf870d1, 0xb375c60e, 0x481cba6a,
|
||||
0x87ed6cd8, 0x2d7b67ae, 0x01540f48, 0x84028fc6, 0xdd85c144, 0x8f53ee54, 0x1a9e4fad, 0x84acc548,
|
||||
0x52d51248, 0xac47ab43, 0xf16ab743, 0x65ab6f18, 0xa8f73060, 0x56c84832, 0x9c6a604a, 0x8ef1ffad,
|
||||
0x4676a043, 0x6568c23e, 0x416ed459, 0xb586ec62, 0x122e98c2, 0x81a65618, 0x17db048e, 0x690f3b25,
|
||||
0xb58c4e32, 0x8e69e297, 0xd4dcaf42, 0x5158ac43, 0x0f9da082, 0x6cbaee60, 0x9e115b82, 0x55dffe96,
|
||||
0xa899f660, 0x846a0905, 0xf53a9252, 0xb283a4b8, 0x6db66b18, 0x867316b2, 0xdfad5753, 0x59995dd0,
|
||||
0x5e1caa6b, 0x08b3f160, 0x056a1bc6, 0x9c5403ae, 0x738cae43, 0x77fd211b, 0xd8e3a951, 0x150aad43,
|
||||
0x558809b0, 0xf04f454a, 0x09daf150, 0x3a433d63, 0xa4daf1c0, 0x4d551ac7, 0xd0edec69, 0xbe36f118,
|
||||
0x5b76b818, 0x8d919bd8, 0xbc92ea52, 0xe8096ec3, 0x1895e2bc, 0xfd053360, 0x701c42ad, 0x9a8e9bd8,
|
||||
0xac06aa6b, 0xc9851a56, 0x54f65e46, 0xb39e306c, 0x880763c0, 0x361f1fb0, 0x95a5b04c, 0x897319ad,
|
||||
0xc1b9be46, 0xe6d89d9d, 0xa75cd443, 0xb7361147, 0x630b8b25, 0x5a2e4ea6, 0x203bbb4b, 0x5b4b6c18,
|
||||
0x9dbbac43, 0x6d0663c0, 0x1f115536, 0x61d80718, 0xf4fde097, 0xfb50e162, 0x954a6276, 0x0006ee47,
|
||||
0x30b26eae, 0xf5737358, 0xf9a5fdce, 0xf2c75d18, 0xfda64b25, 0xd565d1a2, 0xf055a743, 0x10aaa545,
|
||||
0xa70c63c0, 0xa15a4450, 0xdbcb13ad, 0xdc705246, 0x02f7e9c7, 0xe57e6763, 0x65604ead, 0x07df1955,
|
||||
0x882faa6b, 0xb4286b18, 0x539747c0, 0xc9b6a1c0, 0xb76e7f46, 0xf3418432, 0xd5bbb153, 0xb840d3a2,
|
||||
0x6c0717d9, 0xb14109b0, 0x94076181, 0xf40aa953, 0x08de89c3, 0x06bdaa4d, 0x27efae32, 0x5ba4fe45,
|
||||
0x1e7410cc, 0x57e847d4, 0xe5425177, 0xb50b714c, 0x06513532, 0xfde617c6, 0xe05c3532, 0x0af30852,
|
||||
0xa2a33a60, 0x2cc7f3a2, 0x5777cf57, 0x313477d5, 0x311544c1, 0x49f4aa6b, 0xef01ef17, 0x07db33d4,
|
||||
0x0a60c947, 0xe4174e4d, 0x34058a12, 0x411e3ab8, 0xfc4a9532, 0x5bcaf082, 0x55c21955, 0x489a32b6,
|
||||
0xf1f7154c, 0x60fa9f6e, 0x4dc4ec57, 0x5fe7a743, 0x1309e552, 0x03e12c42, 0x07f4175e, 0xcb56aa43,
|
||||
0x9d411787, 0xc1686041, 0xeec21955, 0xe97cf3a2, 0x11cc6044, 0xce9b2b47, 0x32bb53d4, 0xc7153b25,
|
||||
0x7c24188d, 0x1640c947, 0x1606b941, 0x671d864b, 0xb4430118, 0x3c6641ad, 0xf99000c0, 0x57a745ad,
|
||||
0xf098880e, 0x7cd14298, 0xb53316b2, 0x5b0749ae, 0x80c734c6, 0x5bb26318, 0xf5734761, 0xb5a0f1c0,
|
||||
0x643f3cae, 0xd034324a, 0xd5ef81ae, 0xa383e447, 0x8c820298, 0xeba139ae, 0x1e73c80e, 0x0c3fe743,
|
||||
0x8ac65918, 0x03104081, 0xa486bb25, 0x24165343, 0x15c67118, 0x6204f948, 0x4e3d5bc6, 0x3ef9f382,
|
||||
0xe3e7524a, 0x9f10634c, 0xfba8794c, 0x0c2d306c, 0xb99df762, 0x3e1a4d47, 0x3f6c3951, 0xd373354d,
|
||||
0xca206c4a, 0x6f454aad, 0x02f5af43, 0x0f35831f, 0x31bcd4ad, 0xfa34da48, 0x3a598cae, 0x26ef7f4c,
|
||||
0xa104b648, 0x9cf2134c, 0xc5c2336c, 0x448f9c5b, 0x55b8f1c0, 0x115917ad, 0x33216f4b, 0x5c67692e,
|
||||
0xd436c658, 0x7c22da36, 0x0ce9e217, 0xa62a3160, 0xb08803ae, 0xf918c162, 0x0e9c096c, 0xf250119c,
|
||||
0x0d987f47, 0x40254832, 0x610df245, 0xa55cf3a2, 0xd4886e4a, 0xc172aa43, 0x1af4c04e, 0xbe2d47ae,
|
||||
0x58a0cf45, 0xa414dc48, 0xdde3f3a2, 0x26562843, 0x9aea0455, 0xb1b63c44, 0xcef89963, 0x12005d4d,
|
||||
0x21c21754, 0x18eef160, 0x4903a1cf, 0x9b023818, 0x4685336c, 0xc9f31556, 0xe6dd0a18, 0x099630ad,
|
||||
0x10dabd32, 0xcaaf708c, 0xc53ebb25, 0x42657a90, 0x74e3614c, 0x365c4048, 0x7cf9f3a2, 0x7f2addb0,
|
||||
0xe6bf09b0, 0x1165fa5b, 0xcef84e43, 0x895be7cf, 0xb2116c4a, 0xa423108a, 0xa3bec236, 0x196db14c,
|
||||
0xe05f6f4f, 0x07ee0118, 0xdcb8f8ce, 0xbd5e7918, 0x2159ab4d, 0x8ae54170, 0x527b0905, 0x7c8d3d44,
|
||||
0x0d552705, 0xe5b21cad, 0x1b8ae64e, 0xc79cab55, 0x4e88e2bc, 0x444c1581, 0x86147c4c, 0xb4222648,
|
||||
0x4136daad, 0x437ea22e, 0x2b92694c, 0x154baa6b, 0x0555795b, 0x9b484232, 0x6944f181, 0x036a6259,
|
||||
0x1808ff60, 0xb0403148, 0x7b5e1b59, 0xdd30fb62, 0x4583266c, 0xb289c96d, 0x35e4aa6b, 0x50a23532,
|
||||
0x3f1263c0, 0x763aae6c, 0xa729c144, 0x5ee5c64c, 0x02bf35d0, 0x367f3ac6, 0xfe547940, 0x2e1ea353,
|
||||
0xe798ee48, 0x6c058495, 0x755dd5cb, 0x2ca6ef63, 0x7a0574bc, 0x9ac81c2e, 0xa5b33e44, 0x4fe69953,
|
||||
0xf9556d62, 0x086a1bc6, 0xac28126c, 0x4fa7e6ad, 0xd4293d3e, 0x4e4f764b, 0x718849ad, 0x8139ff18,
|
||||
0x4c6118b9, 0x65444c90, 0x371eeda9, 0xe2b4c0ad, 0xcd01f5da, 0x7671c344, 0x3021f518, 0x26369c4b,
|
||||
0xd7f6f360, 0xdb55336c, 0xccdc7d18, 0x51d732c6, 0x335b5b4c, 0x094c2d05, 0x0dd546a6, 0x83d33118,
|
||||
0x33dcff6d, 0xfd40b64c, 0x86e93f18, 0x87e2c780, 0xf0e1c1b2, 0xc67be347, 0x1df9d243, 0x6a646dae,
|
||||
0xb0833b47, 0x8f457e4c, 0x0dbbe2bc, 0x4ac048c6, 0x7cc2194c, 0x1c84bb25, 0xb66b8218, 0xe3ee027b,
|
||||
0x5cd4048e, 0xadcb0b18, 0xdc036e18, 0xb62e7999, 0xdee95243, 0x1ccdc344, 0x91cde560, 0xc8e0f460,
|
||||
0xbea0f1c0, 0x35747b6d, 0x9686bb25, 0x28ce3c47, 0xaf0e5e48, 0x87f58f4b, 0x124dd9a2, 0xa21463c0,
|
||||
0xa8f94952, 0xf71fd586, 0xe6fa056c, 0x92b86bb8, 0x707d6981, 0x22870732, 0x116fef62, 0xe0fd3ead,
|
||||
0x78c2814e, 0x95d882c3, 0xdb3cba32, 0xe8b0e2bc, 0xb9c69b18, 0xe29ed783, 0x26c01118, 0xcbcd8451,
|
||||
0xf1d02e18, 0x1b55aead, 0xb5549bc0, 0x47baa232, 0xbcf8f1c0, 0xae29dbb2, 0x0b881cd2, 0x75c8bb25,
|
||||
0x14851955, 0xc7113b25, 0xa6db048e, 0x77606505, 0x4f163b25, 0x567c692e, 0x25e02a64, 0x10143b25,
|
||||
0x93123b25, 0xa463f8a2, 0xef218abc, 0x25133b25, 0xe189bb25, 0xc0f83eb2, 0x6ab7c936, 0xa3624c90,
|
||||
0x6af8c4d9, 0x38c55b80, 0xb21f09b0, 0x33e7a5bc, 0xf558fb94, 0x6a5c4c90, 0x20d0048e, 0x14d1048e,
|
||||
0xcabd2e4e, 0x26bfd35f, 0x065e8abc, 0xccce1c2e, 0x2a55ec6d, 0xcd01f5da, 0x0bef32c6, 0x991d5fc0,
|
||||
0x6f4d4550, 0x0f35831f, 0xc7183b25, 0x8c7b0905, 0x7a9cbb25, 0x7eafa951, 0x86579bc0, 0xa15a4450,
|
||||
0xe5425177, 0x876e8ad5, 0xf6946257, 0x40c5ffad, 0x2e209d53, 0x6262e773, 0x42ef4c90, 0x9fc351c5,
|
||||
0x45ac795b, 0x6ac66d4f, 0x0a588abc, 0x9d411787, 0x8f9bbb25, 0xc4288368, 0xf745535b, 0x9c7086cf,
|
||||
0xc4422e4e, 0xc2533532, 0x84945250, 0x8b5d715e, 0x0f331c73, 0x228a9bd8, 0x4f3f0849, 0x17f4bbd5,
|
||||
0xc0e64a4a, 0xc53ebb25, 0x8dfab7ad, 0x36097e40, 0x2a27966b, 0x307d8abc, 0x1a32c405, 0xcf8d3c41,
|
||||
0x809f8705, 0x21f232c6, 0x64693660, 0x83b763c0, 0xc613ec68, 0xaf517462, 0x8f61e497, 0xae7b0451,
|
||||
0xafd61955, 0x2b85d772, 0xde0cf062, 0xee4ec780, 0xef6aa56f, 0x09b85d61, 0xac44f6cc, 0xc0b73505,
|
||||
0x0dedb944, 0x554d6f4c, 0x627dfe42, 0x48ca34ae, 0x272371d4, 0xf252a5bc, 0x8740f718, 0x262371d4,
|
||||
0x3ce82760, 0xe17c8845, 0x7c17332a, 0x4f5abb25, 0x07eccf57, 0x183f6018, 0xcb4b5f5c, 0xc34a0d47,
|
||||
0x60a4c780, 0xe9c2784c, 0xbccac24d, 0xc143f03c, 0x0260ba7c, 0x4a81ae58, 0xe131b843, 0x1dae7fd5,
|
||||
0x75d041ad, 0x390c7ed0, 0xaeac6d62, 0x8de20e4c, 0x915ee097, 0x1a3e1049, 0x8aca6f18, 0xd4470444,
|
||||
0x4856b3ad, 0x387e211b, 0xd191feb6, 0xe3bd0d41, 0x130009b0, 0xdf18be43, 0xdf143b25, 0x1e93e66d,
|
||||
0x41cfa262, 0x859baa51, 0x3618aa6b, 0x74c5f1c0, 0x3c14226c, 0x5c3cd070, 0xbc671b4f, 0x3f5871d5,
|
||||
0x37011e02, 0xfe53186c, 0xd39bd176, 0x3822b718, 0xe27d3060, 0xabee32c6, 0xc697c818, 0xd22cde50,
|
||||
0xc4cc6c3a, 0xd24ccd43, 0xd450bb25, 0x4101ee43, 0x20f232c6, 0xb7997845, 0xd4e3c162, 0x2fbe7670,
|
||||
0x41a5ee52, 0x800a201b, 0x4699ccda, 0xfcabb552, 0xde53ad32, 0x61668c18, 0xca9ec24e, 0x8b1eac49,
|
||||
0xb990b142, 0xf1e1784d, 0x30d04147, 0x785a995b, 0x12d14acc, 0x39d43680, 0x65e70844, 0x54783b18,
|
||||
0x232a3a63, 0x4e0a194f, 0x2b813b18, 0x2ac0bc49, 0x6af1ae51, 0x3256d062, 0x13d72bd9, 0xa5496444,
|
||||
0xbc944c47, 0x7d35bdd5, 0x109f2446, 0x16ef2e25, 0xe2f2784b, 0xee5ddaac, 0xc7889718, 0xaf49be6d,
|
||||
0xc914a443, 0x1d2bc24e, 0x82199d5d, 0x689c226c, 0x04441b46, 0x1feca832, 0x94208c55, 0x6756a149,
|
||||
0x09dee8d8, 0x1435e9a9, 0x82859f32, 0xadf0a662, 0x2f2bb856, 0x756bcd5a, 0x6b6be917, 0x1c40604a,
|
||||
0xeec4b749, 0x4d44a6b8, 0x162d1cb0, 0x22f232c6, 0x5f2012ad, 0x35612053, 0x02b35e47, 0x2d5c3f44,
|
||||
0x6904ef17, 0xef8a0b4c, 0xe6908932, 0x0df86c76, 0x3669343c, 0xdd8ba87c, 0x35841386, 0xb406e044,
|
||||
0x14a6946d, 0x6a448e3f, 0x2341295e, 0xb2837325, 0x82cf0c05, 0xa64d4141, 0xeb24c672, 0x4282ffda,
|
||||
0xccf2336c, 0x64813fbc, 0x9c81d259, 0xfbe6ed60, 0xc24a1c6c, 0x470ddc48, 0xd4dcaf42, 0x4c373fb2,
|
||||
0xbb9589d9, 0x7e431bc6, 0x3d24be43, 0xf417af44, 0x83f05243, 0xbe022363, 0x10b71d5d, 0xaf4b88d5,
|
||||
0xc3b66644, 0x31d30b71, 0xa056aa6b, 0x48db0364, 0x9780f5ac, 0x763aa0ad, 0x8ebcfe40, 0x241847ad,
|
||||
0xacdbf562, 0xfd09f743, 0x4f211c60, 0x0d963468, 0x80db149a, 0x18e8b944, 0xbcc27746, 0x8f6ce95f,
|
||||
0xde2cee2e, 0x45a71457, 0xde894ead, 0x024cd348, 0x2e0e74ce, 0x23300cac, 0x90527f62, 0x1d66e56d,
|
||||
0x83eddb8d, 0x0850f555, 0xe9a4e797, 0x0ef1ab56, 0x140ed98e, 0x2d3f944d, 0x0b6d18bc, 0xab33ca49,
|
||||
0xaed3b962, 0xc8a0f155, 0xb3eb9c32, 0xfc06424b, 0x927af8ac, 0xdf0119bc, 0xf7ba2452, 0x26590c05,
|
||||
0x0ec0cb6d, 0x337b252d, 0xe7b04a97, 0x5cc4a505, 0x9e81884a, 0xd052534b, 0xf7aa7761, 0x6666b527,
|
||||
0x49a4fd62, 0x3f715247, 0x902baa46, 0x7645812e, 0xbf771240, 0xe58e2451, 0xbb95fca2, 0x35204718,
|
||||
0x759138ae, 0x84300edf, 0x67140d47, 0x2c34465f, 0x260d0f18, 0xfd985c32, 0x3ba94cb2, 0x8067b545,
|
||||
0x062ac825, 0xdee9de59, 0x6254bf32, 0x9b6d2b44, 0xbebd7670, 0x3c55b46c, 0x5e8e5561, 0xa6d9a656,
|
||||
0x631fe149, 0x102f0378, 0xf4ede844, 0x34b94b3e, 0x73cdd55a, 0xd114c850, 0x7b6c5343, 0x6a3dde47,
|
||||
0x385da2b8, 0xf5f8c3d2, 0xe44c0654, 0xa4cb42bb, 0xf53fd176, 0xa424a14b, 0x79b38856, 0xdb717b5d,
|
||||
0x97f0b8bf, 0x031c4627, 0x9731d35a, 0x7bd81e4c, 0x43a850bc, 0xa336ff71, 0xbabd0b59, 0x9767bc73,
|
||||
0x1c131d4c, 0x06a47744, 0x1f5dbe5e, 0xf76f18bc, 0x560ab918, 0xd7cb0202, 0x569b326c, 0x52024c72,
|
||||
0x47525a5f, 0xd36d475f, 0x2e7d5dcc, 0x60330202, 0xd13c026c, 0x1660d7b0, 0x1a042f4e, 0xe644005e,
|
||||
0x5c53ba41, 0xc5adf651, 0x84e15d62, 0xcb76364d, 0x78ec8573, 0x5f6a06ae, 0xac8d3347, 0xd8758fd5,
|
||||
0x91c5351f, 0xdd6d67b1, 0x6027e53c, 0x308bba6d, 0x15448945, 0x612d454b, 0x3a10a143, 0x9b38cf56,
|
||||
0x3c44c556, 0xffb8784c, 0x5409b04b, 0xab2f7661, 0xa286534b, 0x0476c944, 0xd9cf4a52, 0x9cfa276c,
|
||||
0xaf07936b, 0xfcd02e32, 0x2361db8d, 0xc62c878d, 0x560ae740, 0xb21d0818, 0x7a2c4605, 0x8cc6a73b,
|
||||
0x5757be56, 0x50f1e218, 0x13b9194f, 0x48eb17ad, 0x4279112e, 0xf92a3fbc, 0x8ecc0202, 0xe93237ae,
|
||||
0x9bcfc80e, 0x4d72a343, 0xb97eed8d, 0x6732b55e, 0x14fdab43, 0x05e502d4, 0x88bd436d, 0xf4985a86,
|
||||
0xa12f8156, 0x2a91052e, 0xa651d98e, 0x2f750947, 0x61fd5455, 0x8bbcb66e, 0xd7383a60, 0xd9d3945c,
|
||||
0x52e5ac2e, 0x5f7a49be, 0x59036a44, 0x4b7b1978, 0x3a88ca4e, 0x910953b2, 0xc744996d, 0x0b6277c7,
|
||||
0x02a1a6b8, 0x0234d9ad, 0x0e7b8f45, 0x48738653, 0x3a1a5447, 0x0fdc4950, 0x672d5847, 0x04e44448,
|
||||
0x7750945c, 0x602f3260, 0xf5b42201, 0x5c05922e, 0x203c5332, 0x1f7c484b, 0x1b2d8caf, 0xbc99e797,
|
||||
0xe695ed62, 0x11b38375, 0x55b84bb2, 0xfce349be, 0x7181456a, 0x4f51f643, 0x66bb7e52, 0x5d235db2,
|
||||
0xb8c52ab2, 0x111b90d9, 0xa80eb118
|
||||
};
|
||||
|
||||
class CMainParams : public CChainParams {
|
||||
|
@ -143,9 +124,9 @@ public:
|
|||
assert(genesis.hashMerkleRoot == uint256("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"));
|
||||
|
||||
vSeeds.push_back(CDNSSeedData("dogecoin.com", "seed.dogecoin.com"));
|
||||
vSeeds.push_back(CDNSSeedData("mophides.com", "seed.mophides.com"));
|
||||
vSeeds.push_back(CDNSSeedData("dglibrary.org", "seed.dglibrary.org"));
|
||||
vSeeds.push_back(CDNSSeedData("dogechain.info", "seed.dogechain.info"));
|
||||
vSeeds.push_back(CDNSSeedData("multidoge.org", "seed.multidoge.org"));
|
||||
vSeeds.push_back(CDNSSeedData("multidoge.org", "seed2.multidoge.org"));
|
||||
vSeeds.push_back(CDNSSeedData("doger.dogecoin.com", "seed.doger.dogecoin.com"));
|
||||
|
||||
// Workaround for Boost not being quite compatible with C++11;
|
||||
std::vector<unsigned char> pka = list_of(30);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// These need to be macros, as version.cpp's and dogecoin-qt.rc's voodoo requires it
|
||||
#define CLIENT_VERSION_MAJOR 1
|
||||
#define CLIENT_VERSION_MINOR 8
|
||||
#define CLIENT_VERSION_REVISION 2
|
||||
#define CLIENT_VERSION_REVISION 3
|
||||
#define CLIENT_VERSION_BUILD 0
|
||||
|
||||
// Set to true for release, false for prerelease or test build
|
||||
|
|
15
src/compat.h
15
src/compat.h
|
@ -59,19 +59,4 @@ typedef u_int SOCKET;
|
|||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
inline int myclosesocket(SOCKET& hSocket)
|
||||
{
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return WSAENOTSOCK;
|
||||
#ifdef WIN32
|
||||
int ret = closesocket(hSocket);
|
||||
#else
|
||||
int ret = close(hSocket);
|
||||
#endif
|
||||
hSocket = INVALID_SOCKET;
|
||||
return ret;
|
||||
}
|
||||
#define closesocket(s) myclosesocket(s)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
61
src/init.cpp
61
src/init.cpp
|
@ -62,7 +62,8 @@ CWallet* pwalletMain;
|
|||
enum BindFlags {
|
||||
BF_NONE = 0,
|
||||
BF_EXPLICIT = (1U << 0),
|
||||
BF_REPORT_ERROR = (1U << 1)
|
||||
BF_REPORT_ERROR = (1U << 1),
|
||||
BF_WHITELIST = (1U << 2),
|
||||
};
|
||||
|
||||
|
||||
|
@ -183,7 +184,7 @@ bool static Bind(const CService &addr, unsigned int flags) {
|
|||
if (!(flags & BF_EXPLICIT) && IsLimited(addr))
|
||||
return false;
|
||||
std::string strError;
|
||||
if (!BindListenPort(addr, strError)) {
|
||||
if (!BindListenPort(addr, strError, flags & BF_WHITELIST)) {
|
||||
if (flags & BF_REPORT_ERROR)
|
||||
return InitError(strError);
|
||||
return false;
|
||||
|
@ -236,9 +237,8 @@ std::string HelpMessage(HelpMessageMode hmm)
|
|||
strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n";
|
||||
strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n";
|
||||
strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 22556 or testnet: 44556)") + "\n";
|
||||
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS proxy") + "\n";
|
||||
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n";
|
||||
strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n";
|
||||
strUsage += " -socks=<n> " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n";
|
||||
strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n";
|
||||
#ifdef USE_UPNP
|
||||
#if USE_UPNP
|
||||
|
@ -247,6 +247,8 @@ std::string HelpMessage(HelpMessageMode hmm)
|
|||
strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n";
|
||||
#endif
|
||||
#endif
|
||||
strUsage += " -whitebind=<addr> " + _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6") + "\n";
|
||||
strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or ip. Can be specified multiple times.") + "\n";
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
strUsage += "\n" + _("Wallet options:") + "\n";
|
||||
|
@ -479,11 +481,11 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
nLocalServices |= NODE_BLOOM;
|
||||
}
|
||||
|
||||
if (mapArgs.count("-bind")) {
|
||||
if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
|
||||
// when specifying an explicit binding address, you want to listen on it
|
||||
// even when -connect or -proxy is specified
|
||||
if (SoftSetBoolArg("-listen", true))
|
||||
LogPrintf("AppInit2 : parameter interaction: -bind set -> setting -listen=1\n");
|
||||
LogPrintf("AppInit2 : parameter interaction: -bind or -whitebind set -> setting -listen=1\n");
|
||||
}
|
||||
|
||||
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) {
|
||||
|
@ -527,7 +529,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
}
|
||||
|
||||
// Make sure enough file descriptors are available
|
||||
int nBind = std::max((int)mapArgs.count("-bind"), 1);
|
||||
int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
|
||||
nMaxConnections = GetArg("-maxconnections", 125);
|
||||
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
|
||||
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
|
||||
|
@ -549,6 +551,12 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
// Check for -debugnet (deprecated)
|
||||
if (GetBoolArg("-debugnet", false))
|
||||
InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net"));
|
||||
// Check for -socks - as this is a privacy risk to continue, exit here
|
||||
if (mapArgs.count("-socks"))
|
||||
return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
|
||||
// Check for -tor - as this is a privacy risk to continue, exit here
|
||||
if (GetBoolArg("-tor", false))
|
||||
return InitError(_("Error: Unsupported argument -tor found, use -onion."));
|
||||
|
||||
fBenchmark = GetBoolArg("-benchmark", false);
|
||||
mempool.setSanityCheck(GetBoolArg("-checkmempool", RegTest()));
|
||||
|
@ -732,10 +740,6 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
|
||||
RegisterNodeSignals(GetNodeSignals());
|
||||
|
||||
int nSocksVersion = GetArg("-socks", 5);
|
||||
if (nSocksVersion != 4 && nSocksVersion != 5)
|
||||
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
|
||||
|
||||
if (mapArgs.count("-onlynet")) {
|
||||
std::set<enum Network> nets;
|
||||
BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
|
||||
|
@ -751,6 +755,15 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
}
|
||||
}
|
||||
|
||||
if (mapArgs.count("-whitelist")) {
|
||||
BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) {
|
||||
CSubNet subnet(net);
|
||||
if (!subnet.IsValid())
|
||||
return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
|
||||
CNode::AddWhitelistedRange(subnet);
|
||||
}
|
||||
}
|
||||
|
||||
CService addrProxy;
|
||||
bool fProxy = false;
|
||||
if (mapArgs.count("-proxy")) {
|
||||
|
@ -759,12 +772,10 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"]));
|
||||
|
||||
if (!IsLimited(NET_IPV4))
|
||||
SetProxy(NET_IPV4, addrProxy, nSocksVersion);
|
||||
if (nSocksVersion > 4) {
|
||||
if (!IsLimited(NET_IPV6))
|
||||
SetProxy(NET_IPV6, addrProxy, nSocksVersion);
|
||||
SetNameProxy(addrProxy, nSocksVersion);
|
||||
}
|
||||
SetProxy(NET_IPV4, addrProxy);
|
||||
if (!IsLimited(NET_IPV6))
|
||||
SetProxy(NET_IPV6, addrProxy);
|
||||
SetNameProxy(addrProxy);
|
||||
fProxy = true;
|
||||
}
|
||||
|
||||
|
@ -782,24 +793,32 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
addrOnion = mapArgs.count("-onion")?CService(mapArgs["-onion"], 9050):CService(mapArgs["-tor"], 9050);
|
||||
if (!addrOnion.IsValid())
|
||||
return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs.count("-onion")?mapArgs["-onion"]:mapArgs["-tor"]));
|
||||
SetProxy(NET_TOR, addrOnion, 5);
|
||||
SetProxy(NET_TOR, addrOnion);
|
||||
SetReachable(NET_TOR);
|
||||
}
|
||||
|
||||
// see Step 2: parameter interactions for more information about these
|
||||
fNoListen = !GetBoolArg("-listen", true);
|
||||
fListen = GetBoolArg("-listen", true);
|
||||
fDiscover = GetBoolArg("-discover", true);
|
||||
fNameLookup = GetBoolArg("-dns", true);
|
||||
|
||||
bool fBound = false;
|
||||
if (!fNoListen) {
|
||||
if (mapArgs.count("-bind")) {
|
||||
if (fListen) {
|
||||
if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
|
||||
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
|
||||
CService addrBind;
|
||||
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
|
||||
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
|
||||
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
|
||||
}
|
||||
BOOST_FOREACH(std::string strBind, mapMultiArgs["-whitebind"]) {
|
||||
CService addrBind;
|
||||
if (!Lookup(strBind.c_str(), addrBind, 0, false))
|
||||
return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
|
||||
if (addrBind.GetPort() == 0)
|
||||
return InitError(strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind));
|
||||
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST));
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct in_addr inaddr_any;
|
||||
|
|
62
src/main.cpp
62
src/main.cpp
|
@ -207,9 +207,13 @@ struct CBlockReject {
|
|||
// processing of incoming data is done after the ProcessMessage call returns,
|
||||
// and we're no longer holding the node's locks.
|
||||
struct CNodeState {
|
||||
//! The peer's address
|
||||
CService address;
|
||||
//! Whether we have a fully established connection.
|
||||
bool fCurrentlyConnected;
|
||||
// Accumulated misbehaviour score for this peer.
|
||||
int nMisbehavior;
|
||||
// Whether this peer should be disconnected and banned.
|
||||
// Whether this peer should be disconnected and banned (unless whitelisted).
|
||||
bool fShouldBan;
|
||||
// String name of this peer (debugging/logging purposes).
|
||||
std::string name;
|
||||
|
@ -223,6 +227,7 @@ struct CNodeState {
|
|||
int64_t nLastBlockProcess;
|
||||
|
||||
CNodeState() {
|
||||
fCurrentlyConnected = false;
|
||||
nMisbehavior = 0;
|
||||
fShouldBan = false;
|
||||
nBlocksToDownload = 0;
|
||||
|
@ -253,12 +258,16 @@ void InitializeNode(NodeId nodeid, const CNode *pnode) {
|
|||
LOCK(cs_main);
|
||||
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
|
||||
state.name = pnode->addrName;
|
||||
state.address = pnode->addr;
|
||||
}
|
||||
|
||||
void FinalizeNode(NodeId nodeid) {
|
||||
LOCK(cs_main);
|
||||
CNodeState *state = State(nodeid);
|
||||
|
||||
if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
|
||||
AddressCurrentlyConnected(state->address);
|
||||
}
|
||||
BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight)
|
||||
mapBlocksInFlight.erase(entry.hash);
|
||||
BOOST_FOREACH(const uint256& hash, state->vBlocksToDownload)
|
||||
|
@ -1571,7 +1580,8 @@ void Misbehaving(NodeId pnode, int howmuch)
|
|||
return;
|
||||
|
||||
state->nMisbehavior += howmuch;
|
||||
if (state->nMisbehavior >= GetArg("-banscore", 100))
|
||||
int banscore = GetArg("-banscore", 100);
|
||||
if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore)
|
||||
{
|
||||
LogPrintf("Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
|
||||
state->fShouldBan = true;
|
||||
|
@ -3737,7 +3747,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||
}
|
||||
}
|
||||
|
||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
|
||||
{
|
||||
RandAddSeedPerfmon();
|
||||
LogPrint("net", "received: %s (%" PRIszu" bytes)\n", strCommand, vRecv.size());
|
||||
|
@ -3822,7 +3832,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
if (!pfrom->fInbound)
|
||||
{
|
||||
// Advertise our address
|
||||
if (!fNoListen && !IsInitialBlockDownload())
|
||||
if (fListen && !IsInitialBlockDownload())
|
||||
{
|
||||
CAddress addr = GetLocalAddress(&pfrom->addr);
|
||||
if (addr.IsRoutable())
|
||||
|
@ -3870,6 +3880,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
else if (strCommand == "verack")
|
||||
{
|
||||
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
||||
|
||||
// Mark this node as currently connected, so we update its timestamp later.
|
||||
if (pfrom->fNetworkNode) {
|
||||
LOCK(cs_main);
|
||||
State(pfrom->GetId())->fCurrentlyConnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -4163,6 +4179,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx);
|
||||
if (nEvicted > 0)
|
||||
LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
|
||||
} else if (pfrom->fWhitelisted) {
|
||||
// Always relay transactions received from whitelisted peers, even
|
||||
// if they are already in the mempool (allowing the node to function
|
||||
// as a gateway for nodes hidden behind it).
|
||||
RelayTransaction(tx, tx.GetHash());
|
||||
}
|
||||
int nDoS = 0;
|
||||
if (state.IsInvalid(nDoS))
|
||||
|
@ -4257,7 +4278,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
|
||||
else if (strCommand == "pong")
|
||||
{
|
||||
int64_t pingUsecEnd = GetTimeMicros();
|
||||
int64_t pingUsecEnd = nTimeReceived;
|
||||
uint64_t nonce = 0;
|
||||
size_t nAvail = vRecv.in_avail();
|
||||
bool bPingFinished = false;
|
||||
|
@ -4426,11 +4447,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
}
|
||||
|
||||
|
||||
// Update the last seen time for this node's address
|
||||
if (pfrom->fNetworkNode)
|
||||
if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")
|
||||
AddressCurrentlyConnected(pfrom->addr);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4513,7 +4529,7 @@ bool ProcessMessages(CNode* pfrom)
|
|||
bool fRet = false;
|
||||
try
|
||||
{
|
||||
fRet = ProcessMessage(pfrom, strCommand, vRecv);
|
||||
fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime);
|
||||
boost::this_thread::interruption_point();
|
||||
}
|
||||
catch (std::ios_base::failure& e)
|
||||
|
@ -4572,8 +4588,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||
// RPC ping request by user
|
||||
pingSend = true;
|
||||
}
|
||||
if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSendMsg.empty()) {
|
||||
// Ping automatically sent as a keepalive
|
||||
if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
|
||||
// Ping automatically sent as a latency probe & keepalive.
|
||||
pingSend = true;
|
||||
}
|
||||
if (pingSend) {
|
||||
|
@ -4581,15 +4597,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||
while (nonce == 0) {
|
||||
RAND_bytes((unsigned char*)&nonce, sizeof(nonce));
|
||||
}
|
||||
pto->nPingNonceSent = nonce;
|
||||
pto->fPingQueued = false;
|
||||
pto->nPingUsecStart = GetTimeMicros();
|
||||
if (pto->nVersion > BIP0031_VERSION) {
|
||||
// Take timestamp as close as possible before transmitting ping
|
||||
pto->nPingUsecStart = GetTimeMicros();
|
||||
pto->nPingNonceSent = nonce;
|
||||
pto->PushMessage("ping", nonce);
|
||||
} else {
|
||||
// Peer is too old to support ping command with nonce, pong will never arrive, disable timing
|
||||
pto->nPingUsecStart = 0;
|
||||
// Peer is too old to support ping command with nonce, pong will never arrive.
|
||||
pto->nPingNonceSent = 0;
|
||||
pto->PushMessage("ping");
|
||||
}
|
||||
}
|
||||
|
@ -4611,7 +4626,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||
pnode->setAddrKnown.clear();
|
||||
|
||||
// Rebroadcast our address
|
||||
if (!fNoListen)
|
||||
if (fListen)
|
||||
{
|
||||
CAddress addr = GetLocalAddress(&pnode->addr);
|
||||
if (addr.IsRoutable())
|
||||
|
@ -4650,11 +4665,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||
|
||||
CNodeState &state = *State(pto->GetId());
|
||||
if (state.fShouldBan) {
|
||||
if (pto->addr.IsLocal())
|
||||
LogPrintf("Warning: not banning local node %s!\n", pto->addr.ToString());
|
||||
if (pto->fWhitelisted)
|
||||
LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
|
||||
else {
|
||||
pto->fDisconnect = true;
|
||||
CNode::Ban(pto->addr);
|
||||
if (pto->addr.IsLocal())
|
||||
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
|
||||
else
|
||||
CNode::Ban(pto->addr);
|
||||
}
|
||||
state.fShouldBan = false;
|
||||
}
|
||||
|
|
212
src/net.cpp
212
src/net.cpp
|
@ -36,9 +36,31 @@
|
|||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
|
||||
// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
|
||||
#ifdef WIN32
|
||||
#ifndef PROTECTION_LEVEL_UNRESTRICTED
|
||||
#define PROTECTION_LEVEL_UNRESTRICTED 10
|
||||
#endif
|
||||
#ifndef IPV6_PROTECTION_LEVEL
|
||||
#define IPV6_PROTECTION_LEVEL 23
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
namespace {
|
||||
const int MAX_OUTBOUND_CONNECTIONS = 8;
|
||||
|
||||
struct ListenSocket {
|
||||
SOCKET socket;
|
||||
bool whitelisted;
|
||||
|
||||
ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {}
|
||||
};
|
||||
}
|
||||
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
|
||||
|
||||
|
||||
|
@ -46,6 +68,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
|
|||
// Global state variables
|
||||
//
|
||||
bool fDiscover = true;
|
||||
bool fListen = true;
|
||||
uint64_t nLocalServices = NODE_NETWORK;
|
||||
CCriticalSection cs_mapLocalHost;
|
||||
map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
|
@ -54,7 +77,7 @@ static bool vfLimited[NET_MAX] = {};
|
|||
static CNode* pnodeLocalHost = NULL;
|
||||
static CNode* pnodeSync = NULL;
|
||||
uint64_t nLocalHostNonce = 0;
|
||||
static std::vector<SOCKET> vhListenSocket;
|
||||
static std::vector<ListenSocket> vhListenSocket;
|
||||
CAddrMan addrman;
|
||||
int nMaxConnections = 125;
|
||||
int nMaxOutboundConnections = 8;
|
||||
|
@ -98,7 +121,7 @@ unsigned short GetListenPort()
|
|||
// find 'best' local address for a particular peer
|
||||
bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
|
||||
{
|
||||
if (fNoListen)
|
||||
if (!fListen)
|
||||
return false;
|
||||
|
||||
int nBestScore = -1;
|
||||
|
@ -313,7 +336,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
|
|||
{
|
||||
if (!RecvLine(hSocket, strLine))
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (pszKeyword == NULL)
|
||||
|
@ -324,7 +347,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
|
|||
break;
|
||||
}
|
||||
}
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
if (strLine.find("<") != string::npos)
|
||||
strLine = strLine.substr(0, strLine.find("<"));
|
||||
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
|
||||
|
@ -338,7 +361,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
|
|||
return true;
|
||||
}
|
||||
}
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("GetMyExternalIP() : connection closed");
|
||||
}
|
||||
|
||||
|
@ -499,8 +522,7 @@ void CNode::CloseSocketDisconnect()
|
|||
if (hSocket != INVALID_SOCKET)
|
||||
{
|
||||
LogPrint("net", "disconnecting node %s\n", addrName);
|
||||
closesocket(hSocket);
|
||||
hSocket = INVALID_SOCKET;
|
||||
CloseSocket(hSocket);
|
||||
}
|
||||
|
||||
// in case this fails, we'll empty the recv buffer when the CNode is deleted
|
||||
|
@ -513,11 +535,6 @@ void CNode::CloseSocketDisconnect()
|
|||
pnodeSync = NULL;
|
||||
}
|
||||
|
||||
void CNode::Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNode::PushVersion()
|
||||
{
|
||||
int nBestHeight = g_signals.GetHeight().get_value_or(0);
|
||||
|
@ -570,6 +587,24 @@ bool CNode::Ban(const CNetAddr &addr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::vector<CSubNet> CNode::vWhitelistedRange;
|
||||
CCriticalSection CNode::cs_vWhitelistedRange;
|
||||
|
||||
bool CNode::IsWhitelistedRange(const CNetAddr &addr) {
|
||||
LOCK(cs_vWhitelistedRange);
|
||||
BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) {
|
||||
if (subnet.Match(addr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CNode::AddWhitelistedRange(const CSubNet &subnet) {
|
||||
LOCK(cs_vWhitelistedRange);
|
||||
vWhitelistedRange.push_back(subnet);
|
||||
}
|
||||
|
||||
#undef X
|
||||
#define X(name) stats.name = name
|
||||
void CNode::copyStats(CNodeStats &stats)
|
||||
|
@ -586,6 +621,7 @@ void CNode::copyStats(CNodeStats &stats)
|
|||
X(nStartingHeight);
|
||||
X(nSendBytes);
|
||||
X(nRecvBytes);
|
||||
X(fWhitelisted);
|
||||
stats.fSyncNode = (this == pnodeSync);
|
||||
|
||||
// It is common for nodes with good ping times to suddenly become lagged,
|
||||
|
@ -630,8 +666,16 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
|
|||
if (handled < 0)
|
||||
return false;
|
||||
|
||||
if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
|
||||
LogPrint("net", "Oversized message from peer=%i, disconnecting", GetId());
|
||||
return false;
|
||||
}
|
||||
|
||||
pch += handled;
|
||||
nBytes -= handled;
|
||||
|
||||
if (msg.complete())
|
||||
msg.nTime = GetTimeMicros();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -759,7 +803,6 @@ void ThreadSocketHandler()
|
|||
|
||||
// close socket and cleanup
|
||||
pnode->CloseSocketDisconnect();
|
||||
pnode->Cleanup();
|
||||
|
||||
// hold in disconnected pool until all refs are released
|
||||
if (pnode->fNetworkNode || pnode->fInbound)
|
||||
|
@ -803,7 +846,6 @@ void ThreadSocketHandler()
|
|||
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Find which sockets have data to receive
|
||||
//
|
||||
|
@ -820,11 +862,12 @@ void ThreadSocketHandler()
|
|||
SOCKET hSocketMax = 0;
|
||||
bool have_fds = false;
|
||||
|
||||
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
|
||||
FD_SET(hListenSocket, &fdsetRecv);
|
||||
hSocketMax = max(hSocketMax, hListenSocket);
|
||||
BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
|
||||
FD_SET(hListenSocket.socket, &fdsetRecv);
|
||||
hSocketMax = max(hSocketMax, hListenSocket.socket);
|
||||
have_fds = true;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
|
@ -885,58 +928,61 @@ void ThreadSocketHandler()
|
|||
MilliSleep(timeout.tv_usec/1000);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Accept new connections
|
||||
//
|
||||
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
|
||||
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
|
||||
BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
|
||||
{
|
||||
struct sockaddr_storage sockaddr;
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
|
||||
CAddress addr;
|
||||
int nInbound = 0;
|
||||
if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
|
||||
{
|
||||
struct sockaddr_storage sockaddr;
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
|
||||
CAddress addr;
|
||||
int nInbound = 0;
|
||||
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
||||
LogPrintf("Warning: Unknown socket family\n");
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
||||
LogPrintf("Warning: Unknown socket family\n");
|
||||
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->fInbound)
|
||||
nInbound++;
|
||||
}
|
||||
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr != WSAEWOULDBLOCK)
|
||||
LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
|
||||
}
|
||||
else if (nInbound >= nMaxConnections - nMaxOutboundConnections)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else if (CNode::IsBanned(addr))
|
||||
{
|
||||
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint("net", "accepted connection %s\n", addr.ToString());
|
||||
CNode* pnode = new CNode(hSocket, addr, "", true);
|
||||
pnode->AddRef();
|
||||
bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodes.push_back(pnode);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->fInbound)
|
||||
nInbound++;
|
||||
}
|
||||
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr != WSAEWOULDBLOCK)
|
||||
LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
|
||||
}
|
||||
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
|
||||
{
|
||||
CloseSocket(hSocket);
|
||||
}
|
||||
else if (CNode::IsBanned(addr) && !whitelisted)
|
||||
{
|
||||
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
|
||||
CloseSocket(hSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint("net", "accepted connection %s\n", addr.ToString());
|
||||
CNode* pnode = new CNode(hSocket, addr, "", true);
|
||||
pnode->AddRef();
|
||||
pnode->fWhitelisted = whitelisted;
|
||||
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodes.push_back(pnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Service each socket
|
||||
//
|
||||
|
@ -1010,23 +1056,27 @@ void ThreadSocketHandler()
|
|||
//
|
||||
// Inactivity checking
|
||||
//
|
||||
if (pnode->vSendMsg.empty())
|
||||
pnode->nLastSendEmpty = GetTime();
|
||||
if (GetTime() - pnode->nTimeConnected > 60)
|
||||
int64_t nTime = GetTime();
|
||||
if (nTime - pnode->nTimeConnected > 60)
|
||||
{
|
||||
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
|
||||
{
|
||||
LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
|
||||
else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
|
||||
{
|
||||
LogPrintf("socket not sending\n");
|
||||
LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
else if (GetTime() - pnode->nLastRecv > 90*60)
|
||||
else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
|
||||
{
|
||||
LogPrintf("socket inactivity timeout\n");
|
||||
LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
|
||||
{
|
||||
LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
}
|
||||
|
@ -1310,8 +1360,7 @@ void ThreadOpenConnections()
|
|||
int nTries = 0;
|
||||
while (true)
|
||||
{
|
||||
// use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
|
||||
CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
|
||||
CAddress addr = addrman.Select();
|
||||
|
||||
// if we selected an invalid address, restart
|
||||
if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
|
||||
|
@ -1557,7 +1606,7 @@ void ThreadMessageHandler()
|
|||
|
||||
|
||||
|
||||
bool BindListenPort(const CService &addrBind, string& strError)
|
||||
bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted)
|
||||
{
|
||||
strError = "";
|
||||
int nOne = 1;
|
||||
|
@ -1580,18 +1629,16 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef SO_NOSIGPIPE
|
||||
// Different way of disabling SIGPIPE on BSD
|
||||
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
// Allow binding if the port is still in TIME_WAIT state after
|
||||
// the program was closed and restarted. Not an issue on windows.
|
||||
// the program was closed and restarted. Not an issue on windows!
|
||||
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
// Set to non-blocking, incoming connections will also inherit this
|
||||
if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
|
||||
|
@ -1615,10 +1662,8 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
|||
#endif
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
|
||||
int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
|
||||
// this call is allowed to fail
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
|
||||
int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1630,6 +1675,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
|||
else
|
||||
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
|
||||
LogPrintf("%s\n", strError);
|
||||
CloseSocket(hListenSocket);
|
||||
return false;
|
||||
}
|
||||
LogPrintf("Bound to %s\n", addrBind.ToString());
|
||||
|
@ -1639,12 +1685,13 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
|||
{
|
||||
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
|
||||
LogPrintf("%s\n", strError);
|
||||
CloseSocket(hListenSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
vhListenSocket.push_back(hListenSocket);
|
||||
vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted));
|
||||
|
||||
if (addrBind.IsRoutable() && fDiscover)
|
||||
if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
|
||||
AddLocal(addrBind, LOCAL_BIND);
|
||||
|
||||
return true;
|
||||
|
@ -1771,11 +1818,11 @@ public:
|
|||
// Close sockets
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->hSocket != INVALID_SOCKET)
|
||||
closesocket(pnode->hSocket);
|
||||
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
|
||||
if (hListenSocket != INVALID_SOCKET)
|
||||
if (closesocket(hListenSocket) == SOCKET_ERROR)
|
||||
LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
|
||||
CloseSocket(pnode->hSocket);
|
||||
BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket)
|
||||
if (hListenSocket.socket != INVALID_SOCKET)
|
||||
if (!CloseSocket(hListenSocket.socket))
|
||||
LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
|
||||
|
||||
// clean up some globals (to help leak detection)
|
||||
BOOST_FOREACH(CNode *pnode, vNodes)
|
||||
|
@ -1784,6 +1831,7 @@ public:
|
|||
delete pnode;
|
||||
vNodes.clear();
|
||||
vNodesDisconnected.clear();
|
||||
vhListenSocket.clear();
|
||||
delete semOutbound;
|
||||
semOutbound = NULL;
|
||||
delete pnodeLocalHost;
|
||||
|
|
37
src/net.h
37
src/net.h
|
@ -28,6 +28,7 @@
|
|||
#include <boost/signals2/signal.hpp>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
||||
class CAddrMan;
|
||||
class CBlockIndex;
|
||||
class CNode;
|
||||
|
@ -36,8 +37,14 @@ namespace boost {
|
|||
class thread_group;
|
||||
}
|
||||
|
||||
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
||||
static const int PING_INTERVAL = 2 * 60;
|
||||
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
||||
static const int TIMEOUT_INTERVAL = 20 * 60;
|
||||
/** The maximum number of entries in an 'inv' protocol message */
|
||||
static const unsigned int MAX_INV_SZ = 50000;
|
||||
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
|
||||
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
|
||||
/** The maximum number of entries in mapAskFor */
|
||||
static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
|
||||
|
||||
|
@ -53,7 +60,7 @@ CNode* FindNode(const CService& ip);
|
|||
CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL);
|
||||
void MapPort(bool fUseUPnP);
|
||||
unsigned short GetListenPort();
|
||||
bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string()));
|
||||
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
|
||||
void StartNode(boost::thread_group& threadGroup);
|
||||
bool StopNode();
|
||||
void SocketSendData(CNode *pnode);
|
||||
|
@ -100,6 +107,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
|||
|
||||
|
||||
extern bool fDiscover;
|
||||
extern bool fListen;
|
||||
extern uint64_t nLocalServices;
|
||||
extern uint64_t nLocalHostNonce;
|
||||
extern CAddrMan addrman;
|
||||
|
@ -143,6 +151,7 @@ public:
|
|||
uint64_t nSendBytes;
|
||||
uint64_t nRecvBytes;
|
||||
bool fSyncNode;
|
||||
bool fWhitelisted;
|
||||
double dPingTime;
|
||||
double dPingWait;
|
||||
std::string addrLocal;
|
||||
|
@ -162,11 +171,14 @@ public:
|
|||
CDataStream vRecv; // received message data
|
||||
unsigned int nDataPos;
|
||||
|
||||
int64_t nTime; // time (in microseconds) of message receipt.
|
||||
|
||||
CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) {
|
||||
hdrbuf.resize(24);
|
||||
in_data = false;
|
||||
nHdrPos = 0;
|
||||
nDataPos = 0;
|
||||
nTime = 0;
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
|
@ -212,7 +224,6 @@ public:
|
|||
|
||||
int64_t nLastSend;
|
||||
int64_t nLastRecv;
|
||||
int64_t nLastSendEmpty;
|
||||
int64_t nTimeConnected;
|
||||
CAddress addr;
|
||||
std::string addrName;
|
||||
|
@ -223,6 +234,7 @@ public:
|
|||
// store the sanitized version in cleanSubVer. The original should be used when dealing with
|
||||
// the network or wire types and the cleaned string used when displayed or logged.
|
||||
std::string strSubVer, cleanSubVer;
|
||||
bool fWhitelisted; // This peer can bypass DoS banning.
|
||||
bool fOneShot;
|
||||
bool fClient;
|
||||
bool fInbound;
|
||||
|
@ -246,6 +258,11 @@ protected:
|
|||
static std::map<CNetAddr, int64_t> setBanned;
|
||||
static CCriticalSection cs_setBanned;
|
||||
|
||||
// Whitelisted ranges. Any node connecting from these is automatically
|
||||
// whitelisted (as well as those connecting to whitelisted binds).
|
||||
static std::vector<CSubNet> vWhitelistedRange;
|
||||
static CCriticalSection cs_vWhitelistedRange;
|
||||
|
||||
// Basic fuzz-testing
|
||||
void Fuzz(int nChance); // modifies ssSend
|
||||
|
||||
|
@ -268,10 +285,14 @@ public:
|
|||
CCriticalSection cs_inventory;
|
||||
std::multimap<int64_t, CInv> mapAskFor;
|
||||
|
||||
// Ping time measurement
|
||||
// Ping time measurement:
|
||||
// The pong reply we're expecting, or 0 if no pong expected.
|
||||
uint64_t nPingNonceSent;
|
||||
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
|
||||
int64_t nPingUsecStart;
|
||||
// Last measured round-trip time.
|
||||
int64_t nPingUsecTime;
|
||||
// Whether a ping is requested.
|
||||
bool fPingQueued;
|
||||
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000)
|
||||
|
@ -283,12 +304,12 @@ public:
|
|||
nLastRecv = 0;
|
||||
nSendBytes = 0;
|
||||
nRecvBytes = 0;
|
||||
nLastSendEmpty = GetTime();
|
||||
nTimeConnected = GetTime();
|
||||
addr = addrIn;
|
||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||
nVersion = 0;
|
||||
strSubVer = "";
|
||||
fWhitelisted = false;
|
||||
fOneShot = false;
|
||||
fClient = false; // set by version message
|
||||
fInbound = fInboundIn;
|
||||
|
@ -328,8 +349,7 @@ public:
|
|||
{
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
hSocket = INVALID_SOCKET;
|
||||
CloseSocket(hSocket);
|
||||
}
|
||||
if (pfilter)
|
||||
delete pfilter;
|
||||
|
@ -682,8 +702,6 @@ public:
|
|||
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
|
||||
void CancelSubscribe(unsigned int nChannel);
|
||||
void CloseSocketDisconnect();
|
||||
void Cleanup();
|
||||
|
||||
|
||||
// Denial-of-service detection/prevention
|
||||
// The idea is to detect peers that are behaving
|
||||
|
@ -704,6 +722,9 @@ public:
|
|||
static bool Ban(const CNetAddr &ip);
|
||||
void copyStats(CNodeStats &stats);
|
||||
|
||||
static bool IsWhitelistedRange(const CNetAddr &ip);
|
||||
static void AddWhitelistedRange(const CSubNet &subnet);
|
||||
|
||||
// Network stats
|
||||
static void RecordBytesRecv(uint64_t bytes);
|
||||
static void RecordBytesSent(uint64_t bytes);
|
||||
|
|
177
src/netbase.cpp
177
src/netbase.cpp
|
@ -25,7 +25,7 @@ using namespace std;
|
|||
|
||||
// Settings
|
||||
static proxyType proxyInfo[NET_MAX];
|
||||
static proxyType nameproxyInfo;
|
||||
static CService nameProxy;
|
||||
static CCriticalSection cs_proxyInfos;
|
||||
int nConnectTimeout = 5000;
|
||||
bool fNameLookup = false;
|
||||
|
@ -161,56 +161,12 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
|
|||
return Lookup(pszName, addr, portDefault, false);
|
||||
}
|
||||
|
||||
bool static Socks4(const CService &addrDest, SOCKET& hSocket)
|
||||
{
|
||||
LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString());
|
||||
if (!addrDest.IsIPv4())
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Proxy destination is not IPv4");
|
||||
}
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Cannot get proxy destination address");
|
||||
}
|
||||
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
|
||||
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
|
||||
char* pszSocks4 = pszSocks4IP;
|
||||
int nSize = sizeof(pszSocks4IP);
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet[1] != 0x5a)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
if (pchRet[1] != 0x5b)
|
||||
LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]);
|
||||
return false;
|
||||
}
|
||||
LogPrintf("SOCKS4 connected %s\n", addrDest.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
||||
{
|
||||
LogPrintf("SOCKS5 connecting %s\n", strDest);
|
||||
if (strDest.size() > 255)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Hostname too long");
|
||||
}
|
||||
char pszSocks5Init[] = "\5\1\0";
|
||||
|
@ -219,18 +175,18 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
|||
ssize_t ret = send(hSocket, pszSocks5Init, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet1[2];
|
||||
if (recv(hSocket, pchRet1, 2, 0) != 2)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Proxy failed to initialize");
|
||||
}
|
||||
string strSocks5("\5\1");
|
||||
|
@ -242,23 +198,23 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
|||
ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL);
|
||||
if (ret != (ssize_t)strSocks5.size())
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet2[4];
|
||||
if (recv(hSocket, pchRet2, 4, 0) != 4)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet2[0] != 0x05)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Proxy failed to accept request");
|
||||
}
|
||||
if (pchRet2[1] != 0x00)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
switch (pchRet2[1])
|
||||
{
|
||||
case 0x01: return error("Proxy error: general failure");
|
||||
|
@ -274,7 +230,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
|||
}
|
||||
if (pchRet2[2] != 0x00)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error: malformed proxy response");
|
||||
}
|
||||
char pchRet3[256];
|
||||
|
@ -286,23 +242,23 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
|||
{
|
||||
ret = recv(hSocket, pchRet3, 1, 0) != 1;
|
||||
if (ret) {
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error reading from proxy");
|
||||
}
|
||||
int nRecv = pchRet3[0];
|
||||
ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
|
||||
break;
|
||||
}
|
||||
default: closesocket(hSocket); return error("Error: malformed proxy response");
|
||||
default: CloseSocket(hSocket); return error("Error: malformed proxy response");
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error reading from proxy");
|
||||
}
|
||||
if (recv(hSocket, pchRet3, 2, 0) != 2)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return error("Error reading from proxy");
|
||||
}
|
||||
LogPrintf("SOCKS5 connected %s\n", strDest);
|
||||
|
@ -336,7 +292,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||
if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -356,13 +312,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||
if (nRet == 0)
|
||||
{
|
||||
LogPrint("net", "connection to %s timeout\n", addrConnect.ToString());
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
socklen_t nRetSize = sizeof(nRet);
|
||||
|
@ -373,13 +329,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||
#endif
|
||||
{
|
||||
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet != 0)
|
||||
{
|
||||
LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +346,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||
#endif
|
||||
{
|
||||
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +362,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||
if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
CloseSocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -414,53 +370,49 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) {
|
||||
bool SetProxy(enum Network net, CService addrProxy) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
if (!addrProxy.IsValid())
|
||||
return false;
|
||||
LOCK(cs_proxyInfos);
|
||||
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
|
||||
proxyInfo[net] = addrProxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
LOCK(cs_proxyInfos);
|
||||
if (!proxyInfo[net].second)
|
||||
if (!proxyInfo[net].IsValid())
|
||||
return false;
|
||||
proxyInfoOut = proxyInfo[net];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion) {
|
||||
if (nSocksVersion != 0 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
bool SetNameProxy(CService addrProxy) {
|
||||
if (!addrProxy.IsValid())
|
||||
return false;
|
||||
LOCK(cs_proxyInfos);
|
||||
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
|
||||
nameProxy = addrProxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetNameProxy(proxyType &nameproxyInfoOut) {
|
||||
bool GetNameProxy(CService &nameProxyOut) {
|
||||
LOCK(cs_proxyInfos);
|
||||
if (!nameproxyInfo.second)
|
||||
if(!nameProxy.IsValid())
|
||||
return false;
|
||||
nameproxyInfoOut = nameproxyInfo;
|
||||
nameProxyOut = nameProxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HaveNameProxy() {
|
||||
LOCK(cs_proxyInfos);
|
||||
return nameproxyInfo.second != 0;
|
||||
return nameProxy.IsValid();
|
||||
}
|
||||
|
||||
bool IsProxy(const CNetAddr &addr) {
|
||||
LOCK(cs_proxyInfos);
|
||||
for (int i = 0; i < NET_MAX; i++) {
|
||||
if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first))
|
||||
if (addr == (CNetAddr)proxyInfo[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -469,31 +421,18 @@ bool IsProxy(const CNetAddr &addr) {
|
|||
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
proxyType proxy;
|
||||
|
||||
// no proxy needed
|
||||
// no proxy needed (none set for target network)
|
||||
if (!GetProxy(addrDest.GetNetwork(), proxy))
|
||||
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
|
||||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
|
||||
// first connect to proxy server
|
||||
if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout))
|
||||
if (!ConnectSocketDirectly(proxy, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
// do socks negotiation
|
||||
switch (proxy.second) {
|
||||
case 4:
|
||||
if (!Socks4(addrDest, hSocket))
|
||||
return false;
|
||||
break;
|
||||
case 5:
|
||||
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
closesocket(hSocket);
|
||||
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
|
||||
return false;
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
|
@ -507,30 +446,25 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
|
|||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
|
||||
proxyType nameproxy;
|
||||
GetNameProxy(nameproxy);
|
||||
CService nameProxy;
|
||||
GetNameProxy(nameProxy);
|
||||
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port);
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port);
|
||||
if (addrResolved.IsValid()) {
|
||||
addr = addrResolved;
|
||||
return ConnectSocket(addr, hSocketRet, nTimeout);
|
||||
}
|
||||
addr = CService("0.0.0.0:0");
|
||||
if (!nameproxy.second)
|
||||
return false;
|
||||
if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
switch(nameproxy.second) {
|
||||
default:
|
||||
case 4:
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
case 5:
|
||||
if (!Socks5(strDest, port, hSocket))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
addr = CService("0.0.0.0:0");
|
||||
|
||||
if (!HaveNameProxy())
|
||||
return false;
|
||||
// first connect to name proxy server
|
||||
if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout))
|
||||
return false;
|
||||
// do socks negotiation
|
||||
if (!Socks5(strDest, (unsigned short)port, hSocket))
|
||||
return false;
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
|
@ -1270,3 +1204,16 @@ std::string NetworkErrorString(int err)
|
|||
return strprintf("%s (%d)", s, err);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CloseSocket(SOCKET& hSocket)
|
||||
{
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return false;
|
||||
#ifdef WIN32
|
||||
int ret = closesocket(hSocket);
|
||||
#else
|
||||
int ret = close(hSocket);
|
||||
#endif
|
||||
hSocket = INVALID_SOCKET;
|
||||
return ret != SOCKET_ERROR;
|
||||
}
|
||||
|
|
|
@ -163,14 +163,14 @@ class CService : public CNetAddr
|
|||
)
|
||||
};
|
||||
|
||||
typedef std::pair<CService, int> proxyType;
|
||||
typedef CService proxyType;
|
||||
|
||||
enum Network ParseNetwork(std::string net);
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
|
||||
bool SetProxy(enum Network net, CService addrProxy);
|
||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
||||
bool IsProxy(const CNetAddr &addr);
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
|
||||
bool SetNameProxy(CService addrProxy);
|
||||
bool HaveNameProxy();
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0);
|
||||
|
@ -181,5 +181,7 @@ bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nCon
|
|||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
|
||||
/** Return readable error string for a network error code */
|
||||
std::string NetworkErrorString(int err);
|
||||
/** Close socket and set hSocket to INVALID_SOCKET */
|
||||
bool CloseSocket(SOCKET& hSocket);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -318,26 +318,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="socksVersionLabel">
|
||||
<property name="text">
|
||||
<string>SOCKS &Version:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>socksVersion</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QValueComboBox" name="socksVersion">
|
||||
<property name="toolTip">
|
||||
<string>SOCKS version of the proxy (e.g. 5)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_1_Network">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -49,15 +49,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
|
|||
ui->proxyPort->setEnabled(false);
|
||||
ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));
|
||||
|
||||
/** SOCKS version is only selectable for default proxy and is always 5 for IPv6 and Tor */
|
||||
ui->socksVersion->setEnabled(false);
|
||||
ui->socksVersion->addItem("5", 5);
|
||||
ui->socksVersion->addItem("4", 4);
|
||||
ui->socksVersion->setCurrentIndex(0);
|
||||
|
||||
connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool)));
|
||||
connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool)));
|
||||
connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool)));
|
||||
|
||||
ui->proxyIp->installEventFilter(this);
|
||||
|
||||
|
@ -175,7 +168,6 @@ void OptionsDialog::setMapper()
|
|||
mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
|
||||
mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
|
||||
mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);
|
||||
mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion);
|
||||
|
||||
/* Window */
|
||||
#ifndef Q_OS_MAC
|
||||
|
|
|
@ -123,11 +123,6 @@ void OptionsModel::Init()
|
|||
// Only try to set -proxy, if user has enabled fUseProxy
|
||||
if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()))
|
||||
addOverriddenOption("-proxy");
|
||||
if (!settings.contains("nSocksVersion"))
|
||||
settings.setValue("nSocksVersion", 5);
|
||||
// Only try to set -socks, if user has enabled fUseProxy
|
||||
if (settings.value("fUseProxy").toBool() && !SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString()))
|
||||
addOverriddenOption("-socks");
|
||||
|
||||
// Display
|
||||
if (!settings.contains("language"))
|
||||
|
@ -189,8 +184,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
|
|||
QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
|
||||
return strlIpPort.at(1);
|
||||
}
|
||||
case ProxySocksVersion:
|
||||
return settings.value("nSocksVersion", 5);
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
case Fee:
|
||||
|
@ -282,13 +275,6 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
|
|||
}
|
||||
}
|
||||
break;
|
||||
case ProxySocksVersion: {
|
||||
if (settings.value("nSocksVersion") != value) {
|
||||
settings.setValue("nSocksVersion", value.toInt());
|
||||
setRestartRequired(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef ENABLE_WALLET
|
||||
case Fee: // core option - can be changed on-the-fly
|
||||
// Todo: Add is valid check and warn via message, if not
|
||||
|
@ -357,20 +343,16 @@ bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
|
|||
// GUI settings can be overridden with -proxy.
|
||||
proxyType curProxy;
|
||||
if (GetProxy(NET_IPV4, curProxy)) {
|
||||
if (curProxy.second == 5) {
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
proxy.setHostName(QString::fromStdString(curProxy.first.ToStringIP()));
|
||||
proxy.setPort(curProxy.first.GetPort());
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
proxy.setHostName(QString::fromStdString(curProxy.ToStringIP()));
|
||||
proxy.setPort(curProxy.GetPort());
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
proxy.setType(QNetworkProxy::NoProxy);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void OptionsModel::setRestartRequired(bool fRequired)
|
||||
|
|
|
@ -345,20 +345,14 @@ void PaymentServer::initNetManager()
|
|||
|
||||
QNetworkProxy proxy;
|
||||
|
||||
// Query active proxy (fails if no SOCKS5 proxy)
|
||||
// Query active SOCKS5 proxy
|
||||
if (optionsModel->getProxySettings(proxy)) {
|
||||
if (proxy.type() == QNetworkProxy::Socks5Proxy) {
|
||||
netManager->setProxy(proxy);
|
||||
netManager->setProxy(proxy);
|
||||
|
||||
qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
|
||||
}
|
||||
else
|
||||
qDebug() << "PaymentServer::initNetManager : No active proxy server found.";
|
||||
qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
|
||||
}
|
||||
else
|
||||
emit message(tr("Net manager warning"),
|
||||
tr("Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy."),
|
||||
CClientUIInterface::MSG_WARNING);
|
||||
qDebug() << "PaymentServer::initNetManager : No active proxy server found.";
|
||||
|
||||
connect(netManager, SIGNAL(finished(QNetworkReply*)),
|
||||
this, SLOT(netRequestFinished(QNetworkReply*)));
|
||||
|
|
|
@ -71,7 +71,7 @@ Value getinfo(const Array& params, bool fHelp)
|
|||
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
||||
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("testnet", TestNet()));
|
||||
#ifdef ENABLE_WALLET
|
||||
|
|
|
@ -134,8 +134,8 @@ Value getpeerinfo(const Array& params, bool fHelp)
|
|||
if (fStateStats) {
|
||||
obj.push_back(Pair("banscore", statestats.nMisbehavior));
|
||||
}
|
||||
if (stats.fSyncNode)
|
||||
obj.push_back(Pair("syncnode", true));
|
||||
obj.push_back(Pair("syncnode", stats.fSyncNode));
|
||||
obj.push_back(Pair("whitelisted", stats.fWhitelisted));
|
||||
|
||||
ret.push_back(obj);
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
|
|||
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee)));
|
||||
Array localAddresses;
|
||||
{
|
||||
|
|
|
@ -831,6 +831,35 @@ struct ser_streamplaceholder
|
|||
|
||||
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
|
||||
|
||||
class CSizeComputer
|
||||
{
|
||||
protected:
|
||||
size_t nSize;
|
||||
|
||||
public:
|
||||
int nType;
|
||||
int nVersion;
|
||||
|
||||
CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
|
||||
|
||||
CSizeComputer& write(const char *psz, int nSize)
|
||||
{
|
||||
this->nSize += nSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CSizeComputer& operator<<(const T& obj)
|
||||
{
|
||||
::Serialize(*this, obj, nType, nVersion);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return nSize;
|
||||
}
|
||||
};
|
||||
|
||||
/** Double ended buffer combining vector and stream-like interfaces.
|
||||
*
|
||||
* >> and << read and write unformatted data using the above serialization templates.
|
||||
|
|
|
@ -97,7 +97,6 @@ bool fDaemon = false;
|
|||
bool fServer = false;
|
||||
string strMiscWarning;
|
||||
bool fBloomFilters = true;
|
||||
bool fNoListen = false;
|
||||
bool fLogTimestamps = false;
|
||||
volatile bool fReopenDebugLog = false;
|
||||
CClientUIInterface uiInterface;
|
||||
|
|
|
@ -115,7 +115,6 @@ extern bool fPrintToDebugLog;
|
|||
extern bool fServer;
|
||||
extern std::string strMiscWarning;
|
||||
extern bool fBloomFilters;
|
||||
extern bool fNoListen;
|
||||
extern bool fLogTimestamps;
|
||||
extern volatile bool fReopenDebugLog;
|
||||
|
||||
|
|
Loading…
Reference in a new issue