6 #if defined(HAVE_CONFIG_H)
7 #include <config/bitcoin-config.h>
54 #include <unordered_map>
60 "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed "
61 "MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
93 #define FEELER_SLEEP_WINDOW 1
127 std::map<CNetAddr, LocalServiceInfo>
133 m_addr_fetches.push_back(strDest);
139 for (
const std::string &bind_arg :
gArgs.
GetArgs(
"-bind")) {
141 constexpr uint16_t dummy_port = 0;
143 if (
Lookup(bind_arg, bind_addr, dummy_port,
false)) {
144 if (bind_addr.
GetPort() != dummy_port) {
153 for (
const std::string &whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
167 return static_cast<uint16_t
>(
178 int nBestReachability = -1;
181 for (
const auto &entry : mapLocalHost) {
182 int nScore = entry.second.nScore;
183 int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
184 if (nReachability > nBestReachability ||
185 (nReachability == nBestReachability && nScore > nBestScore)) {
186 addr =
CService(entry.first, entry.second.nPort);
187 nBestReachability = nReachability;
192 return nBestScore >= 0;
196 static std::vector<CAddress>
201 const auto one_week{7 * 24h};
202 std::vector<CAddress> vSeedsOut;
203 vSeedsOut.reserve(vSeedsIn.size());
205 for (
const auto &seed_in : vSeedsIn) {
207 memcpy(&ip, seed_in.addr,
sizeof(ip));
212 vSeedsOut.push_back(addr);
231 const auto it = mapLocalHost.find(addr);
232 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
253 (!addrLocal.IsRoutable() ||
255 if (
node.IsInboundConn()) {
264 addrLocal.SetIP(
node.GetAddrLocal());
267 if (addrLocal.IsRoutable() ||
gArgs.
GetBoolArg(
"-addrmantest",
false)) {
269 addrLocal.ToString(),
node.GetId());
294 const auto [it, is_newly_added] =
297 if (is_newly_added || nScore >= info.
nScore) {
298 info.
nScore = nScore + !is_newly_added;
313 mapLocalHost.erase(addr);
321 vfLimited[net] = !reachable;
326 return !vfLimited[net];
336 const auto it = mapLocalHost.find(addr);
337 if (it == mapLocalHost.end()) {
347 return mapLocalHost.count(addr) > 0;
352 for (
CNode *pnode : m_nodes) {
353 if (
static_cast<CNetAddr>(pnode->addr) == ip) {
362 for (
CNode *pnode : m_nodes) {
372 for (
CNode *pnode : m_nodes) {
373 if (pnode->m_addr_name == addrName) {
382 for (
CNode *pnode : m_nodes) {
383 if (
static_cast<CService>(pnode->addr) == addr) {
397 for (
const CNode *pnode : m_nodes) {
398 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() &&
399 pnode->GetLocalNonce() == nonce) {
409 struct sockaddr_storage sockaddr_bind;
410 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
412 if (!getsockname(sock, (
struct sockaddr *)&sockaddr_bind,
413 &sockaddr_bind_len)) {
414 addr_bind.
SetSockAddr((
const struct sockaddr *)&sockaddr_bind);
426 if (pszDest ==
nullptr) {
434 LogPrintf(
"Failed to open new connection, already connected\n");
440 BCLog::NET,
"trying connection %s lastseen=%.1fhrs\n",
441 pszDest ? pszDest : addrConnect.
ToString(),
445 const uint16_t default_port{pszDest !=
nullptr
449 std::vector<CService> resolved;
450 if (
Lookup(pszDest, resolved, default_port,
457 "Resolver returned invalid address %s for %s\n",
467 LogPrintf(
"Failed to open new connection, already connected\n");
474 bool connected =
false;
475 std::unique_ptr<Sock> sock;
481 bool proxyConnectionFailed =
false;
487 proxyConnectionFailed)) {
489 sock = std::move(conn.
sock);
510 if (!proxyConnectionFailed) {
522 uint16_t port{default_port};
524 bool proxyConnectionFailed;
537 uint64_t extra_entropy =
546 nonce, extra_entropy, addr_bind, pszDest ? pszDest :
"", conn_type,
569 if (subnet.m_subnet.Match(addr)) {
584 return "outbound-full-relay";
586 return "block-relay-only";
605 if (addrLocal.IsValid()) {
606 error(
"Addr local already set for node: %i. Refusing to change from %s "
608 id, addrLocal.ToString(), addrLocalIn.
ToString());
610 addrLocal = addrLocalIn;
669 const auto time = GetTime<std::chrono::microseconds>();
671 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
672 nRecvBytes += msg_bytes.
size();
673 while (msg_bytes.
size() > 0) {
686 mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.
m_type);
687 if (i == mapRecvBytesPerMsgCmd.end()) {
691 assert(i != mapRecvBytesPerMsgCmd.end());
708 uint32_t nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
721 }
catch (
const std::exception &) {
739 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
764 const std::chrono::microseconds time) {
792 "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
808 std::vector<uint8_t> &header) {
823 size_t nSentSize = 0;
824 size_t nMsgCount = 0;
826 for (
const auto &data :
node.vSendMsg) {
838 reinterpret_cast<const char *
>(data.data()) +
node.nSendOffset,
854 node.CloseSocketDisconnect();
861 node.m_last_send = GetTime<std::chrono::seconds>();
862 node.nSendBytes += nBytes;
863 node.nSendOffset += nBytes;
865 if (
node.nSendOffset != data.size()) {
870 node.nSendOffset = 0;
871 node.nSendSize -= data.size();
876 node.vSendMsg.erase(
node.vSendMsg.begin(),
877 node.vSendMsg.begin() + nMsgCount);
879 if (
node.vSendMsg.empty()) {
1007 template <
typename T,
typename Comparator>
1009 std::vector<T> &
elements, Comparator comparator,
size_t k,
1013 size_t eraseSize = std::min(k,
elements.size());
1020 std::vector<NodeEvictionCandidate> &eviction_candidates) {
1029 const size_t initial_size = eviction_candidates.size();
1030 const size_t total_protect_size{initial_size / 2};
1040 std::array<Net, 3> networks{{{
false,
NET_I2P, 0},
1045 for (Net &n : networks) {
1046 n.count = std::count_if(
1047 eviction_candidates.cbegin(), eviction_candidates.cend(),
1049 return n.is_local ? c.m_is_local : c.m_network == n.id;
1055 std::stable_sort(networks.begin(), networks.end(),
1056 [](Net a, Net b) { return a.count < b.count; });
1059 const size_t max_protect_by_network{total_protect_size / 2};
1060 size_t num_protected{0};
1062 while (num_protected < max_protect_by_network) {
1065 auto num_networks = std::count_if(networks.begin(), networks.end(),
1066 [](
const Net &n) { return n.count; });
1067 if (num_networks == 0) {
1070 const size_t disadvantaged_to_protect{max_protect_by_network -
1072 const size_t protect_per_network{std::max(
1073 disadvantaged_to_protect / num_networks,
static_cast<size_t>(1))};
1077 bool protected_at_least_one{
false};
1079 for (Net &n : networks) {
1083 const size_t before = eviction_candidates.size();
1087 return n.is_local ? c.m_is_local : c.m_network == n.id;
1089 const size_t after = eviction_candidates.size();
1090 if (before > after) {
1091 protected_at_least_one =
true;
1092 const size_t delta{before - after};
1093 num_protected += delta;
1094 if (num_protected >= max_protect_by_network) {
1100 if (!protected_at_least_one) {
1107 assert(num_protected == initial_size - eviction_candidates.size());
1108 const size_t remaining_to_protect{total_protect_size - num_protected};
1110 remaining_to_protect);
1113 [[nodiscard]] std::optional<NodeId>
1155 if (vEvictionCandidates.empty()) {
1156 return std::nullopt;
1164 vEvictionCandidates.begin(), vEvictionCandidates.end(),
1166 vEvictionCandidates.erase(
1168 vEvictionCandidates.begin(), vEvictionCandidates.end(),
1170 vEvictionCandidates.end());
1175 uint64_t naMostConnections;
1176 unsigned int nMostConnections = 0;
1177 std::chrono::seconds nMostConnectionsTime{0};
1178 std::map<uint64_t, std::vector<NodeEvictionCandidate>> mapNetGroupNodes;
1180 std::vector<NodeEvictionCandidate> &group =
1181 mapNetGroupNodes[
node.nKeyedNetGroup];
1182 group.push_back(
node);
1183 const auto grouptime{group[0].m_connected};
1184 size_t group_size = group.size();
1185 if (group_size > nMostConnections ||
1186 (group_size == nMostConnections &&
1187 grouptime > nMostConnectionsTime)) {
1188 nMostConnections = group_size;
1189 nMostConnectionsTime = grouptime;
1190 naMostConnections =
node.nKeyedNetGroup;
1195 vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
1198 return vEvictionCandidates.front().id;
1210 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1217 if (!
node->IsInboundConn()) {
1220 if (
node->fDisconnect) {
1227 node->m_min_ping_time,
1228 node->m_last_block_time,
1229 node->m_last_proof_time,
1230 node->m_last_tx_time,
1231 node->m_has_all_wanted_services,
1232 node->m_relays_txs.load(),
1233 node->m_bloom_filter_loaded.load(),
1234 node->nKeyedNetGroup,
1235 node->m_prefer_evict,
1236 node->addr.IsLocal(),
1237 node->ConnectedThroughNetwork(),
1238 node->m_avalanche_enabled
1239 ?
node->getAvailabilityScore()
1240 : -std::numeric_limits<double>::infinity()};
1241 vEvictionCandidates.push_back(candidate);
1244 const std::optional<NodeId> node_id_to_evict =
1246 if (!node_id_to_evict) {
1250 for (
CNode *pnode : m_nodes) {
1251 if (pnode->GetId() == *node_id_to_evict) {
1254 "selected %s connection for eviction peer=%d; disconnecting\n",
1255 pnode->ConnectionTypeAsString(), pnode->GetId());
1256 pnode->fDisconnect =
true;
1264 struct sockaddr_storage sockaddr;
1265 socklen_t len =
sizeof(sockaddr);
1267 accept(hListenSocket.
socket, (
struct sockaddr *)&sockaddr, &len);
1273 LogPrintf(
"socket error accept failed: %s\n",
1279 if (!addr.
SetSockAddr((
const struct sockaddr *)&sockaddr)) {
1280 LogPrintf(
"Warning: Unknown socket family\n");
1317 for (
const CNode *pnode : m_nodes) {
1318 if (pnode->IsInboundConn()) {
1326 "connection from %s dropped: not accepting new connections\n",
1333 LogPrintf(
"connection from %s dropped: non-selectable socket\n",
1357 nInbound + 1 >= nMaxInbound && discouraged) {
1364 if (nInbound >= nMaxInbound) {
1368 "connection dropped (full)\n");
1378 uint64_t extra_entropy =
1389 const bool inbound_onion =
1393 nonce, extra_entropy, addr_bind,
"",
1399 interface->InitializeNode(*
config, *pnode, nodeServices);
1406 m_nodes.push_back(pnode);
1416 std::optional<int> max_connections;
1417 switch (conn_type) {
1439 int existing_connections =
1441 return std::count_if(
1442 m_nodes.begin(), m_nodes.end(), [conn_type](
CNode *
node) {
1443 return node->m_conn_type == conn_type;
1447 if (max_connections != std::nullopt &&
1448 existing_connections >= max_connections) {
1469 for (
CNode *pnode : m_nodes) {
1470 if (!pnode->fDisconnect) {
1472 "Network not active, dropping peer=%d\n",
1474 pnode->fDisconnect =
true;
1480 std::vector<CNode *> nodes_copy = m_nodes;
1481 for (
CNode *pnode : nodes_copy) {
1482 if (pnode->fDisconnect) {
1484 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode),
1488 pnode->grantOutbound.Release();
1491 pnode->CloseSocketDisconnect();
1502 for (
CNode *pnode : nodes_disconnected_copy) {
1505 if (pnode->GetRefCount() <= 0) {
1517 nodes_size = m_nodes.size();
1528 std::chrono::seconds now)
const {
1535 const auto now{GetTime<std::chrono::seconds>()};
1536 const auto last_send{
node.m_last_send.load()};
1537 const auto last_recv{
node.m_last_recv.load()};
1543 if (last_recv.count() == 0 || last_send.count() == 0) {
1545 "socket no message in first %i seconds, %d %d peer=%d\n",
1547 last_send.count() != 0,
node.GetId());
1563 if (!
node.fSuccessfullyConnected) {
1573 std::set<SOCKET> &send_set,
1574 std::set<SOCKET> &error_set) {
1576 recv_set.insert(hListenSocket.socket);
1581 for (
CNode *pnode : m_nodes) {
1594 bool select_recv = !pnode->fPauseRecv;
1597 LOCK(pnode->cs_vSend);
1598 select_send = !pnode->vSendMsg.empty();
1601 LOCK(pnode->cs_hSocket);
1606 error_set.insert(pnode->hSocket);
1608 send_set.insert(pnode->hSocket);
1612 recv_set.insert(pnode->hSocket);
1617 return !recv_set.empty() || !send_set.empty() || !error_set.empty();
1622 std::set<SOCKET> &send_set,
1623 std::set<SOCKET> &error_set) {
1624 std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
1626 error_select_set)) {
1632 std::unordered_map<SOCKET, struct pollfd> pollfds;
1633 for (
SOCKET socket_id : recv_select_set) {
1634 pollfds[socket_id].fd = socket_id;
1635 pollfds[socket_id].events |= POLLIN;
1638 for (
SOCKET socket_id : send_select_set) {
1639 pollfds[socket_id].fd = socket_id;
1640 pollfds[socket_id].events |= POLLOUT;
1643 for (
SOCKET socket_id : error_select_set) {
1644 pollfds[socket_id].fd = socket_id;
1646 pollfds[socket_id].events |= POLLERR | POLLHUP;
1649 std::vector<struct pollfd> vpollfds;
1650 vpollfds.reserve(pollfds.size());
1651 for (
auto it : pollfds) {
1652 vpollfds.push_back(std::move(it.second));
1664 for (
struct pollfd pollfd_entry : vpollfds) {
1665 if (pollfd_entry.revents & POLLIN) {
1666 recv_set.insert(pollfd_entry.fd);
1668 if (pollfd_entry.revents & POLLOUT) {
1669 send_set.insert(pollfd_entry.fd);
1671 if (pollfd_entry.revents & (POLLERR | POLLHUP)) {
1672 error_set.insert(pollfd_entry.fd);
1678 std::set<SOCKET> &send_set,
1679 std::set<SOCKET> &error_set) {
1680 std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
1682 error_select_set)) {
1691 struct timeval timeout;
1699 FD_ZERO(&fdsetRecv);
1700 FD_ZERO(&fdsetSend);
1701 FD_ZERO(&fdsetError);
1704 for (
SOCKET hSocket : recv_select_set) {
1705 FD_SET(hSocket, &fdsetRecv);
1706 hSocketMax = std::max(hSocketMax, hSocket);
1709 for (
SOCKET hSocket : send_select_set) {
1710 FD_SET(hSocket, &fdsetSend);
1711 hSocketMax = std::max(hSocketMax, hSocket);
1714 for (
SOCKET hSocket : error_select_set) {
1715 FD_SET(hSocket, &fdsetError);
1716 hSocketMax = std::max(hSocketMax, hSocket);
1720 select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
1729 for (
unsigned int i = 0; i <= hSocketMax; i++) {
1730 FD_SET(i, &fdsetRecv);
1732 FD_ZERO(&fdsetSend);
1733 FD_ZERO(&fdsetError);
1740 for (
SOCKET hSocket : recv_select_set) {
1741 if (FD_ISSET(hSocket, &fdsetRecv)) {
1742 recv_set.insert(hSocket);
1746 for (
SOCKET hSocket : send_select_set) {
1747 if (FD_ISSET(hSocket, &fdsetSend)) {
1748 send_set.insert(hSocket);
1752 for (
SOCKET hSocket : error_select_set) {
1753 if (FD_ISSET(hSocket, &fdsetError)) {
1754 error_set.insert(hSocket);
1761 std::set<SOCKET> recv_set, send_set, error_set;
1773 recv_set.count(hListenSocket.socket) > 0) {
1781 std::vector<CNode *> nodes_copy;
1784 nodes_copy = m_nodes;
1785 for (
CNode *pnode : nodes_copy) {
1789 for (
CNode *pnode : nodes_copy) {
1797 bool recvSet =
false;
1798 bool sendSet =
false;
1799 bool errorSet =
false;
1801 LOCK(pnode->cs_hSocket);
1805 recvSet = recv_set.count(pnode->hSocket) > 0;
1806 sendSet = send_set.count(pnode->hSocket) > 0;
1807 errorSet = error_set.count(pnode->hSocket) > 0;
1809 if (recvSet || errorSet) {
1811 uint8_t pchBuf[0x10000];
1814 LOCK(pnode->cs_hSocket);
1818 nBytes = recv(pnode->hSocket, (
char *)pchBuf,
sizeof(pchBuf),
1822 bool notify =
false;
1823 if (!pnode->ReceiveMsgBytes(*
config, {pchBuf, (size_t)nBytes},
1825 pnode->CloseSocketDisconnect();
1829 size_t nSizeAdded = 0;
1830 auto it(pnode->vRecvMsg.begin());
1831 for (; it != pnode->vRecvMsg.end(); ++it) {
1835 nSizeAdded += it->m_raw_message_size;
1838 LOCK(pnode->cs_vProcessMsg);
1839 pnode->vProcessMsg.splice(pnode->vProcessMsg.end(),
1841 pnode->vRecvMsg.begin(), it);
1842 pnode->nProcessQueueSize += nSizeAdded;
1848 }
else if (nBytes == 0) {
1850 if (!pnode->fDisconnect) {
1854 pnode->CloseSocketDisconnect();
1855 }
else if (nBytes < 0) {
1860 if (!pnode->fDisconnect) {
1862 "socket recv error for peer=%d: %s\n",
1865 pnode->CloseSocketDisconnect();
1880 pnode->fDisconnect =
true;
1885 for (
CNode *pnode : nodes_copy) {
1902 fMsgProcWake =
true;
1909 std::vector<std::string> seeds =
1912 int seeds_right_now = 0;
1917 seeds_right_now = seeds.size();
1922 seeds_right_now = seeds.size();
1937 const std::chrono::seconds seeds_wait_time =
1942 for (
const std::string &seed : seeds) {
1943 if (seeds_right_now == 0) {
1947 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n",
1948 seeds_wait_time.count());
1949 std::chrono::seconds to_wait = seeds_wait_time;
1950 while (to_wait.count() > 0) {
1954 std::chrono::seconds w =
1964 for (
const CNode *pnode : m_nodes) {
1965 if (pnode->fSuccessfullyConnected &&
1966 pnode->IsFullOutboundConn()) {
1971 if (nRelevant >= 2) {
1973 LogPrintf(
"%d addresses found from DNS seeds\n",
1976 "P2P peers available. Finished DNS seeding.\n");
1979 "P2P peers available. Skipped DNS seeding.\n");
1993 LogPrintf(
"Waiting for network to be reactivated before querying "
2002 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
2006 std::vector<CNetAddr> vIPs;
2007 std::vector<CAddress> vAdd;
2010 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
2017 unsigned int nMaxIPs = 256;
2022 requiredServiceBits);
2025 Now<NodeSeconds>() - 3 * 24h, -4 * 24h);
2026 vAdd.push_back(addr);
2039 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2052 std::string strDest;
2055 if (m_addr_fetches.empty()) {
2058 strDest = m_addr_fetches.front();
2059 m_addr_fetches.pop_front();
2076 flag ?
"true" :
"false");
2086 int full_outbound_peers = 0;
2089 for (
const CNode *pnode : m_nodes) {
2090 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
2091 pnode->IsFullOutboundConn()) {
2092 ++full_outbound_peers;
2102 int block_relay_peers = 0;
2105 for (
const CNode *pnode : m_nodes) {
2106 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
2107 pnode->IsBlockOnlyConn()) {
2108 ++block_relay_peers;
2116 const std::vector<std::string> connect,
2119 if (!connect.empty()) {
2120 for (int64_t nLoop = 0;; nLoop++) {
2122 for (
const std::string &strAddr : connect) {
2126 for (
int i = 0; i < 10 && i < nLoop; i++) {
2128 std::chrono::milliseconds(500))) {
2140 auto start = GetTime<std::chrono::microseconds>();
2144 auto next_extra_block_relay =
2149 if (!add_fixed_seeds) {
2150 LogPrintf(
"Fixed seeds are disabled\n");
2157 if (!mockOpenConnection &&
2173 bool add_fixed_seeds_now =
false;
2175 if (GetTime<std::chrono::seconds>() >
2176 start + std::chrono::minutes{1}) {
2177 add_fixed_seeds_now =
true;
2178 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and "
2179 "addrman is empty\n");
2183 if (!add_fixed_seeds_now && !dnsseed) {
2185 if (m_addr_fetches.empty() && m_added_nodes.empty()) {
2186 add_fixed_seeds_now =
true;
2188 "Adding fixed seeds as -dnsseed=0, -addnode is not "
2189 "provided and all -seednode(s) attempted\n");
2193 if (add_fixed_seeds_now) {
2198 add_fixed_seeds =
false;
2208 int nOutboundFullRelay = 0;
2209 int nOutboundBlockRelay = 0;
2210 int nOutboundAvalanche = 0;
2211 std::set<std::vector<uint8_t>> setConnected;
2215 for (
const CNode *pnode : m_nodes) {
2216 if (pnode->IsAvalancheOutboundConnection()) {
2217 nOutboundAvalanche++;
2218 }
else if (pnode->IsFullOutboundConn()) {
2219 nOutboundFullRelay++;
2220 }
else if (pnode->IsBlockOnlyConn()) {
2221 nOutboundBlockRelay++;
2231 switch (pnode->m_conn_type) {
2240 setConnected.insert(
2248 auto now = GetTime<std::chrono::microseconds>();
2249 bool anchor =
false;
2250 bool fFeeler =
false;
2279 }
else if (now > next_extra_block_relay &&
2303 next_extra_block_relay =
2306 }
else if (now > next_feeler) {
2330 "Trying to make an anchor connection to %s\n",
2389 if (nANow - addr_last_try < 10min && nTries < 30) {
2439 std::chrono::milliseconds(randsleep))) {
2448 if (mockOpenConnection) {
2449 mockOpenConnection(addrConnect, conn_type);
2452 int(setConnected.size()) >=
2454 &grant,
nullptr, conn_type);
2461 std::vector<CAddress> ret;
2463 for (
const CNode *pnode : m_nodes) {
2464 if (pnode->IsBlockOnlyConn()) {
2465 ret.push_back(pnode->addr);
2473 std::vector<AddedNodeInfo> ret;
2475 std::list<std::string> lAddresses(0);
2478 ret.reserve(m_added_nodes.size());
2479 std::copy(m_added_nodes.cbegin(), m_added_nodes.cend(),
2480 std::back_inserter(lAddresses));
2485 std::map<CService, bool> mapConnected;
2486 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2489 for (
const CNode *pnode : m_nodes) {
2490 if (pnode->addr.IsValid()) {
2491 mapConnected[pnode->addr] = pnode->IsInboundConn();
2493 std::string addrName{pnode->m_addr_name};
2494 if (!addrName.empty()) {
2495 mapConnectedByName[std::move(addrName)] =
2496 std::make_pair(pnode->IsInboundConn(),
2497 static_cast<const CService &
>(pnode->addr));
2502 for (
const std::string &strAddNode : lAddresses) {
2508 auto it = mapConnected.find(service);
2509 if (it != mapConnected.end()) {
2510 addedNode.resolvedAddress = service;
2511 addedNode.fConnected =
true;
2512 addedNode.fInbound = it->second;
2516 auto it = mapConnectedByName.find(strAddNode);
2517 if (it != mapConnectedByName.end()) {
2518 addedNode.resolvedAddress = it->second.second;
2519 addedNode.fConnected =
true;
2520 addedNode.fInbound = it->second.first;
2523 ret.emplace_back(std::move(addedNode));
2535 if (!info.fConnected) {
2545 info.strAddedNode.c_str(),
2564 const char *pszDest,
2578 bool banned_or_discouraged =
2581 if (
IsLocal(addrConnect) || banned_or_discouraged ||
2585 }
else if (
FindNode(std::string(pszDest))) {
2589 CNode *pnode =
ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
2594 if (grantOutbound) {
2604 m_nodes.push_back(pnode);
2615 std::vector<CNode *> nodes_copy;
2618 nodes_copy = m_nodes;
2619 for (
CNode *pnode : nodes_copy) {
2624 bool fMoreWork =
false;
2629 Shuffle(nodes_copy.begin(), nodes_copy.end(), rng);
2631 for (
CNode *pnode : nodes_copy) {
2632 if (pnode->fDisconnect) {
2636 bool fMoreNodeWork =
false;
2639 fMoreNodeWork |= interface->ProcessMessages(
2642 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
2649 interface->SendMessages(*
config, pnode);
2659 for (
CNode *pnode : nodes_copy) {
2667 std::chrono::steady_clock::now() +
2668 std::chrono::milliseconds(100),
2672 fMsgProcWake =
false;
2677 static constexpr
auto err_wait_begin = 1s;
2678 static constexpr
auto err_wait_cap = 5min;
2679 auto err_wait = err_wait_begin;
2681 bool advertising_listen_addr =
false;
2686 if (advertising_listen_addr && conn.
me.
IsValid()) {
2688 advertising_listen_addr =
false;
2692 if (err_wait < err_wait_cap) {
2699 if (!advertising_listen_addr) {
2701 advertising_listen_addr =
true;
2719 struct sockaddr_storage sockaddr;
2720 socklen_t len =
sizeof(sockaddr);
2721 if (!addrBind.
GetSockAddr((
struct sockaddr *)&sockaddr, &len)) {
2723 Untranslated(
"Error: Bind address family for %s not supported"),
2729 std::unique_ptr<Sock> sock =
CreateSock(addrBind);
2733 "connections (socket returned error %s)"),
2749 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_V6ONLY,
2753 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
2754 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_PROTECTION_LEVEL,
2759 if (::bind(sock->Get(), (
struct sockaddr *)&sockaddr, len) ==
2763 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s "
2764 "is probably already running."),
2765 addrBind.
ToString(), PACKAGE_NAME);
2767 strError =
strprintf(
_(
"Unable to bind to %s on this computer "
2768 "(bind returned error %s)"),
2778 strError =
strprintf(
_(
"Error: Listening for incoming connections "
2779 "failed (listen returned error %s)"),
2796 char pszHostName[256] =
"";
2797 if (gethostname(pszHostName,
sizeof(pszHostName)) !=
SOCKET_ERROR) {
2798 std::vector<CNetAddr> vaddr;
2799 if (
LookupHost(pszHostName, vaddr, 0,
true)) {
2800 for (
const CNetAddr &addr : vaddr) {
2802 LogPrintf(
"%s: %s - %s\n", __func__, pszHostName,
2808 #elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
2810 struct ifaddrs *myaddrs;
2811 if (getifaddrs(&myaddrs) == 0) {
2812 for (
struct ifaddrs *ifa = myaddrs; ifa !=
nullptr;
2813 ifa = ifa->ifa_next) {
2814 if (ifa->ifa_addr ==
nullptr || (ifa->ifa_flags & IFF_UP) == 0 ||
2815 strcmp(ifa->ifa_name,
"lo") == 0 ||
2816 strcmp(ifa->ifa_name,
"lo0") == 0) {
2819 if (ifa->ifa_addr->sa_family == AF_INET) {
2820 struct sockaddr_in *s4 =
2821 reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
2824 LogPrintf(
"%s: IPv4 %s: %s\n", __func__, ifa->ifa_name,
2827 }
else if (ifa->ifa_addr->sa_family == AF_INET6) {
2828 struct sockaddr_in6 *s6 =
2829 reinterpret_cast<struct sockaddr_in6 *
>(ifa->ifa_addr);
2832 LogPrintf(
"%s: IPv6 %s: %s\n", __func__, ifa->ifa_name,
2837 freeifaddrs(myaddrs);
2843 LogPrintf(
"%s: %s\n", __func__, active);
2857 AddrMan &addrmanIn,
bool network_active)
2858 : config(&configIn), addrman(addrmanIn), nSeed0(nSeed0In),
2894 bool fBound =
false;
2895 for (
const auto &addrBind : options.
vBinds) {
2899 for (
const auto &addrBind : options.
vWhiteBinds) {
2903 for (
const auto &addr_bind : options.
onion_binds) {
2908 struct in_addr inaddr_any;
2909 inaddr_any.s_addr = htonl(INADDR_ANY);
2910 struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
2926 _(
"Failed to listen on any port. Use -listen=0 if you want "
2940 for (
const auto &strDest : connOptions.
vSeedNodes) {
2953 "%i block-relay-only anchors will be tried for connections.\n",
2959 _(
"Starting network threads...").translated);
2984 fMsgProcWake =
false;
3006 _(
"Cannot provide specific connections and have addrman find "
3007 "outgoing connections at the same."),
3017 ThreadOpenConnections(connect, nullptr);
3107 std::vector<CAddress> anchors_to_dump =
3119 std::vector<CNode *> nodes;
3121 for (
CNode *pnode : nodes) {
3122 pnode->CloseSocketDisconnect();
3130 LogPrintf(
"CloseSocket(hListenSocket) failed with error %s\n",
3148 interface->FinalizeNode(*
config, *pnode);
3158 std::vector<CAddress>
3160 std::optional<Network> network)
const {
3161 std::vector<CAddress> addresses =
3164 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3166 return m_banman->IsDiscouraged(
3168 m_banman->IsBanned(addr);
3175 std::vector<CAddress>
3181 .
Write(local_socket_bytes.data(), local_socket_bytes.size())
3183 const auto current_time = GetTime<std::chrono::microseconds>();
3219 current_time + std::chrono::hours(21) +
3227 for (
const std::string &it : m_added_nodes) {
3228 if (strNode == it) {
3233 m_added_nodes.push_back(strNode);
3239 for (std::vector<std::string>::iterator it = m_added_nodes.begin();
3240 it != m_added_nodes.end(); ++it) {
3241 if (strNode == *it) {
3242 m_added_nodes.erase(it);
3253 return m_nodes.size();
3257 for (
const auto &pnode : m_nodes) {
3270 vstats.reserve(m_nodes.size());
3271 for (
CNode *pnode : m_nodes) {
3272 vstats.emplace_back();
3273 pnode->copyStats(vstats.back());
3274 vstats.back().m_mapped_as = pnode->addr.GetMappedAS(
addrman.
GetAsmap());
3282 "disconnect by address%s matched peer=%d; disconnecting\n",
3284 pnode->fDisconnect =
true;
3291 bool disconnected =
false;
3293 for (
CNode *pnode : m_nodes) {
3294 if (subnet.
Match(pnode->addr)) {
3296 "disconnect by subnet%s matched peer=%d; disconnecting\n",
3299 pnode->fDisconnect =
true;
3300 disconnected =
true;
3303 return disconnected;
3312 for (
CNode *pnode : m_nodes) {
3313 if (
id == pnode->GetId()) {
3316 pnode->fDisconnect =
true;
3329 nTotalBytesSent += bytes;
3331 const auto now = GetTime<std::chrono::seconds>();
3334 nMaxOutboundCycleStartTime = now;
3335 nMaxOutboundTotalBytesSentInCycle = 0;
3339 nMaxOutboundTotalBytesSentInCycle += bytes;
3344 return nMaxOutboundLimit;
3353 if (nMaxOutboundLimit == 0) {
3357 if (nMaxOutboundCycleStartTime.count() == 0) {
3361 const std::chrono::seconds cycleEndTime =
3363 const auto now = GetTime<std::chrono::seconds>();
3364 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
3369 if (nMaxOutboundLimit == 0) {
3373 if (historicalBlockServingLimit) {
3375 const std::chrono::seconds timeLeftInCycle =
3377 const uint64_t buffer =
3378 timeLeftInCycle / std::chrono::minutes{10} *
ONE_MEGABYTE;
3379 if (buffer >= nMaxOutboundLimit ||
3380 nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer) {
3383 }
else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) {
3392 if (nMaxOutboundLimit == 0) {
3396 return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
3398 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
3407 return nTotalBytesSent;
3431 uint64_t windowInvCounters =
invCounters.exchange(0);
3434 int64_t polls = windowInvCounters & std::numeric_limits<uint32_t>::max();
3435 int64_t votes = windowInvCounters >> 32;
3438 decayFactor * (2 * votes - polls) + (1. - decayFactor) * previousScore;
3448 uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn,
3449 uint64_t nLocalExtraEntropyIn,
const CAddress &addrBindIn,
3452 : m_connected(
GetTime<
std::chrono::seconds>()), addr(addrIn),
3453 addrBind(addrBindIn), m_addr_name{addrNameIn.empty()
3454 ? addr.ToStringIPPort()
3456 m_inbound_onion(inbound_onion), nKeyedNetGroup(nKeyedNetGroupIn),
3460 id(idIn), nLocalHostNonce(nLocalHostNonceIn),
3461 nLocalExtraEntropy(nLocalExtraEntropyIn), m_conn_type(conn_type_in) {
3462 if (inbound_onion) {
3465 hSocket = hSocketIn;
3468 mapRecvBytesPerMsgCmd[msg] = 0;
3495 size_t nMessageSize = msg.data.size();
3497 nMessageSize, pnode->
GetId());
3505 msg.data.size(), msg.data.data());
3508 std::vector<uint8_t> serializedHeader;
3510 size_t nTotalSize = nMessageSize + serializedHeader.size();
3512 size_t nBytesSent = 0;
3515 bool optimisticSend(pnode->vSendMsg.empty());
3518 pnode->mapSendBytesPerMsgCmd[msg.m_type] += nTotalSize;
3519 pnode->nSendSize += nTotalSize;
3524 pnode->vSendMsg.push_back(std::move(serializedHeader));
3526 pnode->vSendMsg.push_back(std::move(msg.data));
3530 if (optimisticSend ==
true) {
3540 CNode *found =
nullptr;
3542 for (
auto &&pnode : m_nodes) {
3543 if (pnode->
GetId() ==
id) {
3559 .
Write(vchNetGroup.data(), vchNetGroup.size())
3581 std::stringstream ebMBs;
3583 std::string eb = ebMBs.str();
3584 eb.insert(eb.size() - 1,
".", 1);
3585 if (eb.substr(0, 1) ==
".") {
3594 std::vector<std::string> uacomments;
3595 uacomments.push_back(
"EB" + eb);
3599 for (
const std::string &cmt :
gArgs.
GetArgs(
"-uacomment")) {
3600 uacomments.push_back(cmt);
3604 const std::string client_version =
3617 auto now = GetTime<std::chrono::microseconds>();
3620 std::string clean_addr = addr.
ToString();
3621 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3627 base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
3635 uint32_t size = data.
size();
3640 std::function<void(
const CAddress &addr,
const std::string &msg_type,
bool DumpPeerAddresses(const CChainParams &chainParams, const ArgsManager &args, const AddrMan &addr)
std::vector< CAddress > ReadAnchors(const CChainParams &chainParams, const fs::path &anchors_db_path)
Read the anchor IP address database (anchors.dat)
void DumpAnchors(const CChainParams &chainParams, const fs::path &anchors_db_path, const std::vector< CAddress > &anchors)
Dump the anchor IP address database (anchors.dat)
std::unique_ptr< avalanche::Processor > g_avalanche
Global avalanche instance.
const CChainParams & Params()
Return the currently selected parameters.
Stochastic address manager.
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
void Good(const CService &addr, bool test_before_evict=true, NodeSeconds time=AdjustedTime())
Mark an entry as accessible, possibly moving it from "new" to "tried".
const std::vector< bool > & GetAsmap() const
std::pair< CAddress, NodeSeconds > Select(bool newOnly=false) const
Choose an address to connect to.
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
size_t size() const
Return the number of (unique) addresses in all tables.
std::pair< CAddress, NodeSeconds > SelectTriedCollision()
Randomly select an address in the tried table that another address is attempting to evict.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time=AdjustedTime())
Mark an entry as connection attempted to.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Non-refcounted RAII wrapper for FILE*.
bool IsBanned(const CNetAddr &net_addr)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr)
Return whether net_addr is discouraged.
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
const CMessageHeader::MessageMagic & NetMagic() const
uint16_t GetDefaultPort() const
const std::vector< SeedSpec6 > & FixedSeeds() const
void CreateNodeFromAcceptedSocket(SOCKET hSocket, NetPermissionFlags permissionFlags, const CAddress &addr_bind, const CAddress &addr)
Create a CNode object from a socket that has just been accepted and add the node to the m_nodes membe...
std::condition_variable condMsgProc
size_t GetNodeCount(NumConnections num) const
std::thread threadMessageHandler
std::chrono::seconds GetMaxOutboundTimeLeftInCycle() const
returns the time in second left in the current max outbound cycle in case of no limit,...
bool OutboundTargetReached(bool historicalBlockServingLimit) const
check if the outbound target is reached.
CClientUIInterface * m_client_interface
size_t SocketSendData(CNode &node) const EXCLUSIVE_LOCKS_REQUIRED(node.cs_vSend)
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool AddConnection(const std::string &address, ConnectionType conn_type)
Attempts to open a connection.
CNode * ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type)
void DeleteNode(CNode *pnode)
bool RemoveAddedNode(const std::string &node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
bool AttemptToEvictConnection()
Try to find a connection to evict when the node is full.
bool AlreadyConnectedToAddress(const CAddress &addr)
Determine whether we're already connected to a given address, in order to avoid initiating duplicate ...
ServiceFlags nLocalServices
Services this node offers.
bool GetTryNewOutboundPeer() const
int m_max_outbound_block_relay
std::thread threadI2PAcceptIncoming
void SetTryNewOutboundPeer(bool flag)
std::atomic< bool > flagInterruptMsgProc
unsigned int GetReceiveFloodSize() const
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
void SocketEvents(std::set< SOCKET > &recv_set, std::set< SOCKET > &send_set, std::set< SOCKET > &error_set)
CThreadInterrupt interruptNet
This is signaled when network activity should cease.
std::unique_ptr< CSemaphore > semAddnode
bool Start(CScheduler &scheduler, const Options &options) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex
std::atomic< NodeId > nLastNodeId
void RecordBytesSent(uint64_t bytes)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
BanMan * m_banman
Pointer to this node's banman.
uint64_t GetOutboundTargetBytesLeft() const
response the bytes left in the current max outbound cycle in case of no limit, it will always respons...
std::thread threadDNSAddressSeed
void ThreadI2PAcceptIncoming()
std::vector< CAddress > m_anchors
Addresses that were saved during the previous clean shutdown.
std::chrono::seconds GetMaxOutboundTimeframe() const
unsigned int nPrevNodeCount
void NotifyNumConnectionsChanged()
ServiceFlags GetLocalServices() const
Used to convey which local services we are offering peers during node connection.
bool DisconnectNode(const std::string &node)
std::chrono::seconds m_peer_connect_timeout
std::atomic_bool m_try_another_outbound_peer
flag for deciding to connect to an extra outbound peer, in excess of m_max_outbound_full_relay.
bool InitBinds(const Options &options)
void AddAddrFetch(const std::string &strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex)
std::vector< ListenSocket > vhListenSocket
std::vector< CAddress > GetCurrentBlockRelayOnlyConns() const
Return vector of current BLOCK_RELAY peers.
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint64_t GetMaxOutboundTarget() const
std::unique_ptr< CSemaphore > semOutbound
std::vector< NetWhitelistPermissions > vWhitelistedRange
RecursiveMutex cs_totalBytesSent
bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions)
std::thread threadOpenConnections
Mutex m_addr_fetches_mutex
bool InactivityCheck(const CNode &node) const
Return true if the peer is inactive and should be disconnected.
CNode * FindNode(const CNetAddr &ip)
void GetNodeStats(std::vector< CNodeStats > &vstats) const
std::vector< AddedNodeInfo > GetAddedNodeInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
const uint64_t nSeed0
SipHasher seeds for deterministic randomness.
unsigned int nReceiveFloodSize
int GetExtraFullOutboundCount() const
uint64_t GetTotalBytesRecv() const
RecursiveMutex m_nodes_mutex
static bool NodeFullyConnected(const CNode *pnode)
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex)
CConnman(const Config &configIn, uint64_t seed0, uint64_t seed1, AddrMan &addrmanIn, bool network_active=true)
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
void SetNetworkActive(bool active)
std::list< CNode * > m_nodes_disconnected
void OpenNetworkConnection(const CAddress &addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *strDest, ConnectionType conn_type)
void AddWhitelistPermissionFlags(NetPermissionFlags &flags, const CNetAddr &addr) const
bool GenerateSelectSet(std::set< SOCKET > &recv_set, std::set< SOCKET > &send_set, std::set< SOCKET > &error_set)
void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
uint64_t CalculateKeyedNetGroup(const CAddress &ad) const
bool fAddressesInitialized
bool AddNode(const std::string &node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
std::thread threadOpenAddedConnections
Mutex m_added_nodes_mutex
void Init(const Options &connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
bool CheckIncomingNonce(uint64_t nonce)
int m_max_outbound_full_relay
void RecordBytesRecv(uint64_t bytes)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg)
unsigned int nSendBufferMaxSize
std::unique_ptr< i2p::sam::Session > m_i2p_sam_session
I2P SAM session.
bool m_use_addrman_outgoing
std::map< uint64_t, CachedAddrResponse > m_addr_response_caches
Addr responses stored in different caches per (network, local socket) prevent cross-network node iden...
std::atomic< uint64_t > nTotalBytesRecv
std::atomic< bool > fNetworkActive
std::atomic_bool m_start_extra_block_relay_peers
flag for initiating extra block-relay-only peer connections.
std::vector< CService > m_onion_binds
A vector of -bind=<address>:<port>=onion arguments each of which is an address and port that are desi...
std::vector< NetEventsInterface * > m_msgproc
std::thread threadSocketHandler
uint64_t GetTotalBytesSent() const
void ThreadOpenConnections(std::vector< std::string > connect, std::function< void(const CAddress &, ConnectionType)> mockOpenConnection) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
void AcceptConnection(const ListenSocket &hListenSocket)
bool BindListenPort(const CService &bindAddr, bilingual_str &strError, NetPermissionFlags permissions)
int m_max_avalanche_outbound
void resize(size_type n, value_type c=value_type{})
void Finalize(Span< uint8_t > output)
CHash256 & Write(Span< const uint8_t > input)
Network GetNetClass() const
std::string ToStringIP() const
std::string ToString() const
std::vector< uint8_t > GetGroup(const std::vector< bool > &asmap) const
Get the canonical identifier of our network group.
std::vector< uint8_t > GetAddrBytes() const
bool SetInternal(const std::string &name)
Create an "internal" address that represents a name or FQDN.
enum Network GetNetwork() const
Transport protocol agnostic message container.
uint32_t m_message_size
size of the payload
std::chrono::microseconds m_time
time of message receipt
uint32_t m_raw_message_size
used wire size of the message (including header/checksum)
Information about a peer.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
std::atomic< int > nVersion
std::atomic< double > availabilityScore
The last computed score.
bool IsInboundConn() const
std::atomic< int64_t > nTimeOffset
const std::string m_addr_name
std::string ConnectionTypeAsString() const
std::atomic< bool > m_bip152_highbandwidth_to
std::list< CNetMessage > vRecvMsg
std::atomic< bool > m_bip152_highbandwidth_from
std::atomic_bool fSuccessfullyConnected
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
CSemaphoreGrant grantOutbound
std::unique_ptr< TransportSerializer > m_serializer
Mutex m_subver_mutex
cleanSubVer is a sanitized string of the user agent byte array we read from the wire.
std::atomic_bool fPauseSend
void CloseSocketDisconnect() EXCLUSIVE_LOCKS_REQUIRED(!cs_hSocket)
std::unique_ptr< TransportDeserializer > m_deserializer
double getAvailabilityScore() const
NetPermissionFlags m_permissionFlags
const ConnectionType m_conn_type
Network ConnectedThroughNetwork() const
Get network the peer connected through.
void copyStats(CNodeStats &stats) EXCLUSIVE_LOCKS_REQUIRED(!m_subver_mutex
std::atomic< std::chrono::microseconds > m_last_ping_time
Last measured round-trip time.
void updateAvailabilityScore(double decayFactor)
The availability score is calculated using an exponentially weighted average.
bool ReceiveMsgBytes(const Config &config, Span< const uint8_t > msg_bytes, bool &complete) EXCLUSIVE_LOCKS_REQUIRED(!cs_vRecv)
Receive bytes from the buffer and deserialize them into messages.
void invsPolled(uint32_t count)
The node was polled for count invs.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e.
std::atomic< std::chrono::microseconds > m_min_ping_time
Lowest measured round-trip time.
std::atomic< std::chrono::seconds > m_last_proof_time
UNIX epoch time of the last proof received from this peer that we had not yet seen (e....
std::atomic< bool > m_avalanche_enabled
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::atomic< uint64_t > invCounters
The inventories polled and voted counters since last score computation, stored as a pair of uint32_t ...
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_recv
CNode(NodeId id, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, uint64_t nLocalExtraEntropyIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
CService GetAddrLocal() const EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
void invsVoted(uint32_t count)
The node voted for count invs.
std::atomic< std::chrono::seconds > m_last_send
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Predicate p, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat p until it return false.
RAII-style semaphore lock.
void MoveTo(CSemaphoreGrant &grant)
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringIPPort() const
std::string ToString() const
bool SetSockAddr(const struct sockaddr *paddr)
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
std::string ToString() const
bool Match(const CNetAddr &addr) const
bool sleep_for(std::chrono::milliseconds rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut)
Minimal stream for overwriting and/or appending to an existing byte vector.
virtual uint64_t GetMaxBlockSize() const =0
virtual const CChainParams & GetChainParams() const =0
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
Different type to mark Mutex at global scope.
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
NetPermissionFlags m_flags
static void AddFlag(NetPermissionFlags &flags, NetPermissionFlags f)
static void ClearFlag(NetPermissionFlags &flags, NetPermissionFlags f)
ClearFlag is only called with f == NetPermissionFlags::Implicit.
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
static bool TryParse(const std::string &str, NetWhitebindPermissions &output, bilingual_str &error)
constexpr std::size_t size() const noexcept
constexpr C * data() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
CNetMessage GetMessage(const Config &config, std::chrono::microseconds time) override
const uint256 & GetMessageHash() const
int readData(Span< const uint8_t > msg_bytes)
bool Complete() const override
int readHeader(const Config &config, Span< const uint8_t > msg_bytes)
void prepareForTransport(const Config &config, CSerializedNetMsg &msg, std::vector< uint8_t > &header) override
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
std::string FormatVersion(int nVersion)
std::string FormatUserAgent(const std::string &name, const std::string &version, const std::vector< std::string > &comments)
Format the subversion field according to BIP 14 spec.
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
const std::string CLIENT_NAME
#define WSAGetLastError()
static bool IsSelectableSocket(const SOCKET &s)
const Config & GetConfig()
static const uint64_t ONE_MEGABYTE
1MB
static uint32_t ReadLE32(const uint8_t *ptr)
const std::vector< std::string > GetRandomizedDNSSeeds(const CChainParams ¶ms)
Return the list of hostnames to look up for DNS seeds.
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
#define LogPrint(category,...)
static unsigned char elements[DATACOUNT][DATALEN]
static bool create_directories(const std::filesystem::path &p)
Create directory (and if necessary its parents), unless the leaf directory already exists or is a sym...
FILE * fopen(const fs::path &p, const char *mode)
Implement std::hash so RCUPtr can be used as a key for maps or sets.
void TraceThread(const char *thread_name, std::function< void()> thread_func)
A wrapper for do-something-once thread functions.
static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
bool IsPeerAddrLocalGood(CNode *pnode)
static void EraseLastKElements(std::vector< T > &elements, Comparator comparator, size_t k, std::function< bool(const NodeEvictionCandidate &)> predicate=[](const NodeEvictionCandidate &n) { return true;})
Sort an array by the specified comparator, then erase the last K elements where predicate is true.
static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE
Number of DNS seeds to query when the number of connections is low.
bool IsLocal(const CService &addr)
check whether a given address is potentially local
static const uint64_t RANDOMIZER_ID_NETGROUP
CService GetLocalAddress(const CNetAddr &addrPeer)
static const uint64_t SELECT_TIMEOUT_MILLISECONDS
static bool CompareNodeBlockRelayOnlyTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
void RemoveLocal(const CService &addr)
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
BindFlags
Used to pass flags to the Bind() function.
@ BF_DONT_ADVERTISE
Do not call AddLocal() for our special addresses, e.g., for incoming Tor connections,...
static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE
static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL
static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD
static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS
Maximum number of block-relay-only anchor connections.
bool GetLocal(CService &addr, const CNetAddr *paddrPeer)
static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
std::map< CNetAddr, LocalServiceInfo > mapLocalHost GUARDED_BY(g_maplocalhost_mutex)
static bool CompareNodeAvailabilityScore(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static CAddress GetBindAddress(SOCKET sock)
Get the bind address for a socket as CAddress.
static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS
How long to delay before querying DNS seeds.
static const uint64_t RANDOMIZER_ID_ADDRCACHE
void ProtectEvictionCandidatesByRatio(std::vector< NodeEvictionCandidate > &eviction_candidates)
Protect desirable or disadvantaged inbound peers from eviction by ratio.
const std::string NET_MESSAGE_COMMAND_OTHER
void SetReachable(enum Network net, bool reachable)
Mark a network as reachable or unreachable (no automatic connects to it)
static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const uint8_t > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
const char *const ANCHORS_DATABASE_FILENAME
Anchor IP address database file name.
std::string getSubVersionEB(uint64_t MaxBlockSize)
This function convert MaxBlockSize from byte to MB with a decimal precision one digit rounded down E....
GlobalMutex g_maplocalhost_mutex
bool AddLocal(const CService &addr, int nScore)
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
static bool CompareNodeProofTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#define FEELER_SLEEP_WINDOW
void CaptureMessageToFile(const CAddress &addr, const std::string &msg_type, Span< const uint8_t > data, bool is_incoming)
Dump binary message to file, with timestamp.
static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS
static int GetnScore(const CService &addr)
std::string ConnectionTypeAsString(ConnectionType conn_type)
Convert ConnectionType enum to a string value.
static std::vector< CAddress > convertSeed6(const std::vector< SeedSpec6 > &vSeedsIn)
Convert the pnSeed6 array into usable address objects.
static const uint64_t RANDOMIZER_ID_EXTRAENTROPY
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static CNetCleanup instance_of_cnetcleanup
std::string userAgent(const Config &config)
static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME
The default timeframe for -maxuploadtarget.
void Discover()
Look up IP addresses from all interfaces on the machine and add them to the list of local addresses t...
bool IsReachable(enum Network net)
bool SeenLocal(const CService &addr)
vote for a local address
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static const bool DEFAULT_WHITELISTFORCERELAY
Default for -whitelistforcerelay.
static const bool DEFAULT_FORCEDNSSEED
static const bool DEFAULT_WHITELISTRELAY
Default for -whitelistrelay.
static constexpr auto EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL
Run the extra block-relay-only connection loop once every 5 minutes.
static const bool DEFAULT_FIXEDSEEDS
ConnectionType
Different types of connections to a peer.
@ BLOCK_RELAY
We use block-relay-only connections to help prevent against partition attacks.
@ MANUAL
We open manual connections to addresses that users explicitly inputted via the addnode RPC,...
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
@ FEELER
Feeler connections are short-lived connections made to check that a node is alive.
@ INBOUND
Inbound connections are those initiated by a peer.
@ AVALANCHE_OUTBOUND
Special case of connection to a full relay outbound with avalanche service enabled.
@ ADDR_FETCH
AddrFetch connections are short lived connections used to solicit addresses from peers.
static constexpr auto FEELER_INTERVAL
Run the feeler connection loop once every 2 minutes.
static const bool DEFAULT_DNSSEED
static const int MAX_BLOCK_RELAY_ONLY_CONNECTIONS
Maximum number of block-relay-only outgoing connections.
@ NET_MAX
Dummy value to indicate the number of NET_* constants.
@ NET_ONION
TOR (v2 or v3)
@ NET_UNROUTABLE
Addresses from these networks are not publicly routable on the global Internet.
@ NET_INTERNAL
A set of addresses that represent the hash of a string or FQDN.
bool GetNameProxy(proxyType &nameProxyOut)
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
bool SetSocketNoDelay(const SOCKET &hSocket)
Set the TCP_NODELAY flag on a socket.
bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, uint16_t port, const Sock &sock, int nTimeout, bool &outProxyConnectionFailed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
void InterruptSocks5(bool interrupt)
bool ConnectSocketDirectly(const CService &addrConnect, const Sock &sock, int nTimeout, bool manual_connection)
Try to connect to the specified service on the specified socket.
std::function< std::unique_ptr< Sock >const CService &)> CreateSock
Socket factory.
bool Lookup(const std::string &name, std::vector< CService > &vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
Resolve a service string to its corresponding service.
CService LookupNumeric(const std::string &name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
Resolve a service string with a numeric IP to its first corresponding service.
bool IsBadPort(uint16_t port)
Determine if a port is "bad" from the perspective of attempting to connect to a node on that port.
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
Resolve a host string to its corresponding network addresses.
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
const std::vector< std::string > & getAllNetMessageTypes()
Get a vector of all valid message types (see above)
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services),...
ServiceFlags
nServices flags.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en....
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
constexpr auto GetRandMillis
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
static uint16_t GetDefaultPort()
void ser_writedata32(Stream &s, uint32_t obj)
void ser_writedata64(Stream &s, uint64_t obj)
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< const std::byte > AsBytes(Span< T > s) noexcept
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
void SplitHostPort(std::string in, uint16_t &portOut, std::string &hostOut)
Cache responses to addr requests to minimize privacy leak.
std::chrono::microseconds m_cache_entry_expiration
std::vector< CAddress > m_addrs_response_cache
void AddSocketPermissionFlags(NetPermissionFlags &flags) const
std::vector< NetWhitebindPermissions > vWhiteBinds
std::vector< CService > onion_binds
std::vector< std::string > m_specified_outgoing
std::vector< CService > vBinds
bool m_i2p_accept_incoming
std::vector< std::string > vSeedNodes
bool m_use_addrman_outgoing
bool bind_on_any
True if the user did not specify -bind= or -whitebind= and thus we should bind on 0....
POD that contains various stats about a node.
mapMsgCmdSize mapSendBytesPerMsgCmd
std::chrono::microseconds m_last_ping_time
std::chrono::seconds m_last_recv
std::optional< double > m_availabilityScore
std::chrono::seconds m_last_proof_time
ConnectionType m_conn_type
std::chrono::seconds m_last_send
std::chrono::seconds m_last_tx_time
std::chrono::microseconds m_min_ping_time
std::chrono::seconds m_connected
bool m_bip152_highbandwidth_from
bool m_bip152_highbandwidth_to
mapMsgCmdSize mapRecvBytesPerMsgCmd
std::chrono::seconds m_last_block_time
NetPermissionFlags m_permissionFlags
std::vector< uint8_t > data
Sort eviction candidates by network/localhost and connection uptime.
CompareNodeNetworkTime(bool is_local, Network network)
bool operator()(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) const
std::chrono::seconds m_last_tx_time
std::chrono::seconds m_connected
std::chrono::seconds m_last_block_time
std::chrono::microseconds m_min_ping_time
std::chrono::seconds m_last_proof_time
An established connection with another peer.
std::unique_ptr< Sock > sock
Connected socket.
CService me
Our I2P address.
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
bool error(const char *fmt, const Args &...args)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTimeMillis()
Returns the system time (not mockable)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
NodeSeconds AdjustedTime()
#define TRACE6(context, event, a, b, c, d, e, f)
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation