Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 2,062 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
// Return the number of peers we have over our outbound connection limit. | // Return the number of peers we have over our outbound connection limit. | ||||
// Exclude peers that are marked for disconnect, or are going to be disconnected | // Exclude peers that are marked for disconnect, or are going to be disconnected | ||||
// soon (eg ADDR_FETCH and FEELER). | // soon (eg ADDR_FETCH and FEELER). | ||||
// Also exclude peers that haven't finished initial connection handshake yet (so | // Also exclude peers that haven't finished initial connection handshake yet (so | ||||
// that we don't decide we're over our desired connection limit, and then evict | // that we don't decide we're over our desired connection limit, and then evict | ||||
// some peer that has finished the handshake). | // some peer that has finished the handshake). | ||||
int CConnman::GetExtraOutboundCount() { | int CConnman::GetExtraFullOutboundCount() { | ||||
int nOutbound = 0; | int full_outbound_peers = 0; | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (const CNode *pnode : vNodes) { | for (const CNode *pnode : vNodes) { | ||||
if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && | if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && | ||||
pnode->IsOutboundOrBlockRelayConn()) { | pnode->IsFullOutboundConn()) { | ||||
++nOutbound; | ++full_outbound_peers; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return std::max( | return std::max(full_outbound_peers - m_max_outbound_full_relay, 0); | ||||
nOutbound - m_max_outbound_full_relay - m_max_outbound_block_relay, 0); | } | ||||
int CConnman::GetExtraBlockRelayCount() { | |||||
int block_relay_peers = 0; | |||||
{ | |||||
LOCK(cs_vNodes); | |||||
for (const CNode *pnode : vNodes) { | |||||
if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && | |||||
pnode->IsBlockOnlyConn()) { | |||||
++block_relay_peers; | |||||
} | |||||
} | |||||
} | |||||
return std::max(block_relay_peers - m_max_outbound_block_relay, 0); | |||||
} | } | ||||
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) { | void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) { | ||||
// Connect to specific addresses | // Connect to specific addresses | ||||
if (!connect.empty()) { | if (!connect.empty()) { | ||||
for (int64_t nLoop = 0;; nLoop++) { | for (int64_t nLoop = 0;; nLoop++) { | ||||
ProcessAddrFetch(); | ProcessAddrFetch(); | ||||
for (const std::string &strAddr : connect) { | for (const std::string &strAddr : connect) { | ||||
Show All 14 Lines | void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) { | ||||
} | } | ||||
// Initiate network connections | // Initiate network connections | ||||
int64_t nStart = GetTime(); | int64_t nStart = GetTime(); | ||||
// Minimum time before next feeler connection (in microseconds). | // Minimum time before next feeler connection (in microseconds). | ||||
int64_t nNextFeeler = | int64_t nNextFeeler = | ||||
PoissonNextSend(nStart * 1000 * 1000, FEELER_INTERVAL); | PoissonNextSend(nStart * 1000 * 1000, FEELER_INTERVAL); | ||||
int64_t nNextExtraBlockRelay = PoissonNextSend( | |||||
nStart * 1000 * 1000, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL); | |||||
while (!interruptNet) { | while (!interruptNet) { | ||||
ProcessAddrFetch(); | ProcessAddrFetch(); | ||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) { | if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) { | ||||
return; | return; | ||||
} | } | ||||
CSemaphoreGrant grant(*semOutbound); | CSemaphoreGrant grant(*semOutbound); | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | while (!interruptNet) { | ||||
// Determine what type of connection to open. Opening | // Determine what type of connection to open. Opening | ||||
// BLOCK_RELAY connections to addresses from anchors.dat gets the | // BLOCK_RELAY connections to addresses from anchors.dat gets the | ||||
// highest priority. Then we open OUTBOUND_FULL_RELAY priority until we | // highest priority. Then we open OUTBOUND_FULL_RELAY priority until we | ||||
// meet our full-relay capacity. Then we open BLOCK_RELAY connection | // meet our full-relay capacity. Then we open BLOCK_RELAY connection | ||||
// until we hit our block-relay-only peer limit. | // until we hit our block-relay-only peer limit. | ||||
// GetTryNewOutboundPeer() gets set when a stale tip is detected, so we | // GetTryNewOutboundPeer() gets set when a stale tip is detected, so we | ||||
// try opening an additional OUTBOUND_FULL_RELAY connection. If none of | // try opening an additional OUTBOUND_FULL_RELAY connection. If none of | ||||
// these conditions are met, check the nNextFeeler timer to decide if | // these conditions are met, check to see if it's time to try an extra | ||||
// we should open a FEELER. | // block-relay-only peer (to confirm our tip is current, see below) or | ||||
// the nNextFeeler timer to decide if we should open a FEELER. | |||||
if (!m_anchors.empty() && | if (!m_anchors.empty() && | ||||
(nOutboundBlockRelay < m_max_outbound_block_relay)) { | (nOutboundBlockRelay < m_max_outbound_block_relay)) { | ||||
conn_type = ConnectionType::BLOCK_RELAY; | conn_type = ConnectionType::BLOCK_RELAY; | ||||
anchor = true; | anchor = true; | ||||
} else if (nOutboundFullRelay < m_max_outbound_full_relay) { | } else if (nOutboundFullRelay < m_max_outbound_full_relay) { | ||||
// OUTBOUND_FULL_RELAY | // OUTBOUND_FULL_RELAY | ||||
} else if (nOutboundBlockRelay < m_max_outbound_block_relay) { | } else if (nOutboundBlockRelay < m_max_outbound_block_relay) { | ||||
conn_type = ConnectionType::BLOCK_RELAY; | conn_type = ConnectionType::BLOCK_RELAY; | ||||
} else if (GetTryNewOutboundPeer()) { | } else if (GetTryNewOutboundPeer()) { | ||||
// OUTBOUND_FULL_RELAY | // OUTBOUND_FULL_RELAY | ||||
} else if (nTime > nNextExtraBlockRelay && | |||||
m_start_extra_block_relay_peers) { | |||||
// Periodically connect to a peer (using regular outbound selection | |||||
// methodology from addrman) and stay connected long enough to sync | |||||
// headers, but not much else. | |||||
// | |||||
// Then disconnect the peer, if we haven't learned anything new. | |||||
// | |||||
// The idea is to make eclipse attacks very difficult to pull off, | |||||
// because every few minutes we're finding a new peer to learn | |||||
// headers from. | |||||
// | |||||
// This is similar to the logic for trying extra outbound | |||||
// (full-relay) peers, except: | |||||
// - we do this all the time on a poisson timer, rather than just | |||||
// when our tip is stale | |||||
// - we potentially disconnect our next-youngest block-relay-only | |||||
// peer, if our newest block-relay-only peer delivers a block more | |||||
// recently. | |||||
// See the eviction logic in net_processing.cpp. | |||||
// | |||||
// Because we can promote these connections to block-relay-only | |||||
// connections, they do not get their own ConnectionType enum | |||||
// (similar to how we deal with extra outbound peers). | |||||
nNextExtraBlockRelay = | |||||
PoissonNextSend(nTime, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL); | |||||
conn_type = ConnectionType::BLOCK_RELAY; | |||||
} else if (nTime > nNextFeeler) { | } else if (nTime > nNextFeeler) { | ||||
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL); | nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL); | ||||
conn_type = ConnectionType::FEELER; | conn_type = ConnectionType::FEELER; | ||||
fFeeler = true; | fFeeler = true; | ||||
} else { | } else { | ||||
// skip to next iteration of while loop | // skip to next iteration of while loop | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,251 Lines • Show Last 20 Lines |