6#if defined(HAVE_CONFIG_H)
7#include <config/bitcoin-config.h>
55#include <unordered_map>
61 "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed "
62 "MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
94#define FEELER_SLEEP_WINDOW 1
128std::map<CNetAddr, LocalServiceInfo>
134 m_addr_fetches.push_back(strDest);
140 for (
const std::string &bind_arg :
gArgs.
GetArgs(
"-bind")) {
142 constexpr uint16_t dummy_port = 0;
144 if (
Lookup(bind_arg, bind_addr, dummy_port,
false)) {
145 if (bind_addr.
GetPort() != dummy_port) {
154 for (
const std::string &whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
168 return static_cast<uint16_t
>(
179 int nBestReachability = -1;
182 for (
const auto &entry : mapLocalHost) {
183 int nScore = entry.second.nScore;
184 int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
185 if (nReachability > nBestReachability ||
186 (nReachability == nBestReachability && nScore > nBestScore)) {
187 addr =
CService(entry.first, entry.second.nPort);
188 nBestReachability = nReachability;
193 return nBestScore >= 0;
197static std::vector<CAddress>
202 const auto one_week{7 * 24h};
203 std::vector<CAddress> vSeedsOut;
204 vSeedsOut.reserve(vSeedsIn.size());
206 for (
const auto &seed_in : vSeedsIn) {
208 memcpy(&ip, seed_in.addr,
sizeof(ip));
213 vSeedsOut.push_back(addr);
232 const auto it = mapLocalHost.find(addr);
233 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
254 (!addrLocal.IsRoutable() ||
256 if (
node.IsInboundConn()) {
265 addrLocal.SetIP(
node.GetAddrLocal());
268 if (addrLocal.IsRoutable() ||
gArgs.
GetBoolArg(
"-addrmantest",
false)) {
270 addrLocal.ToString(),
node.GetId());
295 const auto [it, is_newly_added] =
298 if (is_newly_added || nScore >= info.
nScore) {
299 info.
nScore = nScore + !is_newly_added;
314 mapLocalHost.erase(addr);
322 vfLimited[net] = !reachable;
327 return !vfLimited[net];
337 const auto it = mapLocalHost.find(addr);
338 if (it == mapLocalHost.end()) {
348 return mapLocalHost.count(addr) > 0;
353 for (
CNode *pnode : m_nodes) {
354 if (
static_cast<CNetAddr>(pnode->addr) == ip) {
363 for (
CNode *pnode : m_nodes) {
373 for (
CNode *pnode : m_nodes) {
374 if (pnode->m_addr_name == addrName) {
383 for (
CNode *pnode : m_nodes) {
384 if (
static_cast<CService>(pnode->addr) == addr) {
398 for (
const CNode *pnode : m_nodes) {
399 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() &&
400 pnode->GetLocalNonce() == nonce) {
410 struct sockaddr_storage sockaddr_bind;
411 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
413 if (!getsockname(sock, (
struct sockaddr *)&sockaddr_bind,
414 &sockaddr_bind_len)) {
415 addr_bind.
SetSockAddr((
const struct sockaddr *)&sockaddr_bind);
427 if (pszDest ==
nullptr) {
435 LogPrintf(
"Failed to open new connection, already connected\n");
441 pszDest ? pszDest : addrConnect.
ToString(),
443 pszDest ? 0h : Now<NodeSeconds>() - addrConnect.
nTime));
446 const uint16_t default_port{pszDest !=
nullptr
450 std::vector<CService> resolved;
451 if (
Lookup(pszDest, resolved, default_port,
458 "Resolver returned invalid address %s for %s\n",
468 LogPrintf(
"Failed to open new connection, already connected\n");
475 bool connected =
false;
476 std::unique_ptr<Sock> sock;
482 bool proxyConnectionFailed =
false;
488 proxyConnectionFailed)) {
490 sock = std::move(conn.
sock);
511 if (!proxyConnectionFailed) {
523 uint16_t port{default_port};
525 bool proxyConnectionFailed;
534 std::vector<NetWhitelistPermissions> whitelist_permissions =
537 : std::vector<NetWhitelistPermissions>{};
539 whitelist_permissions);
546 uint64_t extra_entropy =
555 nonce, extra_entropy, addr_bind, pszDest ? pszDest :
"", conn_type,
578 const std::vector<NetWhitelistPermissions> &ranges)
const {
579 for (
const auto &subnet : ranges) {
580 if (subnet.m_subnet.Match(addr)) {
606 return "outbound-full-relay";
608 return "block-relay-only";
627 if (addrLocal.IsValid()) {
628 error(
"Addr local already set for node: %i. Refusing to change from %s "
630 id, addrLocal.ToString(), addrLocalIn.
ToString());
632 addrLocal = addrLocalIn;
691 const auto time = GetTime<std::chrono::microseconds>();
693 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
694 nRecvBytes += msg_bytes.
size();
695 while (msg_bytes.
size() > 0) {
708 mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.
m_type);
709 if (i == mapRecvBytesPerMsgCmd.end()) {
713 assert(i != mapRecvBytesPerMsgCmd.end());
730 uint32_t nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
743 }
catch (
const std::exception &) {
761 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
786 const std::chrono::microseconds time) {
814 "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
830 std::vector<uint8_t> &header) {
845 size_t nSentSize = 0;
846 size_t nMsgCount = 0;
848 for (
const auto &data :
node.vSendMsg) {
858 nBytes =
node.m_sock->Send(
859 reinterpret_cast<const char *
>(data.data()) +
node.nSendOffset,
875 node.CloseSocketDisconnect();
882 node.m_last_send = GetTime<std::chrono::seconds>();
883 node.nSendBytes += nBytes;
884 node.nSendOffset += nBytes;
886 if (
node.nSendOffset != data.size()) {
891 node.nSendOffset = 0;
892 node.nSendSize -= data.size();
897 node.vSendMsg.erase(
node.vSendMsg.begin(),
898 node.vSendMsg.begin() + nMsgCount);
900 if (
node.vSendMsg.empty()) {
905 return {nSentSize, !
node.vSendMsg.empty()};
1028template <
typename T,
typename Comparator>
1030 std::vector<T> &
elements, Comparator comparator,
size_t k,
1034 size_t eraseSize = std::min(k,
elements.size());
1041 std::vector<NodeEvictionCandidate> &eviction_candidates) {
1050 const size_t initial_size = eviction_candidates.size();
1051 const size_t total_protect_size{initial_size / 2};
1061 std::array<Net, 3> networks{{{
false,
NET_I2P, 0},
1066 for (Net &n : networks) {
1067 n.count = std::count_if(
1068 eviction_candidates.cbegin(), eviction_candidates.cend(),
1070 return n.is_local ? c.m_is_local : c.m_network == n.id;
1076 std::stable_sort(networks.begin(), networks.end(),
1077 [](Net a, Net b) { return a.count < b.count; });
1080 const size_t max_protect_by_network{total_protect_size / 2};
1081 size_t num_protected{0};
1083 while (num_protected < max_protect_by_network) {
1086 auto num_networks = std::count_if(networks.begin(), networks.end(),
1087 [](
const Net &n) { return n.count; });
1088 if (num_networks == 0) {
1091 const size_t disadvantaged_to_protect{max_protect_by_network -
1093 const size_t protect_per_network{std::max(
1094 disadvantaged_to_protect / num_networks,
static_cast<size_t>(1))};
1098 bool protected_at_least_one{
false};
1100 for (Net &n : networks) {
1104 const size_t before = eviction_candidates.size();
1108 return n.is_local ? c.m_is_local : c.m_network == n.id;
1110 const size_t after = eviction_candidates.size();
1111 if (before > after) {
1112 protected_at_least_one =
true;
1113 const size_t delta{before - after};
1114 num_protected += delta;
1115 if (num_protected >= max_protect_by_network) {
1121 if (!protected_at_least_one) {
1128 assert(num_protected == initial_size - eviction_candidates.size());
1129 const size_t remaining_to_protect{total_protect_size - num_protected};
1131 remaining_to_protect);
1134[[nodiscard]] std::optional<NodeId>
1176 if (vEvictionCandidates.empty()) {
1177 return std::nullopt;
1185 vEvictionCandidates.begin(), vEvictionCandidates.end(),
1187 vEvictionCandidates.erase(
1189 vEvictionCandidates.begin(), vEvictionCandidates.end(),
1191 vEvictionCandidates.end());
1196 uint64_t naMostConnections;
1197 unsigned int nMostConnections = 0;
1198 std::chrono::seconds nMostConnectionsTime{0};
1199 std::map<uint64_t, std::vector<NodeEvictionCandidate>> mapNetGroupNodes;
1201 std::vector<NodeEvictionCandidate> &group =
1202 mapNetGroupNodes[
node.nKeyedNetGroup];
1203 group.push_back(
node);
1204 const auto grouptime{group[0].m_connected};
1205 size_t group_size = group.size();
1206 if (group_size > nMostConnections ||
1207 (group_size == nMostConnections &&
1208 grouptime > nMostConnectionsTime)) {
1209 nMostConnections = group_size;
1210 nMostConnectionsTime = grouptime;
1211 naMostConnections =
node.nKeyedNetGroup;
1216 vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
1219 return vEvictionCandidates.front().id;
1231 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1238 if (!
node->IsInboundConn()) {
1241 if (
node->fDisconnect) {
1248 node->m_min_ping_time,
1249 node->m_last_block_time,
1250 node->m_last_proof_time,
1251 node->m_last_tx_time,
1252 node->m_has_all_wanted_services,
1253 node->m_relays_txs.load(),
1254 node->m_bloom_filter_loaded.load(),
1255 node->nKeyedNetGroup,
1256 node->m_prefer_evict,
1257 node->addr.IsLocal(),
1258 node->ConnectedThroughNetwork(),
1259 node->m_avalanche_enabled
1260 ?
node->getAvailabilityScore()
1261 : -std::numeric_limits<double>::infinity()};
1262 vEvictionCandidates.push_back(candidate);
1265 const std::optional<NodeId> node_id_to_evict =
1267 if (!node_id_to_evict) {
1271 for (
CNode *pnode : m_nodes) {
1272 if (pnode->GetId() == *node_id_to_evict) {
1275 "selected %s connection for eviction peer=%d; disconnecting\n",
1276 pnode->ConnectionTypeAsString(), pnode->GetId());
1277 pnode->fDisconnect =
true;
1285 struct sockaddr_storage sockaddr;
1286 socklen_t len =
sizeof(sockaddr);
1287 auto sock = hListenSocket.
sock->Accept((
struct sockaddr *)&sockaddr, &len);
1293 LogPrintf(
"socket error accept failed: %s\n",
1299 if (!addr.
SetSockAddr((
const struct sockaddr *)&sockaddr)) {
1300 LogPrintf(
"Warning: Unknown socket family\n");
1324 for (
const CNode *pnode : m_nodes) {
1325 if (pnode->IsInboundConn()) {
1333 "connection from %s dropped: not accepting new connections\n",
1339 LogPrintf(
"connection from %s dropped: non-selectable socket\n",
1361 nInbound + 1 >= nMaxInbound && discouraged) {
1367 if (nInbound >= nMaxInbound) {
1371 "connection dropped (full)\n");
1380 uint64_t extra_entropy =
1385 const bool inbound_onion =
1393 .prefer_evict = discouraged,
1404 m_nodes.push_back(pnode);
1414 std::optional<int> max_connections;
1415 switch (conn_type) {
1437 int existing_connections =
1439 return std::count_if(
1440 m_nodes.begin(), m_nodes.end(), [conn_type](
CNode *
node) {
1441 return node->m_conn_type == conn_type;
1445 if (max_connections != std::nullopt &&
1446 existing_connections >= max_connections) {
1467 for (
CNode *pnode : m_nodes) {
1468 if (!pnode->fDisconnect) {
1470 "Network not active, dropping peer=%d\n",
1472 pnode->fDisconnect =
true;
1478 std::vector<CNode *> nodes_copy = m_nodes;
1479 for (
CNode *pnode : nodes_copy) {
1480 if (pnode->fDisconnect) {
1482 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode),
1486 pnode->grantOutbound.Release();
1489 pnode->CloseSocketDisconnect();
1500 for (
CNode *pnode : nodes_disconnected_copy) {
1503 if (pnode->GetRefCount() <= 0) {
1515 nodes_size = m_nodes.size();
1526 std::chrono::seconds now)
const {
1533 const auto now{GetTime<std::chrono::seconds>()};
1534 const auto last_send{
node.m_last_send.load()};
1535 const auto last_recv{
node.m_last_recv.load()};
1541 if (last_recv.count() == 0 || last_send.count() == 0) {
1543 "socket no message in first %i seconds, %d %d peer=%d\n",
1545 last_send.count() != 0,
node.GetId());
1561 if (!
node.fSuccessfullyConnected) {
1574 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
1577 for (
CNode *pnode : nodes) {
1578 bool select_recv = !pnode->fPauseRecv;
1580 WITH_LOCK(pnode->cs_vSend,
return !pnode->vSendMsg.empty());
1581 if (!select_recv && !select_send) {
1585 LOCK(pnode->m_sock_mutex);
1586 if (pnode->m_sock) {
1589 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
1593 return events_per_sock;
1602 const auto timeout =
1610 if (events_per_sock.empty() ||
1611 !events_per_sock.begin()->first->WaitMany(timeout,
1625 const std::vector<CNode *> &nodes,
1627 for (
CNode *pnode : nodes) {
1635 bool recvSet =
false;
1636 bool sendSet =
false;
1637 bool errorSet =
false;
1639 LOCK(pnode->m_sock_mutex);
1640 if (!pnode->m_sock) {
1643 const auto it = events_per_sock.find(pnode->m_sock);
1644 if (it != events_per_sock.end()) {
1647 errorSet = it->second.occurred &
Sock::ERR;
1653 auto [bytes_sent, data_left] =
1672 if (recvSet || errorSet) {
1674 uint8_t pchBuf[0x10000];
1677 LOCK(pnode->m_sock_mutex);
1678 if (!pnode->m_sock) {
1682 pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
1685 bool notify =
false;
1686 if (!pnode->ReceiveMsgBytes(*
config, {pchBuf, (size_t)nBytes},
1688 pnode->CloseSocketDisconnect();
1692 size_t nSizeAdded = 0;
1693 auto it(pnode->vRecvMsg.begin());
1694 for (; it != pnode->vRecvMsg.end(); ++it) {
1698 nSizeAdded += it->m_raw_message_size;
1701 LOCK(pnode->cs_vProcessMsg);
1702 pnode->vProcessMsg.splice(pnode->vProcessMsg.end(),
1704 pnode->vRecvMsg.begin(), it);
1705 pnode->nProcessQueueSize += nSizeAdded;
1711 }
else if (nBytes == 0) {
1713 if (!pnode->fDisconnect) {
1717 pnode->CloseSocketDisconnect();
1718 }
else if (nBytes < 0) {
1723 if (!pnode->fDisconnect) {
1725 "socket recv error for peer=%d: %s\n",
1728 pnode->CloseSocketDisconnect();
1734 pnode->fDisconnect =
true;
1745 const auto it = events_per_sock.find(listen_socket.sock);
1746 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
1763 fMsgProcWake =
true;
1770 std::vector<std::string> seeds =
1773 int seeds_right_now = 0;
1778 seeds_right_now = seeds.size();
1783 seeds_right_now = seeds.size();
1798 const std::chrono::seconds seeds_wait_time =
1803 for (
const std::string &seed : seeds) {
1804 if (seeds_right_now == 0) {
1808 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n",
1809 seeds_wait_time.count());
1810 std::chrono::seconds to_wait = seeds_wait_time;
1811 while (to_wait.count() > 0) {
1815 std::chrono::seconds w =
1825 for (
const CNode *pnode : m_nodes) {
1826 if (pnode->fSuccessfullyConnected &&
1827 pnode->IsFullOutboundConn()) {
1832 if (nRelevant >= 2) {
1834 LogPrintf(
"%d addresses found from DNS seeds\n",
1837 "P2P peers available. Finished DNS seeding.\n");
1840 "P2P peers available. Skipped DNS seeding.\n");
1854 LogPrintf(
"Waiting for network to be reactivated before querying "
1863 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
1867 std::vector<CNetAddr> vIPs;
1868 std::vector<CAddress> vAdd;
1871 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
1878 unsigned int nMaxIPs = 256;
1883 requiredServiceBits);
1886 Now<NodeSeconds>() - 3 * 24h, -4 * 24h);
1887 vAdd.push_back(addr);
1900 LogPrintf(
"%d addresses found from DNS seeds\n", found);
1913 std::string strDest;
1916 if (m_addr_fetches.empty()) {
1919 strDest = m_addr_fetches.front();
1920 m_addr_fetches.pop_front();
1937 flag ?
"true" :
"false");
1947 int full_outbound_peers = 0;
1950 for (
const CNode *pnode : m_nodes) {
1951 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
1952 pnode->IsFullOutboundConn()) {
1953 ++full_outbound_peers;
1963 int block_relay_peers = 0;
1966 for (
const CNode *pnode : m_nodes) {
1967 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
1968 pnode->IsBlockOnlyConn()) {
1969 ++block_relay_peers;
1977 const std::vector<std::string> connect,
1980 if (!connect.empty()) {
1981 for (int64_t nLoop = 0;; nLoop++) {
1983 for (
const std::string &strAddr : connect) {
1987 for (
int i = 0; i < 10 && i < nLoop; i++) {
1989 std::chrono::milliseconds(500))) {
2001 auto start = GetTime<std::chrono::microseconds>();
2005 auto next_extra_block_relay =
2010 if (!add_fixed_seeds) {
2011 LogPrintf(
"Fixed seeds are disabled\n");
2018 if (!mockOpenConnection &&
2034 bool add_fixed_seeds_now =
false;
2036 if (GetTime<std::chrono::seconds>() >
2037 start + std::chrono::minutes{1}) {
2038 add_fixed_seeds_now =
true;
2039 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and "
2040 "addrman is empty\n");
2044 if (!add_fixed_seeds_now && !dnsseed) {
2046 if (m_addr_fetches.empty() && m_added_nodes.empty()) {
2047 add_fixed_seeds_now =
true;
2049 "Adding fixed seeds as -dnsseed=0, -addnode is not "
2050 "provided and all -seednode(s) attempted\n");
2054 if (add_fixed_seeds_now) {
2059 add_fixed_seeds =
false;
2069 int nOutboundFullRelay = 0;
2070 int nOutboundBlockRelay = 0;
2071 int nOutboundAvalanche = 0;
2072 std::set<std::vector<uint8_t>> setConnected;
2076 for (
const CNode *pnode : m_nodes) {
2077 if (pnode->IsAvalancheOutboundConnection()) {
2078 nOutboundAvalanche++;
2079 }
else if (pnode->IsFullOutboundConn()) {
2080 nOutboundFullRelay++;
2081 }
else if (pnode->IsBlockOnlyConn()) {
2082 nOutboundBlockRelay++;
2092 switch (pnode->m_conn_type) {
2101 setConnected.insert(
2109 auto now = GetTime<std::chrono::microseconds>();
2110 bool anchor =
false;
2111 bool fFeeler =
false;
2139 }
else if (now > next_extra_block_relay &&
2163 next_extra_block_relay =
2166 }
else if (now > next_feeler) {
2190 "Trying to make an anchor connection to %s\n",
2249 if (current_time - addr_last_try < 10min && nTries < 30) {
2299 std::chrono::milliseconds(randsleep))) {
2308 if (mockOpenConnection) {
2309 mockOpenConnection(addrConnect, conn_type);
2312 int(setConnected.size()) >=
2314 &grant,
nullptr, conn_type);
2321 std::vector<CAddress> ret;
2323 for (
const CNode *pnode : m_nodes) {
2324 if (pnode->IsBlockOnlyConn()) {
2325 ret.push_back(pnode->addr);
2333 std::vector<AddedNodeInfo> ret;
2335 std::list<std::string> lAddresses(0);
2338 ret.reserve(m_added_nodes.size());
2339 std::copy(m_added_nodes.cbegin(), m_added_nodes.cend(),
2340 std::back_inserter(lAddresses));
2345 std::map<CService, bool> mapConnected;
2346 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2349 for (
const CNode *pnode : m_nodes) {
2350 if (pnode->addr.IsValid()) {
2351 mapConnected[pnode->addr] = pnode->IsInboundConn();
2353 std::string addrName{pnode->m_addr_name};
2354 if (!addrName.empty()) {
2355 mapConnectedByName[std::move(addrName)] =
2356 std::make_pair(pnode->IsInboundConn(),
2357 static_cast<const CService &
>(pnode->addr));
2362 for (
const std::string &strAddNode : lAddresses) {
2368 auto it = mapConnected.find(service);
2369 if (it != mapConnected.end()) {
2370 addedNode.resolvedAddress = service;
2371 addedNode.fConnected =
true;
2372 addedNode.fInbound = it->second;
2376 auto it = mapConnectedByName.find(strAddNode);
2377 if (it != mapConnectedByName.end()) {
2378 addedNode.resolvedAddress = it->second.second;
2379 addedNode.fConnected =
true;
2380 addedNode.fInbound = it->second.first;
2383 ret.emplace_back(std::move(addedNode));
2395 if (!info.fConnected) {
2405 info.strAddedNode.c_str(),
2424 const char *pszDest,
2438 bool banned_or_discouraged =
2441 if (
IsLocal(addrConnect) || banned_or_discouraged ||
2445 }
else if (
FindNode(std::string(pszDest))) {
2449 CNode *pnode =
ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
2454 if (grantOutbound) {
2464 m_nodes.push_back(pnode);
2474 bool fMoreWork =
false;
2482 for (
CNode *pnode : snap.Nodes()) {
2483 if (pnode->fDisconnect) {
2487 bool fMoreNodeWork =
false;
2490 fMoreNodeWork |= interface->ProcessMessages(
2493 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
2500 interface->SendMessages(*
config, pnode);
2512 std::chrono::steady_clock::now() +
2513 std::chrono::milliseconds(100),
2517 fMsgProcWake =
false;
2522 static constexpr auto err_wait_begin = 1s;
2523 static constexpr auto err_wait_cap = 5min;
2524 auto err_wait = err_wait_begin;
2526 bool advertising_listen_addr =
false;
2531 if (advertising_listen_addr && conn.
me.
IsValid()) {
2533 advertising_listen_addr =
false;
2537 if (err_wait < err_wait_cap) {
2544 if (!advertising_listen_addr) {
2546 advertising_listen_addr =
true;
2564 struct sockaddr_storage sockaddr;
2565 socklen_t len =
sizeof(sockaddr);
2566 if (!addrBind.
GetSockAddr((
struct sockaddr *)&sockaddr, &len)) {
2568 Untranslated(
"Error: Bind address family for %s not supported"),
2574 std::unique_ptr<Sock> sock =
CreateSock(addrBind);
2578 "connections (socket returned error %s)"),
2594 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_V6ONLY,
2598 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
2599 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_PROTECTION_LEVEL,
2604 if (::bind(sock->Get(), (
struct sockaddr *)&sockaddr, len) ==
2608 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s "
2609 "is probably already running."),
2610 addrBind.
ToString(), PACKAGE_NAME);
2612 strError =
strprintf(
_(
"Unable to bind to %s on this computer "
2613 "(bind returned error %s)"),
2623 strError =
strprintf(
_(
"Error: Listening for incoming connections "
2624 "failed (listen returned error %s)"),
2641 char pszHostName[256] =
"";
2642 if (gethostname(pszHostName,
sizeof(pszHostName)) !=
SOCKET_ERROR) {
2643 std::vector<CNetAddr> vaddr;
2644 if (
LookupHost(pszHostName, vaddr, 0,
true)) {
2645 for (
const CNetAddr &addr : vaddr) {
2647 LogPrintf(
"%s: %s - %s\n", __func__, pszHostName,
2653#elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
2655 struct ifaddrs *myaddrs;
2656 if (getifaddrs(&myaddrs) == 0) {
2657 for (
struct ifaddrs *ifa = myaddrs; ifa !=
nullptr;
2658 ifa = ifa->ifa_next) {
2659 if (ifa->ifa_addr ==
nullptr || (ifa->ifa_flags & IFF_UP) == 0 ||
2660 strcmp(ifa->ifa_name,
"lo") == 0 ||
2661 strcmp(ifa->ifa_name,
"lo0") == 0) {
2664 if (ifa->ifa_addr->sa_family == AF_INET) {
2665 struct sockaddr_in *s4 =
2666 reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
2669 LogPrintf(
"%s: IPv4 %s: %s\n", __func__, ifa->ifa_name,
2672 }
else if (ifa->ifa_addr->sa_family == AF_INET6) {
2673 struct sockaddr_in6 *s6 =
2674 reinterpret_cast<struct sockaddr_in6 *
>(ifa->ifa_addr);
2677 LogPrintf(
"%s: IPv6 %s: %s\n", __func__, ifa->ifa_name,
2682 freeifaddrs(myaddrs);
2688 LogPrintf(
"%s: %s\n", __func__, active);
2702 AddrMan &addrmanIn,
bool network_active)
2703 : config(&configIn), addrman(addrmanIn), nSeed0(nSeed0In),
2739 bool fBound =
false;
2740 for (
const auto &addrBind : options.
vBinds) {
2744 for (
const auto &addrBind : options.
vWhiteBinds) {
2748 for (
const auto &addr_bind : options.
onion_binds) {
2753 struct in_addr inaddr_any;
2754 inaddr_any.s_addr = htonl(INADDR_ANY);
2755 struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
2771 _(
"Failed to listen on any port. Use -listen=0 if you want "
2785 for (
const auto &strDest : connOptions.
vSeedNodes) {
2798 "%i block-relay-only anchors will be tried for connections.\n",
2804 _(
"Starting network threads...").translated);
2829 fMsgProcWake =
false;
2851 _(
"Cannot provide specific connections and have addrman find "
2852 "outgoing connections at the same."),
2862 ThreadOpenConnections(connect, nullptr);
2952 std::vector<CAddress> anchors_to_dump =
2964 std::vector<CNode *> nodes;
2966 for (
CNode *pnode : nodes) {
2967 pnode->CloseSocketDisconnect();
2983 interface->FinalizeNode(*
config, *pnode);
2993std::vector<CAddress>
2995 std::optional<Network> network)
const {
2996 std::vector<CAddress> addresses =
2999 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3001 return m_banman->IsDiscouraged(
3003 m_banman->IsBanned(addr);
3010std::vector<CAddress>
3016 .
Write(local_socket_bytes.data(), local_socket_bytes.size())
3018 const auto current_time = GetTime<std::chrono::microseconds>();
3054 current_time + std::chrono::hours(21) +
3062 for (
const std::string &it : m_added_nodes) {
3063 if (strNode == it) {
3068 m_added_nodes.push_back(strNode);
3074 for (std::vector<std::string>::iterator it = m_added_nodes.begin();
3075 it != m_added_nodes.end(); ++it) {
3076 if (strNode == *it) {
3077 m_added_nodes.erase(it);
3088 return m_nodes.size();
3092 for (
const auto &pnode : m_nodes) {
3105 vstats.reserve(m_nodes.size());
3106 for (
CNode *pnode : m_nodes) {
3107 vstats.emplace_back();
3108 pnode->copyStats(vstats.back());
3109 vstats.back().m_mapped_as = pnode->addr.GetMappedAS(
addrman.
GetAsmap());
3117 "disconnect by address%s matched peer=%d; disconnecting\n",
3119 pnode->fDisconnect =
true;
3126 bool disconnected =
false;
3128 for (
CNode *pnode : m_nodes) {
3129 if (subnet.
Match(pnode->addr)) {
3131 "disconnect by subnet%s matched peer=%d; disconnecting\n",
3134 pnode->fDisconnect =
true;
3135 disconnected =
true;
3138 return disconnected;
3147 for (
CNode *pnode : m_nodes) {
3148 if (
id == pnode->GetId()) {
3151 pnode->fDisconnect =
true;
3164 nTotalBytesSent += bytes;
3166 const auto now = GetTime<std::chrono::seconds>();
3169 nMaxOutboundCycleStartTime = now;
3170 nMaxOutboundTotalBytesSentInCycle = 0;
3174 nMaxOutboundTotalBytesSentInCycle += bytes;
3179 return nMaxOutboundLimit;
3188 if (nMaxOutboundLimit == 0) {
3192 if (nMaxOutboundCycleStartTime.count() == 0) {
3196 const std::chrono::seconds cycleEndTime =
3198 const auto now = GetTime<std::chrono::seconds>();
3199 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
3204 if (nMaxOutboundLimit == 0) {
3208 if (historicalBlockServingLimit) {
3210 const std::chrono::seconds timeLeftInCycle =
3212 const uint64_t buffer =
3213 timeLeftInCycle / std::chrono::minutes{10} *
ONE_MEGABYTE;
3214 if (buffer >= nMaxOutboundLimit ||
3215 nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer) {
3218 }
else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) {
3227 if (nMaxOutboundLimit == 0) {
3231 return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
3233 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
3242 return nTotalBytesSent;
3266 uint64_t windowInvCounters =
invCounters.exchange(0);
3269 int64_t polls = windowInvCounters & std::numeric_limits<uint32_t>::max();
3270 int64_t votes = windowInvCounters >> 32;
3273 decayFactor * (2 * votes - polls) + (1. - decayFactor) * previousScore;
3283 uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn,
3284 uint64_t nLocalExtraEntropyIn,
const CAddress &addrBindIn,
3287 : m_permission_flags{node_opts.permission_flags}, m_sock{sock},
3288 m_connected(
GetTime<
std::chrono::seconds>()), addr(addrIn),
3289 addrBind(addrBindIn),
3290 m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
3291 m_inbound_onion(inbound_onion), m_prefer_evict{node_opts.prefer_evict},
3292 nKeyedNetGroup(nKeyedNetGroupIn),
3296 id(idIn), nLocalHostNonce(nLocalHostNonceIn),
3297 nLocalExtraEntropy(nLocalExtraEntropyIn), m_conn_type(conn_type_in) {
3298 if (inbound_onion) {
3303 mapRecvBytesPerMsgCmd[msg] = 0;
3326 size_t nMessageSize = msg.data.size();
3328 nMessageSize, pnode->
GetId());
3336 msg.data.size(), msg.data.data());
3339 std::vector<uint8_t> serializedHeader;
3341 size_t nTotalSize = nMessageSize + serializedHeader.size();
3343 size_t nBytesSent = 0;
3346 bool optimisticSend(pnode->vSendMsg.empty());
3349 pnode->mapSendBytesPerMsgCmd[msg.m_type] += nTotalSize;
3350 pnode->nSendSize += nTotalSize;
3355 pnode->vSendMsg.push_back(std::move(serializedHeader));
3357 pnode->vSendMsg.push_back(std::move(msg.data));
3362 if (optimisticSend) {
3372 CNode *found =
nullptr;
3374 for (
auto &&pnode : m_nodes) {
3375 if (pnode->
GetId() ==
id) {
3391 .
Write(vchNetGroup.data(), vchNetGroup.size())
3413 std::stringstream ebMBs;
3415 std::string eb = ebMBs.str();
3416 eb.insert(eb.size() - 1,
".", 1);
3417 if (eb.substr(0, 1) ==
".") {
3426 std::vector<std::string> uacomments;
3427 uacomments.push_back(
"EB" + eb);
3431 for (
const std::string &cmt :
gArgs.
GetArgs(
"-uacomment")) {
3432 uacomments.push_back(cmt);
3436 const std::string client_version =
3449 auto now = GetTime<std::chrono::microseconds>();
3452 std::string clean_addr = addr.
ToString();
3453 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3459 base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
3467 uint32_t size = data.
size();
3472std::function<void(
const CAddress &addr,
const std::string &msg_type,
std::vector< CAddress > ReadAnchors(const CChainParams &chainParams, const fs::path &anchors_db_path)
Read the anchor IP address database (anchors.dat)
bool DumpPeerAddresses(const CChainParams &chainParams, const ArgsManager &args, const AddrMan &addr)
void DumpAnchors(const CChainParams &chainParams, const fs::path &anchors_db_path, const std::vector< CAddress > &anchors)
Dump the anchor IP address database (anchors.dat)
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.
const std::vector< bool > & GetAsmap() const
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as connection attempted to.
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.
void Good(const CService &addr, bool test_before_evict=true, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as accessible, possibly moving it from "new" to "tried".
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.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
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
const std::vector< SeedSpec6 > & FixedSeeds() const
uint16_t GetDefaultPort() const
RAII helper to atomically create a copy of m_nodes and add a reference to each of the nodes.
bool whitelist_relay
flag for adding 'relay' permission to whitelisted inbound and manual peers with default permissions.
std::condition_variable condMsgProc
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.
std::vector< NetWhitelistPermissions > vWhitelistedRangeIncoming
CClientUIInterface * m_client_interface
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
Sock::EventsPerSock GenerateWaitSockets(Span< CNode *const > nodes)
Generate a collection of sockets to check for IO readiness.
void SocketHandlerConnected(const std::vector< CNode * > &nodes, const Sock::EventsPerSock &events_per_sock) EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
Do the read/write for connected sockets that are ready for IO.
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
bool whitelist_forcerelay
flag for adding 'forcerelay' permission to whitelisted inbound and manual peers with default permissi...
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
RecursiveMutex cs_totalBytesSent
bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions)
std::thread threadOpenConnections
size_t GetNodeCount(ConnectionDirection) const
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
std::pair< size_t, bool > SocketSendData(CNode &node) const EXCLUSIVE_LOCKS_REQUIRED(node.cs_vSend)
(Try to) send data from node's vSendMsg.
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 SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
Check connected and listening sockets for IO readiness and process them accordingly.
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 AddWhitelistPermissionFlags(NetPermissionFlags &flags, const CNetAddr &addr, const std::vector< NetWhitelistPermissions > &ranges) const
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 CreateNodeFromAcceptedSocket(std::unique_ptr< Sock > &&sock, NetPermissionFlags permission_flags, 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...
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::vector< NetWhitelistPermissions > vWhitelistedRangeOutgoing
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.
void SocketHandlerListening(const Sock::EventsPerSock &events_per_sock)
Accept incoming connections, one from each read-ready listening socket.
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{})
CHash256 & Write(Span< const uint8_t > input)
void Finalize(Span< uint8_t > output)
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
CNode(NodeId id, std::shared_ptr< Sock > sock, 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, CNodeOptions &&node_opts={})
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
std::unique_ptr< TransportDeserializer > m_deserializer
double getAvailabilityScore() const
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.
const NetPermissionFlags m_permission_flags
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
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.
void CloseSocketDisconnect() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex)
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)
static constexpr Event SEND
If passed to Wait(), then it will wait for readiness to send to the socket.
static constexpr Event ERR
Ignored if passed to Wait(), but could be set in the occurred events if an exceptional condition has ...
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
constexpr std::size_t size() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
constexpr C * data() 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.
bool error(const char *fmt, const Args &...args)
#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)
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)
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
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
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
std::map< CNetAddr, LocalServiceInfo > mapLocalHost GUARDED_BY(g_maplocalhost_mutex)
bool AddLocal(const CService &addr, int nScore)
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 const uint64_t RANDOMIZER_ID_EXTRAENTROPY
static std::vector< CAddress > convertSeed6(const std::vector< SeedSpec6 > &vSeedsIn)
Convert the pnSeed6 array into usable address objects.
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_FORCEDNSSEED
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)
std::function< std::unique_ptr< Sock >(const CService &)> CreateSock
Socket factory.
bool ConnectSocketDirectly(const CService &addrConnect, const Sock &sock, int nTimeout, bool manual_connection)
Try to connect to the specified service on the specified socket.
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.
const std::vector< std::string > & getAllNetMessageTypes()
Get a vector of all valid message types (see above)
ServiceFlags GetDesirableServiceFlags(ServiceFlags services)
Gets the set of service flags which are "desirable" for a given peer.
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
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.
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< const std::byte > AsBytes(Span< T > s) noexcept
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::shared_ptr< Sock > sock
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....
NetPermissionFlags permission_flags
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_permission_flags
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
static time_point now() noexcept
Return current system time or mocked time, if set.
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
Auxiliary requested/occurred events to wait for in WaitMany().
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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTimeMillis()
Returns the system time (not mockable)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
#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.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
void SplitHostPort(std::string_view in, uint16_t &portOut, std::string &hostOut)
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation