| 252 | } |
| 253 | |
| 254 | bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) |
| 255 | { |
| 256 | if (!addr.IsRoutable()) |
| 257 | return false; |
| 258 | |
| 259 | bool fNew = false; |
| 260 | int nId; |
| 261 | CAddrInfo* pinfo = Find(addr, &nId); |
| 262 | |
| 263 | // Do not set a penalty for a source's self-announcement |
| 264 | if (addr == source) { |
| 265 | nTimePenalty = 0; |
| 266 | } |
| 267 | |
| 268 | if (pinfo) { |
| 269 | // periodically update nTime |
| 270 | bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); |
| 271 | int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); |
| 272 | if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty)) |
| 273 | pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty); |
| 274 | |
| 275 | // add services |
| 276 | pinfo->nServices = ServiceFlags(pinfo->nServices | addr.nServices); |
| 277 | |
| 278 | // do not update if no new information is present |
| 279 | if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime)) |
| 280 | return false; |
| 281 | |
| 282 | // do not update if the entry was already in the "tried" table |
| 283 | if (pinfo->fInTried) |
| 284 | return false; |
| 285 | |
| 286 | // do not update if the max reference count is reached |
| 287 | if (pinfo->nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS) |
| 288 | return false; |
| 289 | |
| 290 | // stochastic test: previous nRefCount == N: 2^N times harder to increase it |
| 291 | int nFactor = 1; |
| 292 | for (int n = 0; n < pinfo->nRefCount; n++) |
| 293 | nFactor *= 2; |
| 294 | if (nFactor > 1 && (RandomInt(nFactor) != 0)) |
| 295 | return false; |
| 296 | } else { |
| 297 | pinfo = Create(addr, source, &nId); |
| 298 | pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty); |
| 299 | nNew++; |
| 300 | fNew = true; |
| 301 | } |
| 302 | |
| 303 | int nUBucket = pinfo->GetNewBucket(nKey, source); |
| 304 | int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket); |
| 305 | if (vvNew[nUBucket][nUBucketPos] != nId) { |
| 306 | bool fInsert = vvNew[nUBucket][nUBucketPos] == -1; |
| 307 | if (!fInsert) { |
| 308 | CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]]; |
| 309 | if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) { |
| 310 | // Overwrite the existing new table entry. |
| 311 | fInsert = true; |
nothing calls this directly
no test coverage detected