6#if defined(HAVE_CONFIG_H)
7#include <config/bitcoin-config.h>
56#include <unordered_map>
62 "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed "
63 "MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
95#define FEELER_SLEEP_WINDOW 1
129std::map<CNetAddr, LocalServiceInfo>
135 m_addr_fetches.push_back(strDest);
141 for (
const std::string &bind_arg :
gArgs.
GetArgs(
"-bind")) {
143 constexpr uint16_t dummy_port = 0;
145 if (
Lookup(bind_arg, bind_addr, dummy_port,
false)) {
146 if (bind_addr.
GetPort() != dummy_port) {
155 for (
const std::string &whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
169 return static_cast<uint16_t
>(
180 int nBestReachability = -1;
183 for (
const auto &entry : mapLocalHost) {
184 int nScore = entry.second.nScore;
185 int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
186 if (nReachability > nBestReachability ||
187 (nReachability == nBestReachability && nScore > nBestScore)) {
188 addr =
CService(entry.first, entry.second.nPort);
189 nBestReachability = nReachability;
194 return nBestScore >= 0;
198static std::vector<CAddress>
203 const auto one_week{7 * 24h};
204 std::vector<CAddress> vSeedsOut;
205 vSeedsOut.reserve(vSeedsIn.size());
207 for (
const auto &seed_in : vSeedsIn) {
209 memcpy(&ip, seed_in.addr,
sizeof(ip));
214 vSeedsOut.push_back(addr);
233 const auto it = mapLocalHost.find(addr);
234 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
255 (!addrLocal.IsRoutable() ||
257 if (
node.IsInboundConn()) {
266 addrLocal.SetIP(
node.GetAddrLocal());
269 if (addrLocal.IsRoutable() ||
gArgs.
GetBoolArg(
"-addrmantest",
false)) {
271 addrLocal.ToString(),
node.GetId());
296 const auto [it, is_newly_added] =
299 if (is_newly_added || nScore >= info.
nScore) {
300 info.
nScore = nScore + !is_newly_added;
315 mapLocalHost.erase(addr);
323 vfLimited[net] = !reachable;
328 return !vfLimited[net];
338 const auto it = mapLocalHost.find(addr);
339 if (it == mapLocalHost.end()) {
349 return mapLocalHost.count(addr) > 0;
354 for (
CNode *pnode : m_nodes) {
355 if (
static_cast<CNetAddr>(pnode->addr) == ip) {
364 for (
CNode *pnode : m_nodes) {
374 for (
CNode *pnode : m_nodes) {
375 if (pnode->m_addr_name == addrName) {
384 for (
CNode *pnode : m_nodes) {
385 if (
static_cast<CService>(pnode->addr) == addr) {
399 for (
const CNode *pnode : m_nodes) {
400 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() &&
401 pnode->GetLocalNonce() == nonce) {
411 struct sockaddr_storage sockaddr_bind;
412 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
414 if (!getsockname(sock, (
struct sockaddr *)&sockaddr_bind,
415 &sockaddr_bind_len)) {
416 addr_bind.
SetSockAddr((
const struct sockaddr *)&sockaddr_bind);
419 "getsockname failed\n");
429 if (pszDest ==
nullptr) {
437 LogPrintf(
"Failed to open new connection, already connected\n");
443 "trying connection %s lastseen=%.1fhrs\n",
444 pszDest ? pszDest : addrConnect.
ToString(),
446 pszDest ? 0h : Now<NodeSeconds>() - addrConnect.
nTime));
449 const uint16_t default_port{pszDest !=
nullptr
453 std::vector<CService> resolved;
454 if (
Lookup(pszDest, resolved, default_port,
461 "Resolver returned invalid address %s for %s\n",
471 LogPrintf(
"Failed to open new connection, already connected\n");
478 bool connected =
false;
479 std::unique_ptr<Sock> sock;
485 bool proxyConnectionFailed =
false;
491 proxyConnectionFailed)) {
493 sock = std::move(conn.
sock);
514 if (!proxyConnectionFailed) {
526 uint16_t port{default_port};
528 bool proxyConnectionFailed;
537 std::vector<NetWhitelistPermissions> whitelist_permissions =
540 : std::vector<NetWhitelistPermissions>{};
542 whitelist_permissions);
549 uint64_t extra_entropy =
558 nonce, extra_entropy, addr_bind, pszDest ? pszDest :
"", conn_type,
584 const std::vector<NetWhitelistPermissions> &ranges)
const {
585 for (
const auto &subnet : ranges) {
586 if (subnet.m_subnet.Match(addr)) {
612 if (addrLocal.IsValid()) {
613 error(
"Addr local already set for node: %i. Refusing to change from %s "
615 id, addrLocal.ToString(), addrLocalIn.
ToString());
617 addrLocal = addrLocalIn;
676 const auto time = GetTime<std::chrono::microseconds>();
678 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
679 nRecvBytes += msg_bytes.
size();
680 while (msg_bytes.
size() > 0) {
693 mapMsgTypeSize::iterator i =
694 mapRecvBytesPerMsgType.find(msg.
m_type);
695 if (i == mapRecvBytesPerMsgType.end()) {
699 assert(i != mapRecvBytesPerMsgType.end());
716 uint32_t nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
729 }
catch (
const std::exception &) {
747 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
772 const std::chrono::microseconds time) {
800 "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
816 std::vector<uint8_t> &header)
const {
831 size_t nSentSize = 0;
832 size_t nMsgCount = 0;
834 for (
auto it =
node.vSendMsg.begin(); it !=
node.vSendMsg.end(); ++it) {
835 const auto &data = *it;
846 if (it + 1 !=
node.vSendMsg.end()) {
850 nBytes =
node.m_sock->Send(
851 reinterpret_cast<const char *
>(data.data()) +
node.nSendOffset,
867 node.CloseSocketDisconnect();
874 node.m_last_send = GetTime<std::chrono::seconds>();
875 node.nSendBytes += nBytes;
876 node.nSendOffset += nBytes;
878 if (
node.nSendOffset != data.size()) {
883 node.nSendOffset = 0;
884 node.nSendSize -= data.size();
889 node.vSendMsg.erase(
node.vSendMsg.begin(),
890 node.vSendMsg.begin() + nMsgCount);
892 if (
node.vSendMsg.empty()) {
897 return {nSentSize, !
node.vSendMsg.empty()};
908 std::vector<NodeEvictionCandidate> vEvictionCandidates;
912 if (
node->fDisconnect) {
918 .m_connected =
node->m_connected,
919 .m_min_ping_time =
node->m_min_ping_time,
920 .m_last_block_time =
node->m_last_block_time,
921 .m_last_proof_time =
node->m_last_proof_time,
922 .m_last_tx_time =
node->m_last_tx_time,
923 .fRelevantServices =
node->m_has_all_wanted_services,
924 .m_relay_txs =
node->m_relays_txs.load(),
925 .fBloomFilter =
node->m_bloom_filter_loaded.load(),
926 .nKeyedNetGroup =
node->nKeyedNetGroup,
927 .prefer_evict =
node->m_prefer_evict,
928 .m_is_local =
node->addr.IsLocal(),
929 .m_network =
node->ConnectedThroughNetwork(),
931 .m_conn_type =
node->m_conn_type,
933 node->m_avalanche_enabled
934 ?
node->getAvailabilityScore()
935 : -std::numeric_limits<double>::infinity()};
936 vEvictionCandidates.push_back(candidate);
939 const std::optional<NodeId> node_id_to_evict =
941 if (!node_id_to_evict) {
945 for (
CNode *pnode : m_nodes) {
946 if (pnode->GetId() == *node_id_to_evict) {
949 "selected %s connection for eviction peer=%d; disconnecting\n",
950 pnode->ConnectionTypeAsString(), pnode->GetId());
951 pnode->fDisconnect =
true;
959 struct sockaddr_storage sockaddr;
960 socklen_t len =
sizeof(sockaddr);
961 auto sock = hListenSocket.
sock->Accept((
struct sockaddr *)&sockaddr, &len);
967 LogPrintf(
"socket error accept failed: %s\n",
973 if (!addr.
SetSockAddr((
const struct sockaddr *)&sockaddr)) {
975 "Unknown socket family\n");
999 for (
const CNode *pnode : m_nodes) {
1000 if (pnode->IsInboundConn()) {
1008 "connection from %s dropped: not accepting new connections\n",
1014 LogPrintf(
"connection from %s dropped: non-selectable socket\n",
1036 nInbound + 1 >= nMaxInbound && discouraged) {
1042 if (nInbound >= nMaxInbound) {
1046 "connection dropped (full)\n");
1055 uint64_t extra_entropy =
1060 const bool inbound_onion =
1068 .prefer_evict = discouraged,
1080 m_nodes.push_back(pnode);
1090 std::optional<int> max_connections;
1091 switch (conn_type) {
1113 int existing_connections =
1115 return std::count_if(
1116 m_nodes.begin(), m_nodes.end(), [conn_type](
CNode *
node) {
1117 return node->m_conn_type == conn_type;
1121 if (max_connections != std::nullopt &&
1122 existing_connections >= max_connections) {
1143 for (
CNode *pnode : m_nodes) {
1144 if (!pnode->fDisconnect) {
1146 "Network not active, dropping peer=%d\n",
1148 pnode->fDisconnect =
true;
1154 std::vector<CNode *> nodes_copy = m_nodes;
1155 for (
CNode *pnode : nodes_copy) {
1156 if (pnode->fDisconnect) {
1158 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode),
1162 pnode->grantOutbound.Release();
1165 pnode->CloseSocketDisconnect();
1176 for (
CNode *pnode : nodes_disconnected_copy) {
1179 if (pnode->GetRefCount() <= 0) {
1191 nodes_size = m_nodes.size();
1202 std::chrono::seconds now)
const {
1209 const auto now{GetTime<std::chrono::seconds>()};
1210 const auto last_send{
node.m_last_send.load()};
1211 const auto last_recv{
node.m_last_recv.load()};
1217 if (last_recv.count() == 0 || last_send.count() == 0) {
1219 "socket no message in first %i seconds, %d %d peer=%d\n",
1221 last_send.count() != 0,
node.GetId());
1237 if (!
node.fSuccessfullyConnected) {
1250 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
1253 for (
CNode *pnode : nodes) {
1254 bool select_recv = !pnode->fPauseRecv;
1256 WITH_LOCK(pnode->cs_vSend,
return !pnode->vSendMsg.empty());
1257 if (!select_recv && !select_send) {
1261 LOCK(pnode->m_sock_mutex);
1262 if (pnode->m_sock) {
1265 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
1269 return events_per_sock;
1278 const auto timeout =
1286 if (events_per_sock.empty() ||
1287 !events_per_sock.begin()->first->WaitMany(timeout,
1301 const std::vector<CNode *> &nodes,
1303 for (
CNode *pnode : nodes) {
1311 bool recvSet =
false;
1312 bool sendSet =
false;
1313 bool errorSet =
false;
1315 LOCK(pnode->m_sock_mutex);
1316 if (!pnode->m_sock) {
1319 const auto it = events_per_sock.find(pnode->m_sock);
1320 if (it != events_per_sock.end()) {
1323 errorSet = it->second.occurred &
Sock::ERR;
1329 auto [bytes_sent, data_left] =
1348 if (recvSet || errorSet) {
1350 uint8_t pchBuf[0x10000];
1353 LOCK(pnode->m_sock_mutex);
1354 if (!pnode->m_sock) {
1358 pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
1361 bool notify =
false;
1362 if (!pnode->ReceiveMsgBytes(*
config, {pchBuf, (size_t)nBytes},
1364 pnode->CloseSocketDisconnect();
1368 pnode->MarkReceivedMsgsForProcessing();
1371 }
else if (nBytes == 0) {
1373 if (!pnode->fDisconnect) {
1377 pnode->CloseSocketDisconnect();
1378 }
else if (nBytes < 0) {
1383 if (!pnode->fDisconnect) {
1385 "socket recv error for peer=%d: %s\n",
1388 pnode->CloseSocketDisconnect();
1394 pnode->fDisconnect =
true;
1405 const auto it = events_per_sock.find(listen_socket.sock);
1406 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
1423 fMsgProcWake =
true;
1430 std::vector<std::string> seeds =
1433 int seeds_right_now = 0;
1438 seeds_right_now = seeds.size();
1443 seeds_right_now = seeds.size();
1458 const std::chrono::seconds seeds_wait_time =
1463 for (
const std::string &seed : seeds) {
1464 if (seeds_right_now == 0) {
1468 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n",
1469 seeds_wait_time.count());
1470 std::chrono::seconds to_wait = seeds_wait_time;
1471 while (to_wait.count() > 0) {
1475 std::chrono::seconds w =
1485 for (
const CNode *pnode : m_nodes) {
1486 if (pnode->fSuccessfullyConnected &&
1487 pnode->IsFullOutboundConn()) {
1492 if (nRelevant >= 2) {
1494 LogPrintf(
"%d addresses found from DNS seeds\n",
1497 "P2P peers available. Finished DNS seeding.\n");
1500 "P2P peers available. Skipped DNS seeding.\n");
1514 LogPrintf(
"Waiting for network to be reactivated before querying "
1523 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
1527 std::vector<CNetAddr> vIPs;
1528 std::vector<CAddress> vAdd;
1531 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
1538 unsigned int nMaxIPs = 256;
1543 requiredServiceBits);
1546 Now<NodeSeconds>() - 3 * 24h, -4 * 24h);
1547 vAdd.push_back(addr);
1560 LogPrintf(
"%d addresses found from DNS seeds\n", found);
1573 std::string strDest;
1576 if (m_addr_fetches.empty()) {
1579 strDest = m_addr_fetches.front();
1580 m_addr_fetches.pop_front();
1597 flag ?
"true" :
"false");
1607 int full_outbound_peers = 0;
1610 for (
const CNode *pnode : m_nodes) {
1611 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
1612 pnode->IsFullOutboundConn()) {
1613 ++full_outbound_peers;
1623 int block_relay_peers = 0;
1626 for (
const CNode *pnode : m_nodes) {
1627 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
1628 pnode->IsBlockOnlyConn()) {
1629 ++block_relay_peers;
1637 const std::vector<std::string> connect,
1640 if (!connect.empty()) {
1641 for (int64_t nLoop = 0;; nLoop++) {
1643 for (
const std::string &strAddr : connect) {
1647 for (
int i = 0; i < 10 && i < nLoop; i++) {
1649 std::chrono::milliseconds(500))) {
1661 auto start = GetTime<std::chrono::microseconds>();
1665 auto next_extra_block_relay =
1671 if (!add_fixed_seeds) {
1672 LogPrintf(
"Fixed seeds are disabled\n");
1679 if (!mockOpenConnection &&
1695 bool add_fixed_seeds_now =
false;
1697 if (GetTime<std::chrono::seconds>() >
1698 start + std::chrono::minutes{1}) {
1699 add_fixed_seeds_now =
true;
1700 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and "
1701 "addrman is empty\n");
1702 }
else if (!dnsseed && !use_seednodes) {
1705 if (m_added_nodes.empty()) {
1706 add_fixed_seeds_now =
true;
1707 LogPrintf(
"Adding fixed seeds as -dnsseed=0 and neither "
1708 "-addnode nor -seednode are provided\n");
1712 if (add_fixed_seeds_now) {
1717 add_fixed_seeds =
false;
1727 int nOutboundFullRelay = 0;
1728 int nOutboundBlockRelay = 0;
1729 int nOutboundAvalanche = 0;
1730 std::set<std::vector<uint8_t>> setConnected;
1734 for (
const CNode *pnode : m_nodes) {
1735 if (pnode->IsAvalancheOutboundConnection()) {
1736 nOutboundAvalanche++;
1737 }
else if (pnode->IsFullOutboundConn()) {
1738 nOutboundFullRelay++;
1739 }
else if (pnode->IsBlockOnlyConn()) {
1740 nOutboundBlockRelay++;
1750 switch (pnode->m_conn_type) {
1759 setConnected.insert(
1767 auto now = GetTime<std::chrono::microseconds>();
1768 bool anchor =
false;
1769 bool fFeeler =
false;
1797 }
else if (now > next_extra_block_relay &&
1821 next_extra_block_relay =
1824 }
else if (now > next_feeler) {
1848 "Trying to make an anchor connection to %s\n",
1907 if (current_time - addr_last_try < 10min && nTries < 30) {
1957 std::chrono::milliseconds(randsleep))) {
1966 if (mockOpenConnection) {
1967 mockOpenConnection(addrConnect, conn_type);
1970 int(setConnected.size()) >=
1972 &grant,
nullptr, conn_type);
1979 std::vector<CAddress> ret;
1981 for (
const CNode *pnode : m_nodes) {
1982 if (pnode->IsBlockOnlyConn()) {
1983 ret.push_back(pnode->addr);
1991 std::vector<AddedNodeInfo> ret;
1993 std::list<std::string> lAddresses(0);
1996 ret.reserve(m_added_nodes.size());
1997 std::copy(m_added_nodes.cbegin(), m_added_nodes.cend(),
1998 std::back_inserter(lAddresses));
2003 std::map<CService, bool> mapConnected;
2004 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2007 for (
const CNode *pnode : m_nodes) {
2008 if (pnode->addr.IsValid()) {
2009 mapConnected[pnode->addr] = pnode->IsInboundConn();
2011 std::string addrName{pnode->m_addr_name};
2012 if (!addrName.empty()) {
2013 mapConnectedByName[std::move(addrName)] =
2014 std::make_pair(pnode->IsInboundConn(),
2015 static_cast<const CService &
>(pnode->addr));
2020 for (
const std::string &strAddNode : lAddresses) {
2026 auto it = mapConnected.find(service);
2027 if (it != mapConnected.end()) {
2028 addedNode.resolvedAddress = service;
2029 addedNode.fConnected =
true;
2030 addedNode.fInbound = it->second;
2034 auto it = mapConnectedByName.find(strAddNode);
2035 if (it != mapConnectedByName.end()) {
2036 addedNode.resolvedAddress = it->second.second;
2037 addedNode.fConnected =
true;
2038 addedNode.fInbound = it->second.first;
2041 ret.emplace_back(std::move(addedNode));
2053 if (!info.fConnected) {
2063 info.strAddedNode.c_str(),
2082 const char *pszDest,
2096 bool banned_or_discouraged =
2099 if (
IsLocal(addrConnect) || banned_or_discouraged ||
2103 }
else if (
FindNode(std::string(pszDest))) {
2107 CNode *pnode =
ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
2112 if (grantOutbound) {
2122 m_nodes.push_back(pnode);
2132 bool fMoreWork =
false;
2140 for (
CNode *pnode : snap.Nodes()) {
2141 if (pnode->fDisconnect) {
2145 bool fMoreNodeWork =
false;
2148 fMoreNodeWork |= interface->ProcessMessages(
2151 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
2158 interface->SendMessages(*
config, pnode);
2170 std::chrono::steady_clock::now() +
2171 std::chrono::milliseconds(100),
2175 fMsgProcWake =
false;
2180 static constexpr auto err_wait_begin = 1s;
2181 static constexpr auto err_wait_cap = 5min;
2182 auto err_wait = err_wait_begin;
2184 bool advertising_listen_addr =
false;
2189 if (advertising_listen_addr && conn.
me.
IsValid()) {
2191 advertising_listen_addr =
false;
2195 if (err_wait < err_wait_cap) {
2202 if (!advertising_listen_addr) {
2204 advertising_listen_addr =
true;
2222 struct sockaddr_storage sockaddr;
2223 socklen_t len =
sizeof(sockaddr);
2224 if (!addrBind.
GetSockAddr((
struct sockaddr *)&sockaddr, &len)) {
2233 std::unique_ptr<Sock> sock =
CreateSock(addrBind);
2237 "connections (socket returned error %s)"),
2254 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_V6ONLY,
2258 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
2259 setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_PROTECTION_LEVEL,
2264 if (::bind(sock->Get(), (
struct sockaddr *)&sockaddr, len) ==
2268 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s "
2269 "is probably already running."),
2270 addrBind.
ToString(), PACKAGE_NAME);
2272 strError =
strprintf(
_(
"Unable to bind to %s on this computer "
2273 "(bind returned error %s)"),
2285 strError =
strprintf(
_(
"Listening for incoming connections "
2286 "failed (listen returned error %s)"),
2304 char pszHostName[256] =
"";
2305 if (gethostname(pszHostName,
sizeof(pszHostName)) !=
SOCKET_ERROR) {
2306 std::vector<CNetAddr> vaddr;
2307 if (
LookupHost(pszHostName, vaddr, 0,
true)) {
2308 for (
const CNetAddr &addr : vaddr) {
2310 LogPrintf(
"%s: %s - %s\n", __func__, pszHostName,
2316#elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
2318 struct ifaddrs *myaddrs;
2319 if (getifaddrs(&myaddrs) == 0) {
2320 for (
struct ifaddrs *ifa = myaddrs; ifa !=
nullptr;
2321 ifa = ifa->ifa_next) {
2322 if (ifa->ifa_addr ==
nullptr || (ifa->ifa_flags & IFF_UP) == 0 ||
2323 strcmp(ifa->ifa_name,
"lo") == 0 ||
2324 strcmp(ifa->ifa_name,
"lo0") == 0) {
2327 if (ifa->ifa_addr->sa_family == AF_INET) {
2328 struct sockaddr_in *s4 =
2329 reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
2332 LogPrintf(
"%s: IPv4 %s: %s\n", __func__, ifa->ifa_name,
2335 }
else if (ifa->ifa_addr->sa_family == AF_INET6) {
2336 struct sockaddr_in6 *s6 =
2337 reinterpret_cast<struct sockaddr_in6 *
>(ifa->ifa_addr);
2340 LogPrintf(
"%s: IPv6 %s: %s\n", __func__, ifa->ifa_name,
2345 freeifaddrs(myaddrs);
2351 LogPrintf(
"%s: %s\n", __func__, active);
2365 AddrMan &addrmanIn,
bool network_active)
2366 : config(&configIn), addrman(addrmanIn), nSeed0(nSeed0In),
2402 for (
const auto &addrBind : options.
vBinds) {
2408 for (
const auto &addrBind : options.
vWhiteBinds) {
2410 addrBind.m_flags)) {
2414 for (
const auto &addr_bind : options.
onion_binds) {
2424 const CService ipv6_any{in6_addr(IN6ADDR_ANY_INIT),
2428 struct in_addr inaddr_any;
2429 inaddr_any.s_addr = htonl(INADDR_ANY);
2444 _(
"Failed to listen on any port. Use -listen=0 if you want "
2458 for (
const auto &strDest : connOptions.
vSeedNodes) {
2471 "%i block-relay-only anchors will be tried for connections.\n",
2477 _(
"Starting network threads...").translated);
2502 fMsgProcWake =
false;
2524 _(
"Cannot provide specific connections and have addrman find "
2525 "outgoing connections at the same."),
2535 ThreadOpenConnections(connect, nullptr);
2625 std::vector<CAddress> anchors_to_dump =
2637 std::vector<CNode *> nodes;
2639 for (
CNode *pnode : nodes) {
2640 pnode->CloseSocketDisconnect();
2656 interface->FinalizeNode(*
config, *pnode);
2666std::vector<CAddress>
2668 std::optional<Network> network)
const {
2669 std::vector<CAddress> addresses =
2672 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
2674 return m_banman->IsDiscouraged(
2676 m_banman->IsBanned(addr);
2683std::vector<CAddress>
2689 .
Write(local_socket_bytes.data(), local_socket_bytes.size())
2691 const auto current_time = GetTime<std::chrono::microseconds>();
2727 current_time + std::chrono::hours(21) +
2735 for (
const std::string &it : m_added_nodes) {
2736 if (strNode == it) {
2741 m_added_nodes.push_back(strNode);
2747 for (std::vector<std::string>::iterator it = m_added_nodes.begin();
2748 it != m_added_nodes.end(); ++it) {
2749 if (strNode == *it) {
2750 m_added_nodes.erase(it);
2761 return m_nodes.size();
2765 for (
const auto &pnode : m_nodes) {
2778 vstats.reserve(m_nodes.size());
2779 for (
CNode *pnode : m_nodes) {
2780 vstats.emplace_back();
2781 pnode->copyStats(vstats.back());
2782 vstats.back().m_mapped_as = pnode->addr.GetMappedAS(
addrman.
GetAsmap());
2789 for (
auto &&pnode : m_nodes) {
2790 if (pnode->GetId() ==
id) {
2791 pnode->copyStats(stats);
2804 "disconnect by address%s matched peer=%d; disconnecting\n",
2806 pnode->fDisconnect =
true;
2813 bool disconnected =
false;
2815 for (
CNode *pnode : m_nodes) {
2816 if (subnet.
Match(pnode->addr)) {
2818 "disconnect by subnet%s matched peer=%d; disconnecting\n",
2821 pnode->fDisconnect =
true;
2822 disconnected =
true;
2825 return disconnected;
2834 for (
CNode *pnode : m_nodes) {
2835 if (
id == pnode->GetId()) {
2838 pnode->fDisconnect =
true;
2851 nTotalBytesSent += bytes;
2853 const auto now = GetTime<std::chrono::seconds>();
2856 nMaxOutboundCycleStartTime = now;
2857 nMaxOutboundTotalBytesSentInCycle = 0;
2861 nMaxOutboundTotalBytesSentInCycle += bytes;
2866 return nMaxOutboundLimit;
2875 if (nMaxOutboundLimit == 0) {
2879 if (nMaxOutboundCycleStartTime.count() == 0) {
2883 const std::chrono::seconds cycleEndTime =
2885 const auto now = GetTime<std::chrono::seconds>();
2886 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
2891 if (nMaxOutboundLimit == 0) {
2895 if (historicalBlockServingLimit) {
2897 const std::chrono::seconds timeLeftInCycle =
2899 const uint64_t buffer =
2900 timeLeftInCycle / std::chrono::minutes{10} *
ONE_MEGABYTE;
2901 if (buffer >= nMaxOutboundLimit ||
2902 nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer) {
2905 }
else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) {
2914 if (nMaxOutboundLimit == 0) {
2918 return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
2920 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
2929 return nTotalBytesSent;
2949 uint64_t windowInvCounters =
invCounters.exchange(0);
2952 int64_t polls = windowInvCounters & std::numeric_limits<uint32_t>::max();
2953 int64_t votes = windowInvCounters >> 32;
2956 decayFactor * (2 * votes - polls) + (1. - decayFactor) * previousScore;
2966 uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn,
2967 uint64_t nLocalExtraEntropyIn,
const CAddress &addrBindIn,
2975 m_permission_flags{node_opts.permission_flags}, m_sock{sock},
2976 m_connected(
GetTime<
std::chrono::seconds>()), addr(addrIn),
2977 addrBind(addrBindIn),
2978 m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
2979 m_inbound_onion(inbound_onion), m_prefer_evict{node_opts.prefer_evict},
2980 nKeyedNetGroup(nKeyedNetGroupIn), m_conn_type(conn_type_in), id(idIn),
2981 nLocalHostNonce(nLocalHostNonceIn),
2982 nLocalExtraEntropy(nLocalExtraEntropyIn),
2983 m_recv_flood_size{node_opts.recv_flood_size} {
2984 if (inbound_onion) {
2989 mapRecvBytesPerMsgType[msg] = 0;
3004 size_t nSizeAdded = 0;
3009 nSizeAdded += msg.m_raw_message_size;
3013 m_msg_process_queue.splice(m_msg_process_queue.end(),
vRecvMsg);
3014 m_msg_process_queue_size += nSizeAdded;
3020 if (m_msg_process_queue.empty()) {
3021 return std::nullopt;
3024 std::list<CNetMessage> msgs;
3026 msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
3027 m_msg_process_queue_size -= msgs.front().m_raw_message_size;
3030 return std::make_pair(std::move(msgs.front()),
3031 !m_msg_process_queue.empty());
3039 size_t nMessageSize = msg.data.size();
3041 nMessageSize, pnode->
GetId());
3049 msg.data.size(), msg.data.data());
3052 std::vector<uint8_t> serializedHeader;
3054 size_t nTotalSize = nMessageSize + serializedHeader.size();
3056 size_t nBytesSent = 0;
3059 bool optimisticSend(pnode->vSendMsg.empty());
3063 pnode->nSendSize += nTotalSize;
3068 pnode->vSendMsg.push_back(std::move(serializedHeader));
3070 pnode->vSendMsg.push_back(std::move(msg.data));
3075 if (optimisticSend) {
3085 CNode *found =
nullptr;
3087 for (
auto &&pnode : m_nodes) {
3088 if (pnode->
GetId() ==
id) {
3104 .
Write(vchNetGroup.data(), vchNetGroup.size())
3126 std::stringstream ebMBs;
3128 std::string eb = ebMBs.str();
3129 eb.insert(eb.size() - 1,
".", 1);
3130 if (eb.substr(0, 1) ==
".") {
3139 std::vector<std::string> uacomments;
3140 uacomments.push_back(
"EB" + eb);
3144 for (
const std::string &cmt :
gArgs.
GetArgs(
"-uacomment")) {
3145 uacomments.push_back(cmt);
3149 const std::string client_version =
3162 auto now = GetTime<std::chrono::microseconds>();
3165 std::string clean_addr = addr.
ToString();
3166 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3172 base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
3181 uint32_t size = data.
size();
3186std::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.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
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 ...
bool GetTryNewOutboundPeer() const
int m_max_outbound_block_relay
std::thread threadI2PAcceptIncoming
void SetTryNewOutboundPeer(bool flag)
std::atomic< bool > flagInterruptMsgProc
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
std::atomic< ServiceFlags > nLocalServices
Services this node offers.
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_bool fPauseRecv
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
void MarkReceivedMsgsForProcessing() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Move all messages from the received queue to the processing queue.
Mutex m_subver_mutex
cleanSubVer is a sanitized string of the user agent byte array we read from the wire.
const std::unique_ptr< const TransportSerializer > m_serializer
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
double getAvailabilityScore() const
Mutex m_msg_process_queue_mutex
const ConnectionType m_conn_type
Network ConnectedThroughNetwork() const
Get network the peer connected through.
const size_t m_recv_flood_size
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.
void AccountForSentBytes(const std::string &msg_type, size_t sent_bytes) EXCLUSIVE_LOCKS_REQUIRED(cs_vSend)
Account for the total size of a sent message in the per msg type connection stats.
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....
const std::unique_ptr< TransportDeserializer > m_deserializer
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) const 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()
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 const uint64_t ONE_MEGABYTE
1MB
static uint32_t ReadLE32(const uint8_t *ptr)
std::vector< std::string > GetRandomizedDNSSeeds(const CChainParams ¶ms)
Return the list of hostnames to look up for DNS seeds.
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
bool error(const char *fmt, const Args &...args)
#define LogPrintLevel(category, level,...)
#define LogPrint(category,...)
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(std::string_view thread_name, std::function< void()> thread_func)
A wrapper for do-something-once thread functions.
bool IsPeerAddrLocalGood(CNode *pnode)
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
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 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::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
const std::string NET_MESSAGE_TYPE_OTHER
void SetReachable(enum Network net, bool reachable)
Mark a network as reachable or unreachable (no automatic connects to it)
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)
#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)
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 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
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.
std::chrono::microseconds m_last_ping_time
mapMsgTypeSize mapRecvBytesPerMsgType
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
mapMsgTypeSize mapSendBytesPerMsgType
std::chrono::microseconds m_min_ping_time
std::chrono::seconds m_connected
bool m_bip152_highbandwidth_from
bool m_bip152_highbandwidth_to
std::chrono::seconds m_last_block_time
NetPermissionFlags m_permission_flags
std::vector< uint8_t > data
static time_point now() noexcept
Return current system time or mocked time, if set.
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