6#if defined(HAVE_CONFIG_H)
40#if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
53#include <unordered_map>
59static_assert (MAX_BLOCK_RELAY_ONLY_ANCHORS <= static_cast<size_t>(
MAX_BLOCK_RELAY_ONLY_CONNECTIONS),
"MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
86#define FEELER_SLEEP_WINDOW 1
122 m_addr_fetches.push_back(strDest);
137 int nBestReachability = -1;
140 for (
const auto& entry : mapLocalHost)
142 int nScore = entry.second.nScore;
143 int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
144 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
146 addr =
CService(entry.first, entry.second.nPort);
147 nBestReachability = nReachability;
152 return nBestScore >= 0;
156static std::vector<CAddress>
ConvertSeeds(
const std::vector<uint8_t> &vSeedsIn)
162 const int64_t nOneWeek = 7*24*60*60;
163 std::vector<CAddress> vSeedsOut;
172 vSeedsOut.push_back(addr);
187 ret =
CAddress(addr, nLocalServices);
196 const auto it = mapLocalHost.find(addr);
197 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
254 if (!addr.IsRoutable())
263 LogPrintf(
"AddLocal(%s,%i)\n", addr.ToString(), nScore);
267 const auto [it, is_newly_added] = mapLocalHost.emplace(addr,
LocalServiceInfo());
269 if (is_newly_added || nScore >= info.
nScore) {
270 info.
nScore = nScore + (is_newly_added ? 0 : 1);
271 info.
nPort = addr.GetPort();
287 mapLocalHost.erase(addr);
295 vfLimited[net] = !reachable;
301 return !vfLimited[net];
313 const auto it = mapLocalHost.find(addr);
314 if (it == mapLocalHost.end())
return false;
324 return mapLocalHost.count(addr) > 0;
330 for (
CNode* pnode : vNodes) {
331 if (
static_cast<CNetAddr>(pnode->addr) ==
ip) {
341 for (
CNode* pnode : vNodes) {
352 for (
CNode* pnode : vNodes) {
353 if (pnode->m_addr_name == addrName) {
363 for (
CNode* pnode : vNodes) {
364 if (
static_cast<CService>(pnode->addr) == addr) {
379 for (
const CNode* pnode : vNodes) {
380 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() ==
nonce)
390 struct sockaddr_storage sockaddr_bind;
391 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
393 if (!getsockname(sock, (
struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
394 addr_bind.
SetSockAddr((
const struct sockaddr*)&sockaddr_bind);
406 if (pszDest ==
nullptr) {
414 LogPrintf(
"Failed to open new connection, already connected\n");
421 pszDest ? pszDest : addrConnect.
ToString(),
428 std::vector<CService> resolved;
441 LogPrintf(
"Failed to open new connection, already connected\n");
448 bool connected =
false;
449 std::unique_ptr<Sock> sock;
455 bool proxyConnectionFailed =
false;
461 sock = std::move(conn.
sock);
480 if (!proxyConnectionFailed) {
491 uint16_t port{default_port};
493 bool proxyConnectionFailed;
495 proxyConnectionFailed);
543 return "outbound-full-relay";
545 return "block-relay-only";
561 if (addrLocal.IsValid()) {
562 error(
"Addr local already set for node: %i. Refusing to change from %s to %s",
id, addrLocal.ToString(), addrLocalIn.
ToString());
564 addrLocal = addrLocalIn;
574#define X(name) stats.name = name
605 X(mapSendBytesPerMsgCmd);
610 X(mapRecvBytesPerMsgCmd);
634 const auto time = GetTime<std::chrono::microseconds>();
636 nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count();
637 nRecvBytes += msg_bytes.
size();
638 while (msg_bytes.
size() > 0) {
648 bool reject_message{
false};
650 if (reject_message) {
659 auto i = mapRecvBytesPerMsgCmd.find(msg.
m_command);
660 if (i == mapRecvBytesPerMsgCmd.end()) {
663 assert(i != mapRecvBytesPerMsgCmd.end());
680 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
693 catch (
const std::exception&) {
719 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
744 reject_message =
false;
761 LogPrint(
BCLog::NET,
"Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
766 reject_message =
true;
770 reject_message =
true;
793 auto it =
node.vSendMsg.begin();
794 size_t nSentSize = 0;
796 while (it !=
node.vSendMsg.end()) {
797 const auto& data = *it;
808 node.nSendBytes += nBytes;
809 node.nSendOffset += nBytes;
811 if (
node.nSendOffset == data.size()) {
812 node.nSendOffset = 0;
813 node.nSendSize -= data.size();
826 node.CloseSocketDisconnect();
834 if (it ==
node.vSendMsg.end()) {
838 node.vSendMsg.erase(
node.vSendMsg.begin(), it);
903template <
typename T,
typename Comparator>
905 std::vector<T>& elements, Comparator comparator,
size_t k,
908 std::sort(elements.begin(), elements.end(), comparator);
909 size_t eraseSize = std::min(k, elements.size());
910 elements.erase(std::remove_if(elements.end() - eraseSize, elements.end(), predicate), elements.end());
921 const size_t initial_size = eviction_candidates.size();
922 const size_t total_protect_size{initial_size / 2};
927 std::array<Net, 3> networks{
931 for (Net& n : networks) {
932 n.count = std::count_if(eviction_candidates.cbegin(), eviction_candidates.cend(),
934 return n.is_local ? c.m_is_local : c.m_network == n.id;
939 std::stable_sort(networks.begin(), networks.end(), [](Net a, Net b) { return a.count < b.count; });
942 const size_t max_protect_by_network{total_protect_size / 2};
943 size_t num_protected{0};
945 while (num_protected < max_protect_by_network) {
947 auto num_networks = std::count_if(networks.begin(), networks.end(), [](
const Net& n) { return n.count; });
948 if (num_networks == 0) {
951 const size_t disadvantaged_to_protect{max_protect_by_network - num_protected};
952 const size_t protect_per_network{std::max(disadvantaged_to_protect / num_networks,
static_cast<size_t>(1))};
954 bool protected_at_least_one{
false};
956 for (Net& n : networks) {
957 if (n.count == 0)
continue;
958 const size_t before = eviction_candidates.size();
961 return n.is_local ? c.m_is_local : c.m_network == n.id;
963 const size_t after = eviction_candidates.size();
964 if (before > after) {
965 protected_at_least_one =
true;
966 const size_t delta{before - after};
967 num_protected += delta;
968 if (num_protected >= max_protect_by_network) {
974 if (!protected_at_least_one) {
981 assert(num_protected == initial_size - eviction_candidates.size());
982 const size_t remaining_to_protect{total_protect_size - num_protected};
986[[nodiscard]] std::optional<NodeId>
SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
1011 if (vEvictionCandidates.empty())
return std::nullopt;
1016 if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](
NodeEvictionCandidate const &n){return n.prefer_evict;})) {
1017 vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
1023 uint64_t naMostConnections;
1024 unsigned int nMostConnections = 0;
1025 int64_t nMostConnectionsTime = 0;
1026 std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
1028 std::vector<NodeEvictionCandidate> &group = mapNetGroupNodes[
node.nKeyedNetGroup];
1029 group.push_back(
node);
1030 const int64_t grouptime = group[0].nTimeConnected;
1032 if (group.size() > nMostConnections || (group.size() == nMostConnections && grouptime > nMostConnectionsTime)) {
1033 nMostConnections = group.size();
1034 nMostConnectionsTime = grouptime;
1035 naMostConnections =
node.nKeyedNetGroup;
1040 vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
1043 return vEvictionCandidates.front().id;
1056 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1063 if (!
node->IsInboundConn())
1065 if (
node->fDisconnect)
1067 bool peer_relay_txes =
false;
1068 bool peer_filter_not_null =
false;
1069 if (
node->m_tx_relay !=
nullptr) {
1071 peer_relay_txes =
node->m_tx_relay->fRelayTxes;
1072 peer_filter_not_null =
node->m_tx_relay->pfilter !=
nullptr;
1075 node->nLastBlockTime,
node->nLastTXTime,
1077 peer_relay_txes, peer_filter_not_null,
node->nKeyedNetGroup,
1078 node->m_prefer_evict,
node->addr.IsLocal(),
1079 node->ConnectedThroughNetwork()};
1080 vEvictionCandidates.push_back(candidate);
1083 const std::optional<NodeId> node_id_to_evict =
SelectNodeToEvict(std::move(vEvictionCandidates));
1084 if (!node_id_to_evict) {
1088 for (
CNode* pnode : vNodes) {
1089 if (pnode->GetId() == *node_id_to_evict) {
1090 LogPrint(
BCLog::NET,
"selected %s connection for eviction peer=%d; disconnecting\n", pnode->ConnectionTypeAsString(), pnode->GetId());
1091 pnode->fDisconnect =
true;
1099 struct sockaddr_storage sockaddr;
1100 socklen_t len =
sizeof(sockaddr);
1101 SOCKET hSocket = accept(hListenSocket.
socket, (
struct sockaddr*)&sockaddr, &len);
1112 if (!addr.
SetSockAddr((
const struct sockaddr*)&sockaddr)) {
1113 LogPrintf(
"Warning: Unknown socket family\n");
1145 for (
const CNode* pnode : vNodes) {
1146 if (pnode->IsInboundConn()) nInbound++;
1158 LogPrintf(
"connection from %s dropped: non-selectable socket\n", addr.
ToString());
1185 if (nInbound >= nMaxInbound)
1189 LogPrint(
BCLog::NET,
"failed to find an eviction candidate - connection dropped (full)\n");
1214 vNodes.push_back(pnode);
1223 std::optional<int> max_connections;
1224 switch (conn_type) {
1242 return std::count_if(vNodes.begin(), vNodes.end(), [conn_type](
CNode*
node) { return node->m_conn_type == conn_type; }););
1245 if (max_connections != std::nullopt && existing_connections >= max_connections)
return false;
1249 if (!grant)
return false;
1262 for (
CNode* pnode : vNodes) {
1263 if (!pnode->fDisconnect) {
1265 pnode->fDisconnect =
true;
1271 std::vector<CNode*> vNodesCopy = vNodes;
1272 for (
CNode* pnode : vNodesCopy)
1274 if (pnode->fDisconnect)
1277 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
1280 pnode->grantOutbound.Release();
1283 pnode->CloseSocketDisconnect();
1294 for (
CNode* pnode : vNodesDisconnectedCopy)
1297 if (pnode->GetRefCount() <= 0) {
1310 vNodesSize = vNodes.size();
1333 if (
node.nLastRecv == 0 ||
node.nLastSend == 0) {
1348 if (!
node.fSuccessfullyConnected) {
1359 recv_set.insert(hListenSocket.socket);
1364 for (
CNode* pnode : vNodes)
1377 bool select_recv = !pnode->fPauseRecv;
1380 LOCK(pnode->cs_vSend);
1381 select_send = !pnode->vSendMsg.empty();
1384 LOCK(pnode->cs_hSocket);
1388 error_set.insert(pnode->hSocket);
1390 send_set.insert(pnode->hSocket);
1394 recv_set.insert(pnode->hSocket);
1399 return !recv_set.empty() || !send_set.empty() || !error_set.empty();
1403void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
1405 std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
1411 std::unordered_map<SOCKET, struct pollfd> pollfds;
1412 for (
SOCKET socket_id : recv_select_set) {
1413 pollfds[socket_id].fd = socket_id;
1414 pollfds[socket_id].events |= POLLIN;
1417 for (
SOCKET socket_id : send_select_set) {
1418 pollfds[socket_id].fd = socket_id;
1419 pollfds[socket_id].events |= POLLOUT;
1422 for (
SOCKET socket_id : error_select_set) {
1423 pollfds[socket_id].fd = socket_id;
1425 pollfds[socket_id].events |= POLLERR|POLLHUP;
1428 std::vector<struct pollfd> vpollfds;
1429 vpollfds.reserve(pollfds.size());
1430 for (
auto it : pollfds) {
1431 vpollfds.push_back(std::move(it.second));
1438 for (
struct pollfd pollfd_entry : vpollfds) {
1439 if (pollfd_entry.revents & POLLIN) recv_set.insert(pollfd_entry.fd);
1440 if (pollfd_entry.revents & POLLOUT) send_set.insert(pollfd_entry.fd);
1441 if (pollfd_entry.revents & (POLLERR|POLLHUP)) error_set.insert(pollfd_entry.fd);
1447 std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
1456 struct timeval timeout;
1463 FD_ZERO(&fdsetRecv);
1464 FD_ZERO(&fdsetSend);
1465 FD_ZERO(&fdsetError);
1468 for (
SOCKET hSocket : recv_select_set) {
1469 FD_SET(hSocket, &fdsetRecv);
1470 hSocketMax = std::max(hSocketMax, hSocket);
1473 for (
SOCKET hSocket : send_select_set) {
1474 FD_SET(hSocket, &fdsetSend);
1475 hSocketMax = std::max(hSocketMax, hSocket);
1478 for (
SOCKET hSocket : error_select_set) {
1479 FD_SET(hSocket, &fdsetError);
1480 hSocketMax = std::max(hSocketMax, hSocket);
1483 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
1492 for (
unsigned int i = 0; i <= hSocketMax; i++)
1493 FD_SET(i, &fdsetRecv);
1494 FD_ZERO(&fdsetSend);
1495 FD_ZERO(&fdsetError);
1500 for (
SOCKET hSocket : recv_select_set) {
1501 if (FD_ISSET(hSocket, &fdsetRecv)) {
1502 recv_set.insert(hSocket);
1506 for (
SOCKET hSocket : send_select_set) {
1507 if (FD_ISSET(hSocket, &fdsetSend)) {
1508 send_set.insert(hSocket);
1512 for (
SOCKET hSocket : error_select_set) {
1513 if (FD_ISSET(hSocket, &fdsetError)) {
1514 error_set.insert(hSocket);
1522 std::set<SOCKET> recv_set, send_set, error_set;
1532 if (hListenSocket.socket !=
INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0)
1541 std::vector<CNode*> vNodesCopy;
1544 vNodesCopy = vNodes;
1545 for (
CNode* pnode : vNodesCopy)
1548 for (
CNode* pnode : vNodesCopy)
1556 bool recvSet =
false;
1557 bool sendSet =
false;
1558 bool errorSet =
false;
1560 LOCK(pnode->cs_hSocket);
1563 recvSet = recv_set.count(pnode->hSocket) > 0;
1564 sendSet = send_set.count(pnode->hSocket) > 0;
1565 errorSet = error_set.count(pnode->hSocket) > 0;
1567 if (recvSet || errorSet)
1570 uint8_t pchBuf[0x10000];
1573 LOCK(pnode->cs_hSocket);
1576 nBytes = recv(pnode->hSocket, (
char*)pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
1580 bool notify =
false;
1582 pnode->CloseSocketDisconnect();
1585 size_t nSizeAdded = 0;
1586 auto it(pnode->vRecvMsg.begin());
1587 for (; it != pnode->vRecvMsg.end(); ++it) {
1590 nSizeAdded += it->m_raw_message_size;
1593 LOCK(pnode->cs_vProcessMsg);
1594 pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
1595 pnode->nProcessQueueSize += nSizeAdded;
1601 else if (nBytes == 0)
1604 if (!pnode->fDisconnect) {
1607 pnode->CloseSocketDisconnect();
1609 else if (nBytes < 0)
1615 if (!pnode->fDisconnect) {
1618 pnode->CloseSocketDisconnect();
1633 for (
CNode* pnode : vNodesCopy)
1653 fMsgProcWake =
true;
1663 Shuffle(seeds.begin(), seeds.end(), rng);
1664 int seeds_right_now = 0;
1669 seeds_right_now = seeds.size();
1674 seeds_right_now = seeds.size();
1691 for (
const std::string& seed : seeds) {
1692 if (seeds_right_now == 0) {
1696 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
1697 std::chrono::seconds to_wait = seeds_wait_time;
1698 while (to_wait.count() > 0) {
1709 for (
const CNode* pnode : vNodes) {
1710 if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
1713 if (nRelevant >= 2) {
1715 LogPrintf(
"%d addresses found from DNS seeds\n", found);
1716 LogPrintf(
"P2P peers available. Finished DNS seeding.\n");
1718 LogPrintf(
"P2P peers available. Skipped DNS seeding.\n");
1730 LogPrintf(
"Waiting for network to be reactivated before querying DNS seeds.\n");
1736 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
1740 std::vector<CNetAddr> vIPs;
1741 std::vector<CAddress> vAdd;
1743 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
1748 unsigned int nMaxIPs = 256;
1751 int nOneDay = 24*3600;
1754 vAdd.push_back(addr);
1766 LogPrintf(
"%d addresses found from DNS seeds\n", found);
1781 std::string strDest;
1784 if (m_addr_fetches.empty())
1786 strDest = m_addr_fetches.front();
1787 m_addr_fetches.pop_front();
1804 LogPrint(
BCLog::NET,
"net: setting try another outbound peer=%s\n", flag ?
"true" :
"false");
1815 int full_outbound_peers = 0;
1818 for (
const CNode* pnode : vNodes) {
1819 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
1820 ++full_outbound_peers;
1829 int block_relay_peers = 0;
1832 for (
const CNode* pnode : vNodes) {
1833 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
1834 ++block_relay_peers;
1845 if (!connect.empty())
1847 for (int64_t nLoop = 0;; nLoop++)
1850 for (
const std::string& strAddr : connect)
1854 for (
int i = 0; i < 10 && i < nLoop; i++)
1866 auto start = GetTime<std::chrono::microseconds>();
1874 if (!add_fixed_seeds) {
1875 LogPrintf(
"Fixed seeds are disabled\n");
1894 bool add_fixed_seeds_now =
false;
1896 if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
1897 add_fixed_seeds_now =
true;
1898 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and addrman is empty\n");
1902 if (!add_fixed_seeds_now && !dnsseed) {
1904 if (m_addr_fetches.empty() && vAddedNodes.empty()) {
1905 add_fixed_seeds_now =
true;
1906 LogPrintf(
"Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n");
1910 if (add_fixed_seeds_now) {
1914 add_fixed_seeds =
false;
1924 int nOutboundFullRelay = 0;
1925 int nOutboundBlockRelay = 0;
1926 std::set<std::vector<unsigned char> > setConnected;
1930 for (
const CNode* pnode : vNodes) {
1931 if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
1932 if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
1939 switch (pnode->m_conn_type) {
1953 auto now = GetTime<std::chrono::microseconds>();
1954 bool anchor =
false;
1955 bool fFeeler =
false;
2001 }
else if (now > next_feeler) {
2035 int64_t addr_last_try{0};
2075 if (nANow - addr_last_try < 600 && nTries < 30)
2117 std::vector<CAddress> ret;
2119 for (
const CNode* pnode : vNodes) {
2120 if (pnode->IsBlockOnlyConn()) {
2121 ret.push_back(pnode->addr);
2130 std::vector<AddedNodeInfo> ret;
2132 std::list<std::string> lAddresses(0);
2135 ret.reserve(vAddedNodes.size());
2136 std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), std::back_inserter(lAddresses));
2141 std::map<CService, bool> mapConnected;
2142 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2145 for (
const CNode* pnode : vNodes) {
2146 if (pnode->addr.IsValid()) {
2147 mapConnected[pnode->addr] = pnode->IsInboundConn();
2149 std::string addrName{pnode->m_addr_name};
2150 if (!addrName.empty()) {
2151 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(),
static_cast<const CService&
>(pnode->addr));
2156 for (
const std::string& strAddNode : lAddresses) {
2161 auto it = mapConnected.find(service);
2162 if (it != mapConnected.end()) {
2163 addedNode.resolvedAddress = service;
2164 addedNode.fConnected =
true;
2165 addedNode.fInbound = it->second;
2169 auto it = mapConnectedByName.find(strAddNode);
2170 if (it != mapConnectedByName.end()) {
2171 addedNode.resolvedAddress = it->second.second;
2172 addedNode.fConnected =
true;
2173 addedNode.fInbound = it->second.first;
2176 ret.emplace_back(std::move(addedNode));
2191 if (!info.fConnected) {
2229 }
else if (
FindNode(std::string(pszDest)))
2232 CNode* pnode =
ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
2242 vNodes.push_back(pnode);
2252 std::vector<CNode*> vNodesCopy;
2255 vNodesCopy = vNodes;
2256 for (
CNode* pnode : vNodesCopy) {
2261 bool fMoreWork =
false;
2266 Shuffle(vNodesCopy.begin(), vNodesCopy.end(), rng);
2268 for (
CNode* pnode : vNodesCopy)
2270 if (pnode->fDisconnect)
2275 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
2280 LOCK(pnode->cs_sendProcessing);
2290 for (
CNode* pnode : vNodesCopy)
2298 fMsgProcWake =
false;
2304 static constexpr auto err_wait_begin = 1s;
2305 static constexpr auto err_wait_cap = 5min;
2306 auto err_wait = err_wait_begin;
2308 bool advertising_listen_addr =
false;
2314 if (advertising_listen_addr && conn.
me.
IsValid()) {
2316 advertising_listen_addr =
false;
2320 if (err_wait < err_wait_cap) {
2327 if (!advertising_listen_addr) {
2329 advertising_listen_addr =
true;
2346 struct sockaddr_storage sockaddr;
2347 socklen_t len =
sizeof(sockaddr);
2348 if (!addrBind.
GetSockAddr((
struct sockaddr*)&sockaddr, &len))
2355 std::unique_ptr<Sock> sock =
CreateSock(addrBind);
2364 setsockopt(sock->Get(), SOL_SOCKET, SO_REUSEADDR, (
sockopt_arg_type)&nOne,
sizeof(
int));
2370 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_V6ONLY, (
sockopt_arg_type)&nOne,
sizeof(
int));
2373 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
2374 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (
const char*)&nProtLevel,
sizeof(
int));
2378 if (::bind(sock->Get(), (
struct sockaddr*)&sockaddr, len) ==
SOCKET_ERROR)
2409 char pszHostName[256] =
"";
2410 if (gethostname(pszHostName,
sizeof(pszHostName)) !=
SOCKET_ERROR)
2412 std::vector<CNetAddr> vaddr;
2418 LogPrintf(
"%s: %s - %s\n", __func__, pszHostName, addr.ToString());
2422#elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
2424 struct ifaddrs* myaddrs;
2425 if (getifaddrs(&myaddrs) == 0)
2427 for (
struct ifaddrs* ifa = myaddrs; ifa !=
nullptr; ifa = ifa->ifa_next)
2429 if (ifa->ifa_addr ==
nullptr)
continue;
2430 if ((ifa->ifa_flags & IFF_UP) == 0)
continue;
2431 if (strcmp(ifa->ifa_name,
"lo") == 0)
continue;
2432 if (strcmp(ifa->ifa_name,
"lo0") == 0)
continue;
2433 if (ifa->ifa_addr->sa_family == AF_INET)
2435 struct sockaddr_in* s4 = (
struct sockaddr_in*)(ifa->ifa_addr);
2440 else if (ifa->ifa_addr->sa_family == AF_INET6)
2442 struct sockaddr_in6* s6 = (
struct sockaddr_in6*)(ifa->ifa_addr);
2448 freeifaddrs(myaddrs);
2455 LogPrintf(
"%s: %s\n", __func__, active);
2469 : addrman(addrman_in), nSeed0(nSeed0In), nSeed1(nSeed1In)
2480 return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
2508 bool fBound =
false;
2509 for (
const auto& addrBind : options.
vBinds) {
2512 for (
const auto& addrBind : options.
vWhiteBinds) {
2515 for (
const auto& addr_bind : options.
onion_binds) {
2519 struct in_addr inaddr_any;
2520 inaddr_any.s_addr = htonl(INADDR_ANY);
2521 struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
2535 _(
"Failed to listen on any port. Use -listen=0 if you want this."),
2547 for (
const auto& strDest : connOptions.
vSeedNodes) {
2557 LogPrintf(
"%i block-relay-only anchors will be tried for connections.\n",
m_anchors.size());
2585 fMsgProcWake =
false;
2602 _(
"Cannot provide specific connections and have addrman find outgoing connections at the same."),
2700 std::vector<CNode*> nodes;
2702 for (
CNode* pnode : nodes) {
2703 pnode->CloseSocketDisconnect();
2740 std::vector<CAddress> addresses =
addrman.
GetAddr(max_addresses, max_pct, network);
2742 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
2743 [
this](
const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
2754 .
Write(local_socket_bytes.data(), local_socket_bytes.size())
2756 const auto current_time = GetTime<std::chrono::microseconds>();
2793 for (
const std::string& it : vAddedNodes) {
2794 if (strNode == it)
return false;
2797 vAddedNodes.push_back(strNode);
2804 for(std::vector<std::string>::iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) {
2805 if (strNode == *it) {
2806 vAddedNodes.erase(it);
2817 return vNodes.size();
2820 for (
const auto& pnode : vNodes) {
2833 vstats.reserve(vNodes.size());
2834 for (
CNode* pnode : vNodes) {
2835 vstats.emplace_back();
2836 pnode->CopyStats(vstats.back());
2837 vstats.back().m_mapped_as = pnode->addr.GetMappedAS(
addrman.
GetAsmap());
2846 pnode->fDisconnect =
true;
2854 bool disconnected =
false;
2856 for (
CNode* pnode : vNodes) {
2857 if (subnet.
Match(pnode->addr)) {
2859 pnode->fDisconnect =
true;
2860 disconnected =
true;
2863 return disconnected;
2874 for(
CNode* pnode : vNodes) {
2875 if (
id == pnode->GetId()) {
2877 pnode->fDisconnect =
true;
2887 nTotalBytesRecv += bytes;
2893 nTotalBytesSent += bytes;
2895 const auto now = GetTime<std::chrono::seconds>();
2899 nMaxOutboundCycleStartTime = now;
2900 nMaxOutboundTotalBytesSentInCycle = 0;
2904 nMaxOutboundTotalBytesSentInCycle += bytes;
2910 return nMaxOutboundLimit;
2921 if (nMaxOutboundLimit == 0)
2924 if (nMaxOutboundCycleStartTime.count() == 0)
2928 const auto now = GetTime<std::chrono::seconds>();
2929 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
2935 if (nMaxOutboundLimit == 0)
2938 if (historicalBlockServingLimit)
2943 if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
2946 else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
2955 if (nMaxOutboundLimit == 0)
2958 return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
2964 return nTotalBytesRecv;
2970 return nTotalBytesSent;
2983 addrBind(addrBindIn),
2984 m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
2985 m_inbound_onion(inbound_onion),
2986 nKeyedNetGroup(nKeyedNetGroupIn),
2988 nLocalHostNonce(nLocalHostNonceIn),
2989 m_conn_type(conn_type_in),
2990 nLocalServices(nLocalServicesIn)
2993 hSocket = hSocketIn;
2999 mapRecvBytesPerMsgCmd[msg] = 0;
3024 size_t nMessageSize = msg.data.size();
3030 TRACE6(net, outbound_message,
3040 std::vector<unsigned char> serializedHeader;
3041 pnode->
m_serializer->prepareForTransport(msg, serializedHeader);
3042 size_t nTotalSize = nMessageSize + serializedHeader.size();
3044 size_t nBytesSent = 0;
3047 bool optimisticSend(pnode->vSendMsg.empty());
3050 pnode->mapSendBytesPerMsgCmd[msg.m_type] += nTotalSize;
3051 pnode->nSendSize += nTotalSize;
3054 pnode->vSendMsg.push_back(std::move(serializedHeader));
3055 if (nMessageSize) pnode->vSendMsg.push_back(std::move(msg.data));
3065 CNode* found =
nullptr;
3067 for (
auto&& pnode : vNodes) {
3068 if(pnode->
GetId() ==
id) {
3087std::chrono::microseconds
PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval)
3089 double unscaled = -log1p(
GetRand(1ULL << 48) * -0.0000000000000035527136788 );
3090 return now + std::chrono::duration_cast<std::chrono::microseconds>(unscaled * average_interval + 0.5us);
3111 auto now = GetTime<std::chrono::microseconds>();
3114 std::string clean_addr = addr.
ToString();
3115 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3118 fs::create_directories(base_path);
3120 fs::path path = base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
3124 f.
write(msg_type.data(), msg_type.length());
3128 uint32_t size = data.
size();
bool DumpPeerAddresses(const ArgsManager &args, const AddrMan &addr)
std::vector< CAddress > ReadAnchors(const fs::path &anchors_db_path)
Read the anchor IP address database (anchors.dat)
void DumpAnchors(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::pair< CAddress, int64_t > SelectTriedCollision()
Randomly select an address in the tried table that another address is attempting to evict.
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
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Attempt to add one or more addresses to addrman's new table.
void Good(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible, possibly moving it from "new" to "tried".
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
size_t size() const
Return the number of (unique) addresses in all tables.
std::pair< CAddress, int64_t > Select(bool newOnly=false) const
Choose an address to connect to.
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.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
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.
uint32_t nTime
Always included in serialization.
Non-refcounted RAII wrapper for FILE*.
void write(const char *pch, size_t nSize)
const CMessageHeader::MessageStartChars & MessageStart() const
uint16_t GetDefaultPort() const
const std::vector< std::string > & DNSSeeds() const
Return the list of hostnames to look up for DNS seeds.
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 vNodes member...
std::condition_variable condMsgProc
std::thread threadMessageHandler
std::chrono::seconds GetMaxOutboundTimeLeftInCycle() const
returns the time left in the current max outbound cycle in case of no limit, it will always return 0
void ThreadOpenAddedConnections()
bool OutboundTargetReached(bool historicalBlockServingLimit) const
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
CClientUIInterface * m_client_interface
size_t SocketSendData(CNode &node) const EXCLUSIVE_LOCKS_REQUIRED(node.cs_vSend)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
std::vector< AddedNodeInfo > GetAddedNodeInfo() const
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 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 ...
void AddAddrFetch(const std::string &strDest)
ServiceFlags nLocalServices
Services this instance 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
std::list< CNode * > vNodesDisconnected
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
std::atomic< NodeId > nLastNodeId
std::atomic< std::chrono::microseconds > m_next_send_inv_to_incoming
bool ShouldRunInactivityChecks(const CNode &node, int64_t secs_now) const
Return true if we should disconnect the peer for failing an inactivity check.
void RecordBytesSent(uint64_t bytes)
int GetExtraBlockRelayCount() const
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 ThreadOpenConnections(std::vector< std::string > connect)
void ThreadI2PAcceptIncoming()
std::vector< CAddress > m_anchors
Addresses that were saved during the previous clean shutdown.
RecursiveMutex m_addr_fetches_mutex
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::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 This t...
bool InitBinds(const Options &options)
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
void ThreadSocketHandler()
RecursiveMutex cs_totalBytesSent
bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions)
std::thread threadOpenConnections
size_t GetNodeCount(ConnectionDirection) const
int64_t m_peer_connect_timeout
bool InactivityCheck(const CNode &node) const
Return true if the peer is inactive and should be disconnected.
CNode * FindNode(const CNetAddr &ip)
void Init(const Options &connOptions)
void GetNodeStats(std::vector< CNodeStats > &vstats) const
const uint64_t nSeed0
SipHasher seeds for deterministic randomness.
unsigned int nReceiveFloodSize
int GetExtraFullOutboundCount() const
uint64_t GetTotalBytesRecv() const
RecursiveMutex cs_totalBytesRecv
static bool NodeFullyConnected(const CNode *pnode)
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 WakeMessageHandler()
void SetNetworkActive(bool active)
void OpenNetworkConnection(const CAddress &addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *strDest, ConnectionType conn_type)
void AddWhitelistPermissionFlags(NetPermissionFlags &flags, const CNetAddr &addr) const
bool Start(CScheduler &scheduler, const Options &options)
bool GenerateSelectSet(std::set< SOCKET > &recv_set, std::set< SOCKET > &send_set, std::set< SOCKET > &error_set)
void ThreadDNSAddressSeed()
void ThreadMessageHandler()
uint64_t CalculateKeyedNetGroup(const CAddress &ad) const
bool fAddressesInitialized
std::chrono::microseconds PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::seconds average_interval)
Attempts to obfuscate tx time through exponentially distributed emitting.
RecursiveMutex cs_vAddedNodes
std::thread threadOpenAddedConnections
bool CheckIncomingNonce(uint64_t nonce)
int m_max_outbound_full_relay
void RecordBytesRecv(uint64_t bytes)
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...
NetEventsInterface * m_msgproc
std::atomic< bool > fNetworkActive
std::atomic_bool m_start_extra_block_relay_peers
flag for initiating extra block-relay-only peer connections.
CConnman(uint64_t seed0, uint64_t seed1, AddrMan &addrman, bool network_active=true)
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...
bool AddNode(const std::string &node)
std::thread threadSocketHandler
uint64_t GetTotalBytesSent() const
bool RemoveAddedNode(const std::string &node)
void AcceptConnection(const ListenSocket &hListenSocket)
bool BindListenPort(const CService &bindAddr, bilingual_str &strError, NetPermissionFlags permissions)
Double ended buffer combining vector and stream-like interfaces.
void resize(size_type n, value_type c=0)
void Finalize(Span< unsigned char > output)
CHash256 & Write(Span< const unsigned char > input)
Network GetNetClass() const
std::string ToStringIP() const
void SetIP(const CNetAddr &ip)
std::vector< unsigned char > GetAddrBytes() const
std::string ToString() const
Network m_net
Network to which this address belongs.
bool SetInternal(const std::string &name)
Create an "internal" address that represents a name or FQDN.
std::vector< unsigned char > GetGroup(const std::vector< bool > &asmap) const
Get the canonical identifier of our network group.
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.
std::atomic< int64_t > nLastSend
std::atomic< int > nVersion
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
void SetAddrLocal(const CService &addrLocalIn)
May not be called more than once.
std::atomic< bool > m_bip152_highbandwidth_from
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
std::atomic< ServiceFlags > nServices
bool ReceiveMsgBytes(Span< const uint8_t > msg_bytes, bool &complete)
Receive bytes from the buffer and deserialize them into messages.
RecursiveMutex cs_addrLocal
CSemaphoreGrant grantOutbound
const int64_t nTimeConnected
Unix epoch time at peer connection, in seconds.
void CopyStats(CNodeStats &stats)
void CloseSocketDisconnect()
std::unique_ptr< TransportSerializer > m_serializer
std::atomic_bool fPauseSend
std::unique_ptr< TxRelay > m_tx_relay
std::unique_ptr< TransportDeserializer > m_deserializer
NetPermissionFlags m_permissionFlags
std::atomic< int64_t > nLastRecv
std::atomic< int64_t > nLastTXTime
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
const ConnectionType m_conn_type
Network ConnectedThroughNetwork() const
Get network the peer connected through.
std::atomic< std::chrono::microseconds > m_last_ping_time
Last measured round-trip time.
CNode(NodeId id, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
ServiceFlags GetLocalServices() const
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::microseconds > m_min_ping_time
Lowest measured round-trip time.
std::atomic< int64_t > nLastBlockTime
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::atomic_bool fDisconnect
CService GetAddrLocal() const
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta)
Repeat f until the scheduler is stopped.
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 It is treated as if this was the little-endian interpretation of ...
std::string ToString() const
bool Match(const CNetAddr &addr) const
bool sleep_for(std::chrono::milliseconds rel_time)
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual void InitializeNode(CNode *pnode)=0
Initialize a peer (setup state, queue any initial messages)
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode -> cs_sendProcessing)=0
Send queued protocol messages to a given node.
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt)=0
Process protocol messages received from a given node.
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)
A Span is an object that can refer to a contiguous sequence of objects.
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
const CChainParams & m_chain_params
CNetMessage GetMessage(std::chrono::microseconds time, bool &reject_message) override
const uint256 & GetMessageHash() const
int readData(Span< const uint8_t > msg_bytes)
int readHeader(Span< const uint8_t > msg_bytes)
bool Complete() const override
void prepareForTransport(CSerializedNetMsg &msg, std::vector< unsigned char > &header) override
Path class wrapper to prepare application code for transition from boost::filesystem library to std::...
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
#define WSAGetLastError()
static bool IsSelectableSocket(const SOCKET &s)
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE
The maximum allowed size for a serialized block, in bytes (only for buffer size limits)
static uint32_t ReadLE32(const unsigned char *ptr)
static CService ip(uint32_t i)
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
#define LogPrint(category,...)
FILE * fopen(const fs::path &p, const char *mode)
void TraceThread(const char *thread_name, std::function< void()> thread_func)
A wrapper for do-something-once thread functions.
CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
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
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
bool AddLocal(const CService &addr_, int nScore)
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)
RecursiveMutex cs_mapLocalHost
static bool ReverseCompareNodeTimeConnected(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
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::map< CNetAddr, LocalServiceInfo > mapLocalHost GUARDED_BY(cs_mapLocalHost)
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< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
void CaptureMessage(const CAddress &addr, const std::string &msg_type, const Span< const unsigned char > &data, bool is_incoming)
Dump binary message to file, with timestamp.
std::optional< CAddress > GetLocalAddrForPeer(CNode *pnode)
Returns a local address that we should advertise to this peer.
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)
const char *const ANCHORS_DATABASE_FILENAME
Anchor IP address database file name.
CService MaybeFlipIPv6toCJDNS(const CService &service)
If an IPv6 address belongs to the address range used by the CJDNS network and the CJDNS network is re...
static std::vector< CAddress > ConvertSeeds(const std::vector< uint8_t > &vSeedsIn)
Convert the serialized seeds into usable address objects.
#define FEELER_SLEEP_WINDOW
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 bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static CNetCleanup instance_of_cnetcleanup
static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME
The default timeframe for -maxuploadtarget.
bool IsReachable(enum Network net)
bool SeenLocal(const CService &addr)
vote for a local address
std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future (in microseconds) for exponentially distributed events.
static constexpr bool DEFAULT_FIXEDSEEDS
static const bool DEFAULT_WHITELISTFORCERELAY
Default for -whitelistforcerelay.
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH
Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable).
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 int TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr bool DEFAULT_FORCEDNSSEED
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 requested via the addnode RPC or the -a...
@ 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.
@ ADDR_FETCH
AddrFetch connections are short lived connections used to solicit addresses from peers.
static constexpr bool DEFAULT_DNSSEED
static constexpr auto FEELER_INTERVAL
Run the feeler connection loop once every 2 minutes.
static const int MAX_BLOCK_RELAY_ONLY_CONNECTIONS
Maximum number of block-relay-only outgoing connections.
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
@ 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...
std::function< std::unique_ptr< Sock >(const CService &)> CreateSock
Socket factory.
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.
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 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()
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.
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
int GetRandInt(int nMax) noexcept
constexpr auto GetRandMillis
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
void ser_writedata32(Stream &s, uint32_t obj)
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
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.
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....
std::vector< unsigned char > 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::microseconds m_min_ping_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 WITH_LOCK(cs, code)
Run code while locking a mutex.
void SetSyscallSandboxPolicy(SyscallSandboxPolicy syscall_policy)
Force the current thread (and threads created from the current thread) into a restricted-service oper...
@ INITIALIZATION_DNS_SEED
bool error(const char *fmt, const Args &... args)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTimeMillis()
Returns the system time (not mockable)
int64_t GetTimeSeconds()
Returns the system time (not mockable)
int64_t GetTime()
DEPRECATED Use either GetTimeSeconds (not mockable) or GetTime<T> (mockable)
int64_t GetAdjustedTime()
#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
static const int PROTOCOL_VERSION
network protocol versioning