// Returns the number of entries processed int CAddrMan::CopyDestinationStats( std::vector<CDestinationStats>& vStats ) { int nSize = 0; vStats.clear(); vStats.reserve( mapI2pHashes.size() ); for( std::map<uint256, int>::iterator it = mapI2pHashes.begin(); it != mapI2pHashes.end(); it++) { CDestinationStats stats; std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second); if (it2 != mapInfo.end()) { CAddrInfo* paddr = &(*it2).second; stats.sAddress = paddr->ToString(); stats.fInTried = paddr->fInTried; stats.uPort = paddr->GetPort(); stats.nServices = paddr->nServices; stats.nAttempts = paddr->nAttempts; stats.nLastTry = paddr->nLastTry; stats.nSuccessTime = paddr->nLastSuccess; stats.sSource = paddr->source.ToString(); stats.sBase64 = paddr->GetI2pDestination(); nSize++; vStats.push_back( stats ); } } assert( mapI2pHashes.size() == nSize ); return nSize; }
bool CAddrMan::Add_(const CAddress& addrIn, const CNetAddr& source, int64_t nTimePenalty) { #ifdef I2PADDRMAN_EXTENSIONS //! We now need to check for an possibly modify the CAddress object for the garliccat field, so we make a local copy CAddress addr = addrIn; /** * Before we can add an address, even before we can test if its Routable, or use the Find command to match correctly, * we need to make sure that any I2P addresses have the GarlicCat field setup correctly in the IP area of the * CNetAddr portion of a given CAddress->CService->CNetAddr object, this should have already been done, but * double checking it here also insures we do not get a polluted b32 hash map */ if( addr.CheckAndSetGarlicCat() ) LogPrint( "addrman", "While adding an i2p destination, did not expect to need the garliccat fixed for %s\n", addr.ToString() ); #endif if( !addr.IsRoutable() ) { LogPrint( "addrman", "While adding an address, did not expect to find it unroutable: %s\n", addr.ToString() ); return false; } bool fNew = false; int nId; /** * Find Matches by CNetAddr objects, and returns the CAddrInfo object it finds, which is fine and what we want normally * however this means the ports can be different (CService), and other details in the CAddress portion, such as nServices * should not simply be 'or'd with what was found, sometimes we have to remove services in the version exchange that * peers report incorrectly, and having the port wrong means when Good_ is called that the objects do not match exactly. */ CAddrInfo* pinfo = Find(addr, &nId); if (pinfo) { // periodically update nTime bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty)) pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty); /** * Only do the following, IF the source of this information is the node itself (source), * otherwise we're just constantly changing the details, while getting addresses from peers. * * The call (to addrman.Add()) which puts us here, happens at the end of a version message exchange, * for inbound connections only. * For outbound connections, we only have a call to good, if the connection is made. * Other places addrman.Add() is called is for address seeding and user lookup, see net.cpp for those details */ if( (CNetAddr)addr == source ) { /** * add services, don't just 'or' them in here, hard set them to the correct value * original code: pinfo->nServices |= addr.nServices; * ToDo: Why this and the port value has not been fixed as standard procedure could be investigated in more detail * for now Anoncoin has so many unique problems with these 2 values, this should help correct allot of the * current network issues in regard to the values getting corrected over time. */ if( pinfo->nServices != addr.nServices ) { LogPrint( "addrman", "Updating peer record %s, the services listed needed to be changed. From 0x%016x To 0x%016x\n", pinfo->ToString(), pinfo->nServices, addr.nServices ); pinfo->nServices = addr.nServices; } if( pinfo->GetPort() != addr.GetPort() ) { LogPrint( "addrman", "Updating peer record %s, port %d was wrong, changed it to %d\n", pinfo->ToString(), pinfo->GetPort(), addr.GetPort() ); pinfo->SetPort( addr.GetPort() ); } } // do not update if no new information is present if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime)) return false; // do not update if the entry was already in the "tried" table if (pinfo->fInTried) return false; // do not update if the max reference count is reached if (pinfo->nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS) return false; // stochastic test: previous nRefCount == N: 2^N times harder to increase it int nFactor = 1; for (int n = 0; n < pinfo->nRefCount; n++) nFactor *= 2; if (nFactor > 1 && (GetRandInt(nFactor) != 0)) return false; } else { pinfo = Create(addr, source, &nId); pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty); nNew++; fNew = true; } int nUBucket = pinfo->GetNewBucket(nKey, source); 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; }