| 4325 | } |
| 4326 | |
| 4327 | void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now) |
| 4328 | { |
| 4329 | // If we have any extra block-relay-only peers, disconnect the youngest unless |
| 4330 | // it's given us a block -- in which case, compare with the second-youngest, and |
| 4331 | // out of those two, disconnect the peer who least recently gave us a block. |
| 4332 | // The youngest block-relay-only peer would be the extra peer we connected |
| 4333 | // to temporarily in order to sync our tip; see net.cpp. |
| 4334 | // Note that we use higher nodeid as a measure for most recent connection. |
| 4335 | if (m_connman.GetExtraBlockRelayCount() > 0) { |
| 4336 | std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0}; |
| 4337 | |
| 4338 | m_connman.ForEachNode([&](CNode* pnode) { |
| 4339 | if (!pnode->IsBlockOnlyConn() || pnode->fDisconnect) return; |
| 4340 | if (pnode->GetId() > youngest_peer.first) { |
| 4341 | next_youngest_peer = youngest_peer; |
| 4342 | youngest_peer.first = pnode->GetId(); |
| 4343 | youngest_peer.second = pnode->m_last_block_time; |
| 4344 | } |
| 4345 | }); |
| 4346 | NodeId to_disconnect = youngest_peer.first; |
| 4347 | if (youngest_peer.second > next_youngest_peer.second) { |
| 4348 | // Our newest block-relay-only peer gave us a block more recently; |
| 4349 | // disconnect our second youngest. |
| 4350 | to_disconnect = next_youngest_peer.first; |
| 4351 | } |
| 4352 | m_connman.ForNode(to_disconnect, [&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { |
| 4353 | AssertLockHeld(::cs_main); |
| 4354 | // Make sure we're not getting a block right now, and that |
| 4355 | // we've been connected long enough for this eviction to happen |
| 4356 | // at all. |
| 4357 | // Note that we only request blocks from a peer if we learn of a |
| 4358 | // valid headers chain with at least as much work as our tip. |
| 4359 | CNodeState *node_state = State(pnode->GetId()); |
| 4360 | if (node_state == nullptr || |
| 4361 | (now - pnode->m_connected >= MINIMUM_CONNECT_TIME && node_state->nBlocksInFlight == 0)) { |
| 4362 | pnode->fDisconnect = true; |
| 4363 | LogPrint(BCLog::NET, "disconnecting extra block-relay-only peer=%d (last block received at time %d)\n", |
| 4364 | pnode->GetId(), count_seconds(pnode->m_last_block_time)); |
| 4365 | return true; |
| 4366 | } else { |
| 4367 | LogPrint(BCLog::NET, "keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n", |
| 4368 | pnode->GetId(), count_seconds(pnode->m_connected), node_state->nBlocksInFlight); |
| 4369 | } |
| 4370 | return false; |
| 4371 | }); |
| 4372 | } |
| 4373 | |
| 4374 | // Check whether we have too many outbound-full-relay peers |
| 4375 | if (m_connman.GetExtraFullOutboundCount() > 0) { |
| 4376 | // If we have more outbound-full-relay peers than we target, disconnect one. |
| 4377 | // Pick the outbound-full-relay peer that least recently announced |
| 4378 | // us a new block, with ties broken by choosing the more recent |
| 4379 | // connection (higher node id) |
| 4380 | NodeId worst_peer = -1; |
| 4381 | int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max(); |
| 4382 | |
| 4383 | m_connman.ForEachNode([&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { |
| 4384 | AssertLockHeld(::cs_main); |
nothing calls this directly
no test coverage detected