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