6#if defined(HAVE_CONFIG_H)
7#include <config/bitcoin-config.h>
58#include <unordered_map>
64 "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed "
65 "MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
131std::map<CNetAddr, LocalServiceInfo>
137 m_addr_fetches.push_back(strDest);
143 for (
const std::string &bind_arg :
gArgs.
GetArgs(
"-bind")) {
144 constexpr uint16_t dummy_port = 0;
146 const std::optional<CService> bind_addr{
147 Lookup(bind_arg, dummy_port,
false)};
148 if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port) {
149 return bind_addr->GetPort();
156 for (
const std::string &whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
170 return static_cast<uint16_t
>(
181 int nBestReachability = -1;
184 for (
const auto &entry : mapLocalHost) {
185 int nScore = entry.second.nScore;
186 int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
187 if (nReachability > nBestReachability ||
188 (nReachability == nBestReachability && nScore > nBestScore)) {
189 addr =
CService(entry.first, entry.second.nPort);
190 nBestReachability = nReachability;
195 return nBestScore >= 0;
199static std::vector<CAddress>
204 const auto one_week{7 * 24h};
205 std::vector<CAddress> vSeedsOut;
206 vSeedsOut.reserve(vSeedsIn.size());
209 for (
const auto &seed_in : vSeedsIn) {
211 memcpy(&ip, seed_in.addr,
sizeof(ip));
216 vSeedsOut.push_back(addr);
235 const auto it = mapLocalHost.find(addr);
236 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
257 (!addrLocal.IsRoutable() ||
259 if (
node.IsInboundConn()) {
268 addrLocal.SetIP(
node.GetAddrLocal());
271 if (addrLocal.IsRoutable() ||
gArgs.
GetBoolArg(
"-addrmantest",
false)) {
273 addrLocal.ToStringAddrPort(),
node.GetId());
298 const auto [it, is_newly_added] =
301 if (is_newly_added || nScore >= info.
nScore) {
302 info.
nScore = nScore + !is_newly_added;
317 mapLocalHost.erase(addr);
325 vfLimited[net] = !reachable;
330 return !vfLimited[net];
340 const auto it = mapLocalHost.find(addr);
341 if (it == mapLocalHost.end()) {
351 return mapLocalHost.count(addr) > 0;
356 for (
CNode *pnode : m_nodes) {
357 if (
static_cast<CNetAddr>(pnode->addr) == ip) {
366 for (
CNode *pnode : m_nodes) {
376 for (
CNode *pnode : m_nodes) {
377 if (pnode->m_addr_name == addrName) {
386 for (
CNode *pnode : m_nodes) {
387 if (
static_cast<CService>(pnode->addr) == addr) {
401 for (
const CNode *pnode : m_nodes) {
402 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() &&
403 pnode->GetLocalNonce() == nonce) {
413 struct sockaddr_storage sockaddr_bind;
414 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
415 if (!sock.
GetSockName((
struct sockaddr *)&sockaddr_bind,
416 &sockaddr_bind_len)) {
417 addr_bind.
SetSockAddr((
const struct sockaddr *)&sockaddr_bind,
421 "getsockname failed\n");
431 if (pszDest ==
nullptr) {
439 LogPrintf(
"Failed to open new connection, already connected\n");
445 "trying connection %s lastseen=%.1fhrs\n",
448 pszDest ? 0h : Now<NodeSeconds>() - addrConnect.
nTime));
451 const uint16_t default_port{pszDest !=
nullptr
455 const std::vector<CService> resolved{
Lookup(
457 if (!resolved.empty()) {
463 "Resolver returned invalid address %s for %s\n",
473 LogPrintf(
"Failed to open new connection, already connected\n");
480 std::unique_ptr<Sock> sock;
484 std::unique_ptr<i2p::sam::Session> i2p_transient_session;
488 bool proxyConnectionFailed =
false;
492 bool connected{
false};
496 proxyConnectionFailed);
500 if (m_unused_i2p_sessions.empty()) {
501 i2p_transient_session =
502 std::make_unique<i2p::sam::Session>(proxy,
505 i2p_transient_session.swap(
506 m_unused_i2p_sessions.front());
507 m_unused_i2p_sessions.pop();
510 connected = i2p_transient_session->Connect(
511 addrConnect, conn, proxyConnectionFailed);
514 if (m_unused_i2p_sessions.size() <
516 m_unused_i2p_sessions.emplace(
517 i2p_transient_session.release());
523 sock = std::move(conn.
sock);
526 }
else if (use_proxy) {
528 "Using proxy: %s to connect to %s:%s\n",
533 proxyConnectionFailed);
539 if (!proxyConnectionFailed) {
547 uint16_t port{default_port};
549 bool proxyConnectionFailed;
557 std::vector<NetWhitelistPermissions> whitelist_permissions =
560 : std::vector<NetWhitelistPermissions>{};
562 whitelist_permissions);
569 uint64_t extra_entropy =
578 nonce, extra_entropy, addr_bind, pszDest ? pszDest :
"", conn_type,
582 .permission_flags = permission_flags,
601 m_i2p_sam_session.reset();
606 const std::vector<NetWhitelistPermissions> &ranges)
const {
607 for (
const auto &subnet : ranges) {
608 if (subnet.m_subnet.Match(addr)) {
634 if (addrLocal.IsValid()) {
636 "Addr local already set for node: %i. Refusing to change from %s "
640 addrLocal = addrLocalIn;
700 if (wasPaused && !pause) {
703 const auto time = GetTime<std::chrono::microseconds>();
704 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
706 std::chrono::duration_cast<std::chrono::seconds>(time);
713 const auto time = GetTime<std::chrono::microseconds>();
715 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
720 std::chrono::duration_cast<std::chrono::seconds>(time);
723 nRecvBytes += msg_bytes.
size();
726 while (msg_bytes.
size() > 0) {
736 bool reject_message{
false};
738 if (reject_message) {
743 msg.m_raw_message_size;
749 auto i = mapRecvBytesPerMsgType.find(
msg.m_type);
750 if (i == mapRecvBytesPerMsgType.end()) {
754 assert(i != mapRecvBytesPerMsgType.end());
755 i->second +=
msg.m_raw_message_size;
767 std::chrono::duration_cast<std::chrono::seconds>(time);
779 uint32_t nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
792 }
catch (
const std::exception &) {
803 "Header error: Wrong MessageStart %s received, peer=%d\n",
811 "Header error: Size too large (%s, %u bytes), peer=%d\n",
825 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
850 bool &reject_message) {
852 reject_message =
false;
873 "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, "
879 reject_message =
true;
882 "Header error: Invalid message type (%s, %u bytes), peer=%d\n",
885 reject_message =
true;
895 std::vector<uint8_t> &header)
const {
910 size_t nSentSize = 0;
911 size_t nMsgCount = 0;
913 for (
auto it =
node.vSendMsg.begin(); it !=
node.vSendMsg.end(); ++it) {
914 const auto &data = *it;
925 if (it + 1 !=
node.vSendMsg.end()) {
929 nBytes =
node.m_sock->Send(
930 reinterpret_cast<const char *
>(data.data()) +
node.nSendOffset,
946 node.CloseSocketDisconnect();
953 node.m_last_send = GetTime<std::chrono::seconds>();
954 node.nSendBytes += nBytes;
955 node.nSendOffset += nBytes;
957 if (
node.nSendOffset != data.size()) {
962 node.nSendOffset = 0;
963 node.nSendSize -= data.size();
968 node.vSendMsg.erase(
node.vSendMsg.begin(),
969 node.vSendMsg.begin() + nMsgCount);
971 if (
node.vSendMsg.empty()) {
976 return {nSentSize, !
node.vSendMsg.empty()};
987 std::vector<NodeEvictionCandidate> vEvictionCandidates;
991 if (
node->fDisconnect) {
997 .m_connected =
node->m_connected,
998 .m_min_ping_time =
node->m_min_ping_time,
999 .m_last_block_time =
node->m_last_block_time,
1000 .m_last_proof_time =
node->m_last_proof_time,
1001 .m_last_tx_time =
node->m_last_tx_time,
1002 .fRelevantServices =
node->m_has_all_wanted_services,
1003 .m_relay_txs =
node->m_relays_txs.load(),
1004 .fBloomFilter =
node->m_bloom_filter_loaded.load(),
1005 .nKeyedNetGroup =
node->nKeyedNetGroup,
1006 .prefer_evict =
node->m_prefer_evict,
1007 .m_is_local =
node->addr.IsLocal(),
1008 .m_network =
node->ConnectedThroughNetwork(),
1010 .m_conn_type =
node->m_conn_type,
1011 .availabilityScore =
1012 node->m_avalanche_enabled
1013 ?
node->getAvailabilityScore()
1014 : -std::numeric_limits<double>::infinity()};
1015 vEvictionCandidates.push_back(candidate);
1018 const std::optional<NodeId> node_id_to_evict =
1020 if (!node_id_to_evict) {
1024 for (
CNode *pnode : m_nodes) {
1025 if (pnode->GetId() == *node_id_to_evict) {
1028 "selected %s connection for eviction peer=%d; disconnecting\n",
1029 pnode->ConnectionTypeAsString(), pnode->GetId());
1030 pnode->fDisconnect =
true;
1038 struct sockaddr_storage sockaddr;
1039 socklen_t len =
sizeof(sockaddr);
1040 auto sock = hListenSocket.
sock->Accept((
struct sockaddr *)&sockaddr, &len);
1046 LogPrintf(
"socket error accept failed: %s\n",
1052 if (!addr.
SetSockAddr((
const struct sockaddr *)&sockaddr, len)) {
1054 "Unknown socket family\n");
1078 for (
const CNode *pnode : m_nodes) {
1079 if (pnode->IsInboundConn()) {
1087 "connection from %s dropped: not accepting new connections\n",
1092 if (!sock->IsSelectable()) {
1093 LogPrintf(
"connection from %s dropped: non-selectable socket\n",
1101 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
1104 "connection from %s: unable to set TCP_NODELAY, continuing "
1122 nInbound + 1 >= nMaxInbound && discouraged) {
1128 if (nInbound >= nMaxInbound) {
1132 "connection dropped (full)\n");
1141 uint64_t extra_entropy =
1146 const bool inbound_onion =
1154 .prefer_evict = discouraged,
1167 m_nodes.push_back(pnode);
1178 std::optional<int> max_connections;
1179 switch (conn_type) {
1201 int existing_connections =
1203 return std::count_if(
1204 m_nodes.begin(), m_nodes.end(), [conn_type](
CNode *
node) {
1205 return node->m_conn_type == conn_type;
1209 if (max_connections != std::nullopt &&
1210 existing_connections >= max_connections) {
1231 for (
CNode *pnode : m_nodes) {
1232 if (!pnode->fDisconnect) {
1234 "Network not active, dropping peer=%d\n",
1236 pnode->fDisconnect =
true;
1242 std::vector<CNode *> nodes_copy = m_nodes;
1243 for (
CNode *pnode : nodes_copy) {
1244 if (pnode->fDisconnect) {
1246 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode),
1250 pnode->grantOutbound.Release();
1253 pnode->CloseSocketDisconnect();
1264 for (
CNode *pnode : nodes_disconnected_copy) {
1267 if (pnode->GetRefCount() <= 0) {
1279 nodes_size = m_nodes.size();
1290 std::chrono::seconds now)
const {
1297 const auto now{GetTime<std::chrono::seconds>()};
1298 const auto last_send{
node.m_last_send.load()};
1299 const auto last_recv{
node.m_last_recv.load()};
1300 const auto last_msg_start{
node.m_last_msg_start.load()};
1306 if (last_recv.count() == 0 || last_send.count() == 0) {
1308 "socket no message in first %i seconds, %d %d peer=%d\n",
1310 last_send.count() != 0,
node.GetId());
1326 uint64_t inflight_bytes =
node.nInflightBytes.load();
1327 if (inflight_bytes > 0 && !
node.fPauseRecv) {
1332 "socket receive timeout: stalled message, last data "
1333 "received %i seconds ago, bytes=%d peer=%d\n",
1344 "socket receive timeout: stalled message started %i "
1345 "seconds ago, bytes=%d peer=%d\n",
1352 if (!
node.fSuccessfullyConnected) {
1365 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
1368 int inbound_candidates{0};
1369 for (
CNode *pnode : nodes) {
1370 inbound_candidates += pnode->IsInboundConn();
1375 bool select_recv = !pnode->fPauseRecv &&
1377 inbound_candidates <= 3);
1379 WITH_LOCK(pnode->cs_vSend,
return !pnode->vSendMsg.empty());
1380 if (!select_recv && !select_send) {
1384 LOCK(pnode->m_sock_mutex);
1385 if (pnode->m_sock) {
1388 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
1392 return events_per_sock;
1401 const auto timeout =
1409 if (events_per_sock.empty() ||
1410 !events_per_sock.begin()->first->WaitMany(timeout,
1424 const std::vector<CNode *> &nodes,
1426 uint64_t nTotalInflightBytes{0};
1427 for (
CNode *pnode : nodes) {
1435 bool recvSet =
false;
1436 bool sendSet =
false;
1437 bool errorSet =
false;
1439 LOCK(pnode->m_sock_mutex);
1440 if (!pnode->m_sock) {
1443 const auto it = events_per_sock.find(pnode->m_sock);
1444 if (it != events_per_sock.end()) {
1447 errorSet = it->second.occurred &
Sock::ERR;
1453 auto [bytes_sent, data_left] =
1472 if (recvSet || errorSet) {
1474 uint8_t pchBuf[0x10000];
1477 LOCK(pnode->m_sock_mutex);
1478 if (!pnode->m_sock) {
1482 pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
1485 bool notify =
false;
1486 if (!pnode->ReceiveMsgBytes(*
config, {pchBuf, (size_t)nBytes},
1488 pnode->CloseSocketDisconnect();
1491 nTotalInflightBytes += pnode->nInflightBytes;
1493 pnode->MarkReceivedMsgsForProcessing();
1496 }
else if (nBytes == 0) {
1498 if (!pnode->fDisconnect) {
1502 pnode->CloseSocketDisconnect();
1503 }
else if (nBytes < 0) {
1508 if (!pnode->fDisconnect) {
1510 "socket recv error for peer=%d: %s\n",
1513 pnode->CloseSocketDisconnect();
1519 pnode->fDisconnect =
true;
1528 LogPrintf(
"Inflight throttling %s (%d/%d)\n",
1530 nTotalInflightBytes, max_inflight_bytes);
1540 const auto it = events_per_sock.find(listen_socket.sock);
1541 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
1558 fMsgProcWake =
true;
1565 std::vector<std::string> seeds =
1568 int seeds_right_now = 0;
1573 seeds_right_now = seeds.size();
1578 seeds_right_now = seeds.size();
1593 const std::chrono::seconds seeds_wait_time =
1598 for (
const std::string &seed : seeds) {
1599 if (seeds_right_now == 0) {
1603 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n",
1604 seeds_wait_time.count());
1605 std::chrono::seconds to_wait = seeds_wait_time;
1606 while (to_wait.count() > 0) {
1610 std::chrono::seconds w =
1620 for (
const CNode *pnode : m_nodes) {
1621 if (pnode->fSuccessfullyConnected &&
1622 pnode->IsFullOutboundConn()) {
1627 if (nRelevant >= 2) {
1629 LogPrintf(
"%d addresses found from DNS seeds\n",
1632 "P2P peers available. Finished DNS seeding.\n");
1635 "P2P peers available. Skipped DNS seeding.\n");
1649 LogPrintf(
"Waiting for network to be reactivated before querying "
1658 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
1662 std::vector<CAddress> vAdd;
1665 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
1672 unsigned int nMaxIPs = 256;
1673 const auto addresses{
LookupHost(host, nMaxIPs,
true)};
1674 if (!addresses.empty()) {
1675 for (
const CNetAddr &ip : addresses) {
1678 requiredServiceBits);
1681 Now<NodeSeconds>() - 3 * 24h, -4 * 24h);
1682 vAdd.push_back(addr);
1695 LogPrintf(
"%d addresses found from DNS seeds\n", found);
1709 std::string strDest;
1712 if (m_addr_fetches.empty()) {
1715 strDest = m_addr_fetches.front();
1716 m_addr_fetches.pop_front();
1733 flag ?
"true" :
"false");
1743 int full_outbound_peers = 0;
1746 for (
const CNode *pnode : m_nodes) {
1747 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
1748 pnode->IsFullOutboundConn()) {
1749 ++full_outbound_peers;
1759 int block_relay_peers = 0;
1762 for (
const CNode *pnode : m_nodes) {
1763 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect &&
1764 pnode->IsBlockOnlyConn()) {
1765 ++block_relay_peers;
1773 const std::vector<std::string> connect,
1778 if (!connect.empty()) {
1779 for (int64_t nLoop = 0;; nLoop++) {
1781 for (
const std::string &strAddr : connect) {
1785 for (
int i = 0; i < 10 && i < nLoop; i++) {
1787 std::chrono::milliseconds(500))) {
1799 auto start = GetTime<std::chrono::microseconds>();
1803 auto next_extra_block_relay =
1809 if (!add_fixed_seeds) {
1810 LogPrintf(
"Fixed seeds are disabled\n");
1817 if (!mockOpenConnection &&
1833 bool add_fixed_seeds_now =
false;
1835 if (GetTime<std::chrono::seconds>() >
1836 start + std::chrono::minutes{1}) {
1837 add_fixed_seeds_now =
true;
1838 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and "
1839 "addrman is empty\n");
1840 }
else if (!dnsseed && !use_seednodes) {
1843 if (m_added_nodes.empty()) {
1844 add_fixed_seeds_now =
true;
1845 LogPrintf(
"Adding fixed seeds as -dnsseed=0 and neither "
1846 "-addnode nor -seednode are provided\n");
1850 if (add_fixed_seeds_now) {
1855 add_fixed_seeds =
false;
1865 int nOutboundFullRelay = 0;
1866 int nOutboundBlockRelay = 0;
1867 int nOutboundAvalanche = 0;
1868 std::set<std::vector<uint8_t>> setConnected;
1872 for (
const CNode *pnode : m_nodes) {
1873 if (pnode->IsAvalancheOutboundConnection()) {
1874 nOutboundAvalanche++;
1875 }
else if (pnode->IsFullOutboundConn()) {
1876 nOutboundFullRelay++;
1877 }
else if (pnode->IsBlockOnlyConn()) {
1878 nOutboundBlockRelay++;
1888 switch (pnode->m_conn_type) {
1897 setConnected.insert(
1905 auto now = GetTime<std::chrono::microseconds>();
1906 bool anchor =
false;
1907 bool fFeeler =
false;
1935 }
else if (now > next_extra_block_relay &&
1959 next_extra_block_relay =
1963 }
else if (now > next_feeler) {
1987 "Trying to make an anchor connection to %s\n",
2046 if (current_time - addr_last_try < 10min && nTries < 30) {
2105 if (mockOpenConnection) {
2106 mockOpenConnection(addrConnect, conn_type);
2109 int(setConnected.size()) >=
2111 &grant,
nullptr, conn_type);
2118 std::vector<CAddress> ret;
2120 for (
const CNode *pnode : m_nodes) {
2121 if (pnode->IsBlockOnlyConn()) {
2122 ret.push_back(pnode->addr);
2130 std::vector<AddedNodeInfo> ret;
2132 std::list<std::string> lAddresses(0);
2135 ret.reserve(m_added_nodes.size());
2136 std::copy(m_added_nodes.cbegin(), m_added_nodes.cend(),
2137 std::back_inserter(lAddresses));
2142 std::map<CService, bool> mapConnected;
2143 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2146 for (
const CNode *pnode : m_nodes) {
2147 if (pnode->addr.IsValid()) {
2148 mapConnected[pnode->addr] = pnode->IsInboundConn();
2150 std::string addrName{pnode->m_addr_name};
2151 if (!addrName.empty()) {
2152 mapConnectedByName[std::move(addrName)] =
2153 std::make_pair(pnode->IsInboundConn(),
2154 static_cast<const CService &
>(pnode->addr));
2159 for (
const std::string &strAddNode : lAddresses) {
2165 auto it = mapConnected.find(service);
2166 if (it != mapConnected.end()) {
2167 addedNode.resolvedAddress = service;
2168 addedNode.fConnected =
true;
2169 addedNode.fInbound = it->second;
2173 auto it = mapConnectedByName.find(strAddNode);
2174 if (it != mapConnectedByName.end()) {
2175 addedNode.resolvedAddress = it->second.second;
2176 addedNode.fConnected =
true;
2177 addedNode.fInbound = it->second.first;
2180 ret.emplace_back(std::move(addedNode));
2193 if (!info.fConnected) {
2203 info.strAddedNode.c_str(),
2222 const char *pszDest,
2237 bool banned_or_discouraged =
2240 if (
IsLocal(addrConnect) || banned_or_discouraged ||
2244 }
else if (
FindNode(std::string(pszDest))) {
2248 CNode *pnode =
ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
2253 if (grantOutbound) {
2263 m_nodes.push_back(pnode);
2273 bool fMoreWork =
false;
2281 for (
CNode *pnode : snap.Nodes()) {
2282 if (pnode->fDisconnect) {
2286 bool fMoreNodeWork =
false;
2289 fMoreNodeWork |= interface->ProcessMessages(
2292 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
2299 interface->SendMessages(*
config, pnode);
2311 std::chrono::steady_clock::now() +
2312 std::chrono::milliseconds(100),
2316 fMsgProcWake =
false;
2321 static constexpr auto err_wait_begin = 1s;
2322 static constexpr auto err_wait_cap = 5min;
2323 auto err_wait = err_wait_begin;
2325 bool advertising_listen_addr =
false;
2330 if (advertising_listen_addr && conn.
me.
IsValid()) {
2332 advertising_listen_addr =
false;
2336 if (err_wait < err_wait_cap) {
2343 if (!advertising_listen_addr) {
2345 advertising_listen_addr =
true;
2363 struct sockaddr_storage sockaddr;
2364 socklen_t len =
sizeof(sockaddr);
2365 if (!addrBind.
GetSockAddr((
struct sockaddr *)&sockaddr, &len)) {
2374 std::unique_ptr<Sock> sock =
2379 "connections (socket returned error %s)"),
2392 "Error setting SO_REUSEADDR on socket: %s, continuing anyway"),
2405 "socket: %s, continuing anyway"),
2411 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
2412 if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL,
2417 "socket: %s, continuing anyway"),
2424 if (sock->Bind(
reinterpret_cast<struct sockaddr *
>(&sockaddr), len) ==
2428 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s "
2429 "is probably already running."),
2432 strError =
strprintf(
_(
"Unable to bind to %s on this computer "
2433 "(bind returned error %s)"),
2446 strError =
strprintf(
_(
"Listening for incoming connections "
2447 "failed (listen returned error %s)"),
2465 LogPrintf(
"%s: %s\n", __func__, addr.ToStringAddr());
2471 LogPrintf(
"%s: %s\n", __func__, active);
2485 AddrMan &addrmanIn,
bool network_active)
2486 : config(&configIn), addrman(addrmanIn), nSeed0(nSeed0In),
2522 for (
const auto &addrBind : options.
vBinds) {
2528 for (
const auto &addrBind : options.
vWhiteBinds) {
2530 addrBind.m_flags)) {
2534 for (
const auto &addr_bind : options.
onion_binds) {
2544 const CService ipv6_any{in6_addr(IN6ADDR_ANY_INIT),
2548 struct in_addr inaddr_any;
2549 inaddr_any.s_addr = htonl(INADDR_ANY);
2564 _(
"Failed to listen on any port. Use -listen=0 if you want "
2577 for (
const auto &strDest : connOptions.
vSeedNodes) {
2590 "%i block-relay-only anchors will be tried for connections.\n",
2596 _(
"Starting network threads...").translated);
2621 fMsgProcWake =
false;
2643 _(
"Cannot provide specific connections and have addrman find "
2644 "outgoing connections at the same."),
2654 ThreadOpenConnections(connect, nullptr);
2743 std::vector<CAddress> anchors_to_dump =
2755 std::vector<CNode *> nodes;
2757 for (
CNode *pnode : nodes) {
2758 pnode->CloseSocketDisconnect();
2774 interface->FinalizeNode(*
config, *pnode);
2784std::vector<CAddress>
2786 std::optional<Network> network)
const {
2787 std::vector<CAddress> addresses =
2790 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
2792 return m_banman->IsDiscouraged(
2794 m_banman->IsBanned(addr);
2801std::vector<CAddress>
2806 .
Write(local_socket_bytes)
2808 const auto current_time = GetTime<std::chrono::microseconds>();
2844 current_time + 21h +
2852 for (
const std::string &it : m_added_nodes) {
2853 if (strNode == it) {
2858 m_added_nodes.push_back(strNode);
2864 for (std::vector<std::string>::iterator it = m_added_nodes.begin();
2865 it != m_added_nodes.end(); ++it) {
2866 if (strNode == *it) {
2867 m_added_nodes.erase(it);
2878 return m_nodes.size();
2882 for (
const auto &pnode : m_nodes) {
2895 vstats.reserve(m_nodes.size());
2896 for (
CNode *pnode : m_nodes) {
2897 vstats.emplace_back();
2898 pnode->copyStats(vstats.back());
2899 vstats.back().m_mapped_as = pnode->addr.GetMappedAS(
addrman.
GetAsmap());
2906 for (
auto &&pnode : m_nodes) {
2907 if (pnode->GetId() ==
id) {
2908 pnode->copyStats(stats);
2921 "disconnect by address%s matched peer=%d; disconnecting\n",
2923 pnode->fDisconnect =
true;
2930 bool disconnected =
false;
2932 for (
CNode *pnode : m_nodes) {
2933 if (subnet.
Match(pnode->addr)) {
2935 "disconnect by subnet%s matched peer=%d; disconnecting\n",
2938 pnode->fDisconnect =
true;
2939 disconnected =
true;
2942 return disconnected;
2951 for (
CNode *pnode : m_nodes) {
2952 if (
id == pnode->GetId()) {
2955 pnode->fDisconnect =
true;
2968 nTotalBytesSent += bytes;
2970 const auto now = GetTime<std::chrono::seconds>();
2973 nMaxOutboundCycleStartTime = now;
2974 nMaxOutboundTotalBytesSentInCycle = 0;
2978 nMaxOutboundTotalBytesSentInCycle += bytes;
2983 return nMaxOutboundLimit;
2992 if (nMaxOutboundLimit == 0) {
2996 if (nMaxOutboundCycleStartTime.count() == 0) {
3000 const std::chrono::seconds cycleEndTime =
3002 const auto now = GetTime<std::chrono::seconds>();
3003 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
3008 if (nMaxOutboundLimit == 0) {
3012 if (historicalBlockServingLimit) {
3014 const std::chrono::seconds timeLeftInCycle =
3016 const uint64_t buffer =
3017 timeLeftInCycle / std::chrono::minutes{10} *
ONE_MEGABYTE;
3018 if (buffer >= nMaxOutboundLimit ||
3019 nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer) {
3022 }
else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) {
3031 if (nMaxOutboundLimit == 0) {
3035 return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
3037 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
3046 return nTotalBytesSent;
3066 uint64_t windowInvCounters =
invCounters.exchange(0);
3069 int64_t polls = windowInvCounters & std::numeric_limits<uint32_t>::max();
3070 int64_t votes = windowInvCounters >> 32;
3073 decayFactor * (2 * votes - polls) + (1. - decayFactor) * previousScore;
3083 uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn,
3084 uint64_t nLocalExtraEntropyIn,
const CAddress &addrBindIn,
3091 m_permission_flags{node_opts.permission_flags}, m_sock{sock},
3092 m_connected(
GetTime<
std::chrono::seconds>()), addr{addrIn},
3093 addrBind{addrBindIn},
3094 m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
3095 m_inbound_onion{inbound_onion}, m_prefer_evict{node_opts.prefer_evict},
3096 nKeyedNetGroup{nKeyedNetGroupIn}, m_conn_type{conn_type_in}, id{idIn},
3097 nLocalHostNonce{nLocalHostNonceIn},
3098 nLocalExtraEntropy{nLocalExtraEntropyIn},
3099 m_recv_flood_size{node_opts.recv_flood_size},
3100 m_i2p_sam_session{
std::move(node_opts.i2p_sam_session)} {
3101 if (inbound_onion) {
3106 mapRecvBytesPerMsgType[
msg] = 0;
3121 size_t nSizeAdded = 0;
3126 nSizeAdded +=
msg.m_raw_message_size;
3130 m_msg_process_queue.splice(m_msg_process_queue.end(),
vRecvMsg);
3131 m_msg_process_queue_size += nSizeAdded;
3137 if (m_msg_process_queue.empty()) {
3138 return std::nullopt;
3141 std::list<CNetMessage> msgs;
3143 msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
3144 m_msg_process_queue_size -= msgs.front().m_raw_message_size;
3147 return std::make_pair(std::move(msgs.front()),
3148 !m_msg_process_queue.empty());
3156 size_t nMessageSize =
msg.data.size();
3158 nMessageSize, pnode->
GetId());
3166 msg.data.size(),
msg.data.data());
3169 std::vector<uint8_t> serializedHeader;
3171 size_t nTotalSize = nMessageSize + serializedHeader.size();
3173 size_t nBytesSent = 0;
3176 bool optimisticSend(pnode->vSendMsg.empty());
3180 pnode->nSendSize += nTotalSize;
3185 pnode->vSendMsg.push_back(std::move(serializedHeader));
3187 pnode->vSendMsg.push_back(std::move(
msg.data));
3192 if (optimisticSend) {
3202 CNode *found =
nullptr;
3204 for (
auto &&pnode : m_nodes) {
3205 if (pnode->
GetId() ==
id) {
3243 std::stringstream ebMBs;
3245 std::string eb = ebMBs.str();
3246 eb.insert(eb.size() - 1,
".", 1);
3247 if (eb.substr(0, 1) ==
".") {
3256 std::vector<std::string> uacomments;
3257 uacomments.push_back(
"EB" + eb);
3261 for (
const std::string &cmt :
gArgs.
GetArgs(
"-uacomment")) {
3262 uacomments.push_back(cmt);
3266 const std::string client_version =
3279 auto now = GetTime<std::chrono::microseconds>();
3283 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3289 base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
3293 f <<
Span{msg_type};
3298 uint32_t size = data.
size();
3303std::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
bool AddConnection(const std::string &address, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
Attempts to open a connection.
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)
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 ...
static constexpr size_t MAX_UNUSED_I2P_SESSIONS_SIZE
Cap on the size of m_unused_i2p_sessions, to ensure it does not unexpectedly use too much memory.
bool GetTryNewOutboundPeer() const
int m_max_outbound_block_relay
std::thread threadI2PAcceptIncoming
void SetTryNewOutboundPeer(bool flag)
std::atomic< bool > flagInterruptMsgProc
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
void OpenNetworkConnection(const CAddress &addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *strDest, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
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
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex
RecursiveMutex cs_totalBytesSent
bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions)
std::thread threadOpenConnections
size_t GetNodeCount(ConnectionDirection) const
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
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)
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
std::atomic_bool inflight_throttle
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
Mutex m_unused_i2p_sessions_mutex
Mutex protecting m_i2p_sam_sessions.
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...
CNode * ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
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
CHash256 & Write(Span< const uint8_t > input)
void Finalize(Span< uint8_t > output)
Network GetNetClass() const
std::string ToStringAddr() 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.
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
void pauseRecv(bool pause)
std::atomic< int64_t > nTimeOffset
const std::string m_addr_name
std::string ConnectionTypeAsString() const
std::atomic< bool > m_bip152_highbandwidth_to
std::list< CNetMessage > vRecvMsg
std::atomic< bool > m_bip152_highbandwidth_from
std::atomic_bool fSuccessfullyConnected
CNode(NodeId id, std::shared_ptr< Sock > sock, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, uint64_t nLocalExtraEntropyIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion, CNodeOptions &&node_opts={})
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
CSemaphoreGrant grantOutbound
std::atomic< std::chrono::seconds > m_last_msg_start
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
std::atomic< uint64_t > nInflightBytes
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.
bool SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
Set CService from a network sockaddr.
sa_family_t GetSAFamily() const
Get the address family.
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
std::string ToStringAddrPort() const
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
std::chrono::steady_clock Clock
bool sleep_for(Clock::duration rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut)
virtual uint64_t GetMaxBlockSize() const =0
virtual const CChainParams & GetChainParams() const =0
void resize(size_type n, value_type c=value_type{})
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)
std::string ToString() const
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) noexcept
Return the time point advanced by a uniform random duration.
Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive).
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
std::chrono::microseconds rand_exp_duration(std::chrono::microseconds mean) noexcept
Return a duration sampled from an exponential distribution (https://en.wikipedia.org/wiki/Exponential...
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
static constexpr Event SEND
If passed to Wait(), then it will wait for readiness to send to the socket.
virtual int GetSockName(sockaddr *name, socklen_t *name_len) const
getsockname(2) wrapper.
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(std::chrono::microseconds time, bool &reject_message) 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
Minimal stream for overwriting and/or appending to an existing byte vector.
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()
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.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
#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 CAddress GetBindAddress(const Sock &sock)
Get the bind address for a socket as CAddress.
static constexpr auto FEELER_SLEEP_WINDOW
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 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)
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 size_t DEFAULT_MAXINFLIGHTBUFFER
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.
std::unique_ptr< Sock > ConnectDirectly(const CService &dest, bool manual_connection)
Create a socket and try to connect to the specified service.
std::vector< CNetAddr > LookupHost(const std::string &name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
Resolve a host string to its corresponding network addresses.
void InterruptSocks5(bool interrupt)
std::vector< CService > Lookup(const std::string &name, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
Resolve a service string to its corresponding service.
bool GetProxy(enum Network net, Proxy &proxyInfoOut)
std::unique_ptr< Sock > ConnectThroughProxy(const Proxy &proxy, const std::string &dest, uint16_t port, bool &proxy_connection_failed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
std::function< std::unique_ptr< Sock >(int, int, int)> CreateSock
Socket factory.
bool GetNameProxy(Proxy &nameProxyOut)
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.
std::vector< CNetAddr > GetLocalAddresses()
Return all local non-loopback IPv4 and IPv6 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.
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
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.
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
std::unique_ptr< i2p::sam::Session > i2p_sam_session
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
std::chrono::seconds m_last_msg_start
NetPermissionFlags m_permission_flags
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.
bool SplitHostPort(std::string_view in, uint16_t &portOut, std::string &hostOut)
Splits socket address string into host string and port value.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.