Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 785 Lines • ▼ Show 20 Lines | struct NodeEvictionCandidate { | ||||
int64_t nMinPingUsecTime; | int64_t nMinPingUsecTime; | ||||
int64_t nLastBlockTime; | int64_t nLastBlockTime; | ||||
int64_t nLastTXTime; | int64_t nLastTXTime; | ||||
bool fRelevantServices; | bool fRelevantServices; | ||||
bool fRelayTxes; | bool fRelayTxes; | ||||
bool fBloomFilter; | bool fBloomFilter; | ||||
CAddress addr; | CAddress addr; | ||||
uint64_t nKeyedNetGroup; | uint64_t nKeyedNetGroup; | ||||
bool prefer_evict; | |||||
}; | }; | ||||
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, | static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, | ||||
const NodeEvictionCandidate &b) { | const NodeEvictionCandidate &b) { | ||||
return a.nMinPingUsecTime > b.nMinPingUsecTime; | return a.nMinPingUsecTime > b.nMinPingUsecTime; | ||||
} | } | ||||
static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, | static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | std::vector<NodeEvictionCandidate> vEvictionCandidates; | ||||
node->nTimeConnected, | node->nTimeConnected, | ||||
node->nMinPingUsecTime, | node->nMinPingUsecTime, | ||||
node->nLastBlockTime, | node->nLastBlockTime, | ||||
node->nLastTXTime, | node->nLastTXTime, | ||||
HasAllDesirableServiceFlags(node->nServices), | HasAllDesirableServiceFlags(node->nServices), | ||||
node->fRelayTxes, | node->fRelayTxes, | ||||
node->pfilter != nullptr, | node->pfilter != nullptr, | ||||
node->addr, | node->addr, | ||||
node->nKeyedNetGroup}; | node->nKeyedNetGroup, | ||||
node->m_prefer_evict}; | |||||
vEvictionCandidates.push_back(candidate); | vEvictionCandidates.push_back(candidate); | ||||
} | } | ||||
} | } | ||||
// Protect connections with certain characteristics | // Protect connections with certain characteristics | ||||
// Deterministically select 4 peers to protect by netgroup. | // Deterministically select 4 peers to protect by netgroup. | ||||
// An attacker cannot predict which netgroups will be protected | // An attacker cannot predict which netgroups will be protected | ||||
Show All 13 Lines | bool CConnman::AttemptToEvictConnection() { | ||||
// precludes attacks that start later. | // precludes attacks that start later. | ||||
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, | EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, | ||||
vEvictionCandidates.size() / 2); | vEvictionCandidates.size() / 2); | ||||
if (vEvictionCandidates.empty()) { | if (vEvictionCandidates.empty()) { | ||||
return false; | return false; | ||||
} | } | ||||
// If any remaining peers are preferred for eviction consider only them. | |||||
// This happens after the other preferences since if a peer is really the | |||||
// best by other criteria (esp relaying blocks) | |||||
// then we probably don't want to evict it no matter what. | |||||
if (std::any_of( | |||||
vEvictionCandidates.begin(), vEvictionCandidates.end(), | |||||
[](NodeEvictionCandidate const &n) { return n.prefer_evict; })) { | |||||
vEvictionCandidates.erase( | |||||
std::remove_if( | |||||
vEvictionCandidates.begin(), vEvictionCandidates.end(), | |||||
[](NodeEvictionCandidate const &n) { return !n.prefer_evict; }), | |||||
vEvictionCandidates.end()); | |||||
} | |||||
// Identify the network group with the most connections and youngest member. | // Identify the network group with the most connections and youngest member. | ||||
// (vEvictionCandidates is already sorted by reverse connect time) | // (vEvictionCandidates is already sorted by reverse connect time) | ||||
uint64_t naMostConnections; | uint64_t naMostConnections; | ||||
unsigned int nMostConnections = 0; | unsigned int nMostConnections = 0; | ||||
int64_t nMostConnectionsTime = 0; | int64_t nMostConnectionsTime = 0; | ||||
std::map<uint64_t, std::vector<NodeEvictionCandidate>> mapNetGroupNodes; | std::map<uint64_t, std::vector<NodeEvictionCandidate>> mapNetGroupNodes; | ||||
for (const NodeEvictionCandidate &node : vEvictionCandidates) { | for (const NodeEvictionCandidate &node : vEvictionCandidates) { | ||||
std::vector<NodeEvictionCandidate> &group = | std::vector<NodeEvictionCandidate> &group = | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | if (!IsSelectableSocket(hSocket)) { | ||||
CloseSocket(hSocket); | CloseSocket(hSocket); | ||||
return; | return; | ||||
} | } | ||||
// According to the internet TCP_NODELAY is not carried into accepted | // According to the internet TCP_NODELAY is not carried into accepted | ||||
// sockets on all platforms. Set it again here just to be sure. | // sockets on all platforms. Set it again here just to be sure. | ||||
SetSocketNoDelay(hSocket); | SetSocketNoDelay(hSocket); | ||||
if (m_banman && m_banman->IsBanned(addr) && !whitelisted) { | int bannedlevel = m_banman ? m_banman->IsBannedLevel(addr) : 0; | ||||
// Don't accept connections from banned peers, but if our inbound slots | |||||
// aren't almost full, accept if the only banning reason was an automatic | |||||
// misbehavior ban. | |||||
if (!whitelisted && bannedlevel > ((nInbound + 1 < nMaxInbound) ? 1 : 0)) { | |||||
LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", | LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", | ||||
addr.ToString()); | addr.ToString()); | ||||
CloseSocket(hSocket); | CloseSocket(hSocket); | ||||
return; | return; | ||||
} | } | ||||
if (nInbound >= nMaxInbound) { | if (nInbound >= nMaxInbound) { | ||||
if (!AttemptToEvictConnection()) { | if (!AttemptToEvictConnection()) { | ||||
Show All 11 Lines | uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE) | ||||
.Finalize(); | .Finalize(); | ||||
CAddress addr_bind = GetBindAddress(hSocket); | CAddress addr_bind = GetBindAddress(hSocket); | ||||
CNode *pnode = | CNode *pnode = | ||||
new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, | new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, | ||||
CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true); | CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true); | ||||
pnode->AddRef(); | pnode->AddRef(); | ||||
pnode->fWhitelisted = whitelisted; | pnode->fWhitelisted = whitelisted; | ||||
pnode->m_prefer_evict = bannedlevel > 0; | |||||
m_msgproc->InitializeNode(*config, pnode); | m_msgproc->InitializeNode(*config, pnode); | ||||
LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString()); | LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString()); | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
vNodes.push_back(pnode); | vNodes.push_back(pnode); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,784 Lines • Show Last 20 Lines |