6#include <bitcoin-build-config.h>
48#include <unordered_map>
135 m_addr_fetches.push_back(strDest);
141 for (
const std::string& bind_arg :
gArgs.GetArgs(
"-bind")) {
142 constexpr uint16_t dummy_port = 0;
144 const std::optional<CService> bind_addr{
Lookup(bind_arg, dummy_port,
false)};
145 if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port)
return bind_addr->GetPort();
150 for (
const std::string& whitebind_arg :
gArgs.GetArgs(
"-whitebind")) {
161 return static_cast<uint16_t
>(
gArgs.GetIntArg(
"-port",
Params().GetDefaultPort()));
167 if (!
fListen)
return std::nullopt;
169 std::optional<CService> addr;
171 int nBestReachability = -1;
174 for (
const auto& [local_addr, local_service_info] : mapLocalHost) {
182 const int nScore{local_service_info.nScore};
183 const int nReachability{local_addr.GetReachabilityFrom(peer.
addr)};
184 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) {
185 addr.emplace(
CService{local_addr, local_service_info.nPort});
186 nBestReachability = nReachability;
195static std::vector<CAddress>
ConvertSeeds(
const std::vector<uint8_t> &vSeedsIn)
201 const auto one_week{7 * 24h};
202 std::vector<CAddress> vSeedsOut;
211 vSeedsOut.push_back(addr);
228 const auto it = mapLocalHost.find(addr);
229 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
250 if (
node.IsInboundConn()) {
273 return mapLocalHost.clear();
294 const auto [it, is_newly_added] = mapLocalHost.emplace(addr,
LocalServiceInfo());
296 if (is_newly_added || nScore >= info.
nScore) {
297 info.
nScore = nScore + (is_newly_added ? 0 : 1);
314 mapLocalHost.erase(addr);
321 const auto it = mapLocalHost.find(addr);
322 if (it == mapLocalHost.end())
return false;
332 return mapLocalHost.contains(addr);
338 return std::ranges::any_of(m_nodes, [&host](
CNode*
node) {
return node->m_addr_name == host; });
344 return std::ranges::any_of(m_nodes, [&addr_port](
CNode*
node) {
return node->addr == addr_port; });
350 return std::ranges::any_of(m_nodes, [&addr](
CNode*
node) {
return node->addr == addr; });
356 for (
const CNode* pnode : m_nodes) {
365 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && !pnode->IsPrivateBroadcastConn() &&
366 pnode->GetLocalNonce() ==
nonce)
377 const std::optional<Proxy>& proxy_override)
382 if (pszDest ==
nullptr) {
400 const uint16_t default_port{pszDest !=
nullptr ?
GetDefaultPort(pszDest) :
404 std::vector<CAddress> connect_to{};
407 if (!resolved.empty()) {
411 for (
const auto& r : resolved) {
424 connect_to.push_back(addrConnect);
428 connect_to.push_back(addrConnect);
432 connect_to.push_back(addrConnect);
436 std::unique_ptr<Sock> sock;
440 std::unique_ptr<i2p::sam::Session> i2p_transient_session;
442 for (
auto& target_addr: connect_to) {
443 if (target_addr.IsValid()) {
445 if (proxy_override.has_value()) {
447 proxy = proxy_override.value();
449 use_proxy =
GetProxy(target_addr.GetNetwork(), proxy);
451 bool proxyConnectionFailed =
false;
453 if (target_addr.IsI2P() && use_proxy) {
455 bool connected{
false};
461 connected =
m_i2p_sam_session->Connect(target_addr, conn, proxyConnectionFailed);
465 if (m_unused_i2p_sessions.empty()) {
466 i2p_transient_session =
469 i2p_transient_session.swap(m_unused_i2p_sessions.front());
470 m_unused_i2p_sessions.pop();
473 connected = i2p_transient_session->Connect(target_addr, conn, proxyConnectionFailed);
477 m_unused_i2p_sessions.emplace(i2p_transient_session.release());
483 sock = std::move(conn.
sock);
486 }
else if (use_proxy) {
488 sock =
ConnectThroughProxy(proxy, target_addr.ToStringAddr(), target_addr.GetPort(), proxyConnectionFailed);
496 if (!proxyConnectionFailed) {
499 addrman.get().Attempt(target_addr, fCountFailure);
503 uint16_t port{default_port};
505 bool proxyConnectionFailed;
524 .
Write(target_addr.GetNetClass())
536 pszDest ? pszDest :
"",
541 .permission_flags = permission_flags,
542 .proxy_override = proxy_override,
543 .i2p_sam_session = std::move(i2p_transient_session),
573 m_i2p_sam_session.reset();
577 for (
const auto& subnet : ranges) {
578 if (addr.has_value() && subnet.m_subnet.Match(addr.value())) {
601 if (
Assume(!m_addr_local.IsValid())) {
602 m_addr_local = addrLocalIn;
617#define X(name) stats.name = name
640 X(mapSendBytesPerMsgType);
645 X(mapRecvBytesPerMsgType);
669 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
670 nRecvBytes += msg_bytes.size();
671 while (msg_bytes.size() > 0) {
680 bool reject_message{
false};
682 if (reject_message) {
691 auto i = mapRecvBytesPerMsgType.find(msg.m_type);
692 if (i == mapRecvBytesPerMsgType.end()) {
695 assert(i != mapRecvBytesPerMsgType.end());
696 i->second += msg.m_raw_message_size;
710 return log_ip ?
strprintf(
" peeraddr=%s",
addr.ToStringAddrPort()) :
"";
715 return strprintf(
"disconnecting peer=%d%s",
737 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
739 memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy);
750 catch (
const std::exception&) {
778 unsigned int nRemaining = hdr.nMessageSize - nDataPos;
779 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
781 if (vRecv.size() < nDataPos + nCopy) {
783 vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
786 hasher.Write(msg_bytes.first(nCopy));
787 memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy);
797 if (data_hash.IsNull())
798 hasher.Finalize(data_hash);
806 reject_message =
false;
812 msg.m_type = hdr.GetMessageType();
814 msg.m_message_size = hdr.nMessageSize;
824 LogDebug(
BCLog::NET,
"Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
829 reject_message =
true;
830 }
else if (!hdr.IsMessageTypeValid()) {
833 reject_message =
true;
846 if (m_sending_header || m_bytes_sent < m_message_to_send.data.size())
return false;
856 m_header_to_send.clear();
860 m_message_to_send = std::move(msg);
861 m_sending_header =
true;
870 if (m_sending_header) {
871 return {std::span{m_header_to_send}.subspan(m_bytes_sent),
874 have_next_message || !m_message_to_send.data.empty(),
875 m_message_to_send.m_type
878 return {std::span{m_message_to_send.data}.subspan(m_bytes_sent),
882 m_message_to_send.m_type
891 m_bytes_sent += bytes_sent;
892 if (m_sending_header && m_bytes_sent == m_header_to_send.size()) {
894 m_sending_header =
false;
896 }
else if (!m_sending_header && m_bytes_sent == m_message_to_send.data.size()) {
908 return m_message_to_send.GetMemoryUsage();
918const std::array<std::string, 33> V2_MESSAGE_IDS = {
957 std::unordered_map<std::string, uint8_t> m_map;
960 V2MessageMap() noexcept
962 for (
size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
963 m_map.emplace(V2_MESSAGE_IDS[i], i);
967 std::optional<uint8_t> operator()(
const std::string& message_name)
const noexcept
969 auto it = m_map.find(message_name);
970 if (it == m_map.end())
return std::nullopt;
975const V2MessageMap V2_MESSAGE_MAP;
977std::vector<uint8_t> GenerateRandomGarbage() noexcept
979 std::vector<uint8_t>
ret;
992 Assume(m_send_buffer.empty());
996 std::copy(m_send_garbage.begin(), m_send_garbage.end(), m_send_buffer.begin() +
EllSwiftPubKey::size());
1002 m_initiating{initiating},
1004 m_v1_fallback{nodeid},
1005 m_recv_state{initiating ? RecvState::KEY : RecvState::KEY_MAYBE_V1},
1006 m_send_garbage{std::move(garbage)},
1007 m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
1009 Assume(m_send_garbage.size() <= MAX_GARBAGE_LEN);
1013 StartSendingHandshake();
1025 switch (m_recv_state) {
1049 m_recv_state = recv_state;
1056 switch (m_send_state) {
1069 m_send_state = send_state;
1090 std::array<uint8_t, V1_PREFIX_LEN> v1_prefix = {0, 0, 0, 0,
'v',
'e',
'r',
's',
'i',
'o',
'n', 0, 0, 0, 0, 0};
1091 std::copy(std::begin(
Params().MessageStart()), std::end(
Params().MessageStart()), v1_prefix.begin());
1092 Assume(m_recv_buffer.size() <= v1_prefix.size());
1093 if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), v1_prefix.begin())) {
1100 }
else if (m_recv_buffer.size() == v1_prefix.size()) {
1103 std::span<const uint8_t> feedback{m_recv_buffer};
1107 Assume(feedback.empty());
1132 static constexpr std::array<uint8_t, 12> MATCH = {
'v',
'e',
'r',
's',
'i',
'o',
'n', 0, 0, 0, 0, 0};
1133 static constexpr size_t OFFSET = std::tuple_size_v<MessageStartChars>;
1134 if (!
m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
1135 if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
1137 HexStr(std::span(m_recv_buffer).first(OFFSET)));
1153 m_recv_buffer.clear();
1187 m_recv_aad = std::move(m_recv_buffer);
1189 m_recv_buffer.clear();
1215 static constexpr size_t MAX_CONTENTS_LEN =
1222 if (m_recv_len > MAX_CONTENTS_LEN) {
1230 m_recv_decode_buffer.resize(m_recv_len);
1249 switch (m_recv_state) {
1278 switch (m_recv_state) {
1328 static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024;
1337 while (!msg_bytes.empty()) {
1342 if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
1343 switch (m_recv_state) {
1358 size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
1359 m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
1364 Assume(m_recv_buffer.empty());
1374 max_read = std::min(msg_bytes.size(), max_read);
1376 m_recv_buffer.insert(m_recv_buffer.end(),
UCharCast(msg_bytes.data()),
UCharCast(msg_bytes.data() + max_read));
1377 msg_bytes = msg_bytes.subspan(max_read);
1380 switch (m_recv_state) {
1416 if (contents.size() == 0)
return std::nullopt;
1417 uint8_t first_byte = contents[0];
1418 contents = contents.subspan(1);
1420 if (first_byte != 0) {
1422 if (first_byte < std::size(V2_MESSAGE_IDS)) {
1424 return V2_MESSAGE_IDS[first_byte];
1427 return std::nullopt;
1432 return std::nullopt;
1435 size_t msg_type_len{0};
1438 if (contents[msg_type_len] <
' ' || contents[msg_type_len] > 0x7F) {
1443 std::string
ret{
reinterpret_cast<const char*
>(contents.data()), msg_type_len};
1446 if (contents[msg_type_len] != 0)
return {};
1461 std::span<const uint8_t> contents{m_recv_decode_buffer};
1467 reject_message =
false;
1468 msg.m_type = std::move(*msg_type);
1470 msg.m_message_size = contents.size();
1471 msg.m_recv.resize(contents.size());
1472 std::copy(contents.begin(), contents.end(),
UCharCast(msg.m_recv.data()));
1474 LogDebug(
BCLog::NET,
"V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(),
m_nodeid);
1475 reject_message =
true;
1491 if (!(m_send_state ==
SendState::READY && m_send_buffer.empty()))
return false;
1493 std::vector<uint8_t> contents;
1494 auto short_message_id = V2_MESSAGE_MAP(msg.m_type);
1495 if (short_message_id) {
1496 contents.resize(1 + msg.data.size());
1497 contents[0] = *short_message_id;
1498 std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1);
1503 std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
1509 m_send_type = msg.m_type;
1522 Assume(m_send_pos <= m_send_buffer.size());
1524 std::span{m_send_buffer}.subspan(m_send_pos),
1542 m_send_pos += bytes_sent;
1543 Assume(m_send_pos <= m_send_buffer.size());
1545 m_sent_v1_header_worth =
true;
1548 if (m_send_pos == m_send_buffer.size()) {
1565 if (!m_recv_buffer.empty())
return false;
1568 return m_sent_v1_header_worth;
1603 auto it =
node.vSendMsg.begin();
1604 size_t nSentSize = 0;
1605 bool data_left{
false};
1606 std::optional<bool> expected_more;
1609 if (it !=
node.vSendMsg.end()) {
1613 size_t memusage = it->GetMemoryUsage();
1614 if (
node.m_transport->SetMessageToSend(*it)) {
1620 const auto& [data, more, msg_type] =
node.m_transport->GetBytesToSend(it !=
node.vSendMsg.end());
1624 if (expected_more.has_value())
Assume(!data.empty() == *expected_more);
1625 expected_more = more;
1626 data_left = !data.empty();
1628 if (!data.empty()) {
1642 nBytes =
node.m_sock->Send(data.data(), data.size(),
flags);
1646 node.nSendBytes += nBytes;
1648 node.m_transport->MarkBytesSent(nBytes);
1650 if (!msg_type.empty()) {
1651 node.AccountForSentBytes(msg_type, nBytes);
1653 nSentSize += nBytes;
1654 if ((
size_t)nBytes != data.size()) {
1664 node.CloseSocketDisconnect();
1673 if (it ==
node.vSendMsg.end()) {
1676 node.vSendMsg.erase(
node.vSendMsg.begin(), it);
1677 return {nSentSize, data_left};
1690 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1695 if (
node->fDisconnect)
1698 .id =
node->GetId(),
1699 .m_connected =
node->m_connected,
1700 .m_min_ping_time =
node->m_min_ping_time,
1701 .m_last_block_time =
node->m_last_block_time,
1702 .m_last_tx_time =
node->m_last_tx_time,
1703 .fRelevantServices =
node->m_has_all_wanted_services,
1704 .m_relay_txs =
node->m_relays_txs.load(),
1705 .fBloomFilter =
node->m_bloom_filter_loaded.load(),
1706 .nKeyedNetGroup =
node->nKeyedNetGroup,
1707 .prefer_evict =
node->m_prefer_evict,
1708 .m_is_local =
node->addr.IsLocal(),
1709 .m_network =
node->ConnectedThroughNetwork(),
1711 .m_conn_type =
node->m_conn_type,
1713 vEvictionCandidates.push_back(candidate);
1716 const std::optional<NodeId> node_id_to_evict =
SelectNodeToEvict(std::move(vEvictionCandidates));
1717 if (!node_id_to_evict) {
1721 for (
CNode* pnode : m_nodes) {
1722 if (pnode->GetId() == *node_id_to_evict) {
1723 LogDebug(
BCLog::NET,
"selected %s connection for eviction, %s", pnode->ConnectionTypeAsString(), pnode->DisconnectMsg(
fLogIPs));
1726 pnode->m_addr_name.c_str(),
1727 pnode->ConnectionTypeAsString().c_str(),
1728 pnode->ConnectedThroughNetwork(),
1730 pnode->fDisconnect =
true;
1738 struct sockaddr_storage sockaddr;
1739 socklen_t len =
sizeof(sockaddr);
1740 auto sock = hListenSocket.
sock->Accept((
struct sockaddr*)&sockaddr, &len);
1751 if (!addr.
SetSockAddr((
const struct sockaddr*)&sockaddr, len)) {
1780 for (
const CNode* pnode : m_nodes) {
1781 if (pnode->IsInboundConn()) nInbound++;
1790 if (!sock->IsSelectable()) {
1798 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
1799 LogDebug(
BCLog::NET,
"connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
1823 LogDebug(
BCLog::NET,
"failed to find an eviction candidate - connection dropped (full)\n");
1852 .permission_flags = permission_flags,
1853 .prefer_evict = discouraged,
1858 m_msgproc->InitializeNode(*pnode, local_services);
1861 m_nodes.push_back(pnode);
1878 std::optional<int> max_connections;
1879 switch (conn_type) {
1900 return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](
CNode*
node) { return node->m_conn_type == conn_type; }););
1903 if (max_connections != std::nullopt && existing_connections >= max_connections)
return false;
1907 if (!grant)
return false;
1926 decltype(m_reconnections) reconnections_to_add;
1932 if (!network_active) {
1934 for (
CNode* pnode : m_nodes) {
1935 if (!pnode->fDisconnect) {
1937 pnode->fDisconnect =
true;
1943 std::vector<CNode*> nodes_copy = m_nodes;
1944 for (
CNode* pnode : nodes_copy)
1946 if (pnode->fDisconnect)
1949 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());
1954 if (network_active && pnode->m_transport->ShouldReconnectV1()) {
1955 reconnections_to_add.push_back({
1956 .proxy_override = pnode->m_proxy_override,
1957 .addr_connect = pnode->addr,
1958 .grant = std::move(pnode->grantOutbound),
1959 .destination = pnode->m_dest,
1960 .conn_type = pnode->m_conn_type,
1961 .use_v2transport =
false});
1962 LogDebug(
BCLog::NET,
"retrying with v1 transport protocol for peer=%d\n", pnode->GetId());
1966 pnode->grantOutbound.Release();
1969 pnode->CloseSocketDisconnect();
1972 if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];
1983 for (
CNode* pnode : nodes_disconnected_copy)
1986 if (pnode->GetRefCount() <= 0) {
1995 m_reconnections.splice(m_reconnections.end(), std::move(reconnections_to_add));
2004 nodes_size = m_nodes.size();
2023 const auto last_send{
node.m_last_send.load()};
2024 const auto last_recv{
node.m_last_recv.load()};
2028 bool has_received{last_recv.count() != 0};
2029 bool has_sent{last_send.count() != 0};
2031 if (!has_received || !has_sent) {
2032 std::string has_never;
2033 if (!has_received) has_never +=
", never received from peer";
2034 if (!has_sent) has_never +=
", never sent to peer";
2036 "socket no message in first %i seconds%s, %s\n",
2060 if (!
node.fSuccessfullyConnected) {
2077 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
2080 for (
CNode* pnode : nodes) {
2081 bool select_recv = !pnode->fPauseRecv;
2084 LOCK(pnode->cs_vSend);
2088 const auto& [to_send, more, _msg_type] = pnode->m_transport->GetBytesToSend(!pnode->vSendMsg.empty());
2089 select_send = !to_send.empty() || more;
2091 if (!select_recv && !select_send)
continue;
2093 LOCK(pnode->m_sock_mutex);
2094 if (pnode->m_sock) {
2096 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
2100 return events_per_sock;
2119 if (events_per_sock.empty() || !events_per_sock.begin()->first->WaitMany(timeout, events_per_sock)) {
2138 for (
CNode* pnode : nodes) {
2146 bool recvSet =
false;
2147 bool sendSet =
false;
2148 bool errorSet =
false;
2150 LOCK(pnode->m_sock_mutex);
2151 if (!pnode->m_sock) {
2154 const auto it = events_per_sock.find(pnode->m_sock);
2155 if (it != events_per_sock.end()) {
2158 errorSet = it->second.occurred &
Sock::ERR;
2175 if (data_left) recvSet =
false;
2179 if (recvSet || errorSet)
2182 uint8_t pchBuf[0x10000];
2185 LOCK(pnode->m_sock_mutex);
2186 if (!pnode->m_sock) {
2189 nBytes = pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
2193 bool notify =
false;
2194 if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
2196 "receiving message bytes failed, %s\n",
2199 pnode->CloseSocketDisconnect();
2203 pnode->MarkReceivedMsgsForProcessing();
2207 else if (nBytes == 0)
2210 if (!pnode->fDisconnect) {
2213 pnode->CloseSocketDisconnect();
2215 else if (nBytes < 0)
2221 if (!pnode->fDisconnect) {
2224 pnode->CloseSocketDisconnect();
2239 const auto it = events_per_sock.find(listen_socket.sock);
2240 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
2261 fMsgProcWake =
true;
2268 int outbound_connection_count = 0;
2270 if (!
gArgs.GetArgs(
"-seednode").empty()) {
2272 constexpr std::chrono::seconds SEEDNODE_TIMEOUT = 30s;
2273 LogInfo(
"-seednode enabled. Trying the provided seeds for %d seconds before defaulting to the dnsseeds.\n", SEEDNODE_TIMEOUT.count());
2282 LogInfo(
"Couldn't connect to enough peers via seed nodes. Handing fetch logic to the DNS seeds.\n");
2288 LogInfo(
"P2P peers available. Finished fetching data from seed nodes.\n");
2295 std::vector<std::string> seeds =
m_params.DNSSeeds();
2296 std::shuffle(seeds.begin(), seeds.end(), rng);
2297 int seeds_right_now = 0;
2301 seeds_right_now = seeds.size();
2302 }
else if (
addrman.get().Size() == 0) {
2306 seeds_right_now = seeds.size();
2326 for (
const std::string& seed : seeds) {
2327 if (seeds_right_now == 0) {
2330 if (
addrman.get().Size() > 0) {
2331 LogInfo(
"Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
2332 std::chrono::seconds to_wait = seeds_wait_time;
2333 while (to_wait.count() > 0) {
2343 LogInfo(
"%d addresses found from DNS seeds\n", found);
2344 LogInfo(
"P2P peers available. Finished DNS seeding.\n");
2346 LogInfo(
"P2P peers available. Skipped DNS seeding.\n");
2358 LogInfo(
"Waiting for network to be reactivated before querying DNS seeds.\n");
2364 LogInfo(
"Loading addresses from DNS seed %s\n", seed);
2370 std::vector<CAddress> vAdd;
2372 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
2381 unsigned int nMaxIPs = 32;
2382 const auto addresses{
LookupHost(host, nMaxIPs,
true)};
2383 if (!addresses.empty()) {
2387 vAdd.push_back(addr);
2390 addrman.get().Add(vAdd, resolveSource);
2400 LogInfo(
"%d addresses found from DNS seeds\n", found);
2402 LogInfo(
"Skipping DNS seeds. Enough peers have been found\n");
2408 const auto start{SteadyClock::now()};
2419 std::string strDest;
2422 if (m_addr_fetches.empty())
2424 strDest = m_addr_fetches.front();
2425 m_addr_fetches.pop_front();
2451 LogDebug(
BCLog::NET,
"setting try another outbound peer=%s\n", flag ?
"true" :
"false");
2466 for (
const CNode* pnode : m_nodes) {
2467 if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
2481 int full_outbound_peers = 0;
2484 for (
const CNode* pnode : m_nodes) {
2485 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
2486 ++full_outbound_peers;
2495 int block_relay_peers = 0;
2498 for (
const CNode* pnode : m_nodes) {
2499 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
2500 ++block_relay_peers;
2509 std::unordered_set<Network> networks{};
2510 for (
int n = 0; n <
NET_MAX; n++) {
2514 networks.insert(net);
2523 return m_network_conn_counts[net] > 1;
2532 for (
const auto net : nets) {
2548 if (!connect.empty())
2553 for (int64_t nLoop = 0;; nLoop++)
2555 for (
const std::string& strAddr : connect)
2564 for (
int i = 0; i < 10 && i < nLoop; i++)
2587 const bool use_seednodes{!
gArgs.GetArgs(
"-seednode").empty()};
2590 bool add_addr_fetch{
addrman.get().Size() == 0 && !seed_nodes.empty()};
2591 constexpr std::chrono::seconds ADD_NEXT_SEEDNODE = 10s;
2593 if (!add_fixed_seeds) {
2594 LogInfo(
"Fixed seeds are disabled\n");
2598 if (add_addr_fetch) {
2599 add_addr_fetch =
false;
2603 if (
addrman.get().Size() == 0) {
2604 LogInfo(
"Empty addrman, adding seednode (%s) to addrfetch\n", seed);
2606 LogInfo(
"Couldn't connect to peers from addrman after %d seconds. Adding seednode (%s) to addrfetch\n", ADD_NEXT_SEEDNODE.count(), seed);
2624 if (add_fixed_seeds && !fixed_seed_networks.empty()) {
2629 bool add_fixed_seeds_now =
false;
2632 add_fixed_seeds_now =
true;
2633 LogInfo(
"Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
2637 else if (!dnsseed && !use_seednodes) {
2639 if (m_added_node_params.empty()) {
2640 add_fixed_seeds_now =
true;
2641 LogInfo(
"Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
2645 if (add_fixed_seeds_now) {
2653 seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
2654 [&fixed_seed_networks](
const CAddress& addr) { return !fixed_seed_networks.contains(addr.GetNetwork()); }),
2658 addrman.get().Add(seed_addrs, local);
2659 add_fixed_seeds =
false;
2660 LogInfo(
"Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
2670 int nOutboundFullRelay = 0;
2671 int nOutboundBlockRelay = 0;
2672 int outbound_privacy_network_peers = 0;
2673 std::set<std::vector<unsigned char>> outbound_ipv46_peer_netgroups;
2677 for (
const CNode* pnode : m_nodes) {
2678 if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
2679 if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
2682 switch (pnode->m_conn_type) {
2696 const CAddress address{pnode->addr};
2705 ++outbound_privacy_network_peers;
2707 outbound_ipv46_peer_netgroups.insert(
m_netgroupman.GetGroup(address));
2716 add_addr_fetch =
true;
2722 bool anchor =
false;
2723 bool fFeeler =
false;
2724 std::optional<Network> preferred_net;
2770 }
else if (now > next_feeler) {
2776 now > next_extra_network_peer &&
2790 addrman.get().ResolveCollisions();
2802 outbound_ipv46_peer_netgroups.contains(
m_netgroupman.GetGroup(addr)))
continue;
2821 std::tie(addr, addr_last_try) =
addrman.get().SelectTriedCollision();
2826 std::tie(addr, addr_last_try) =
addrman.get().Select(
true, reachable_nets);
2835 std::tie(addr, addr_last_try) =
addrman.get().Select(
true, reachable_nets);
2842 std::tie(addr, addr_last_try) = preferred_net.has_value()
2843 ?
addrman.get().Select(
false, {*preferred_net})
2844 :
addrman.get().Select(
false, reachable_nets);
2848 if (!fFeeler && outbound_ipv46_peer_netgroups.contains(
m_netgroupman.GetGroup(addr))) {
2862 if (current_time - addr_last_try < 10min && nTries < 30) {
2884 LogDebug(
BCLog::NET,
"Not making automatic %s%s connection to %s peer selected for manual (addnode) connection%s\n",
2885 preferred_net.has_value() ?
"network-specific " :
"",
2910 const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(
m_max_automatic_connections - 1, 2)};
2926 std::vector<CAddress>
ret;
2928 for (
const CNode* pnode : m_nodes) {
2929 if (pnode->IsBlockOnlyConn()) {
2930 ret.push_back(pnode->addr);
2939 std::vector<AddedNodeInfo>
ret;
2941 std::list<AddedNodeParams> lAddresses(0);
2944 ret.reserve(m_added_node_params.size());
2945 std::copy(m_added_node_params.cbegin(), m_added_node_params.cend(), std::back_inserter(lAddresses));
2950 std::map<CService, bool> mapConnected;
2951 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2954 for (
const CNode* pnode : m_nodes) {
2955 if (pnode->addr.IsValid()) {
2956 mapConnected[pnode->addr] = pnode->IsInboundConn();
2958 std::string addrName{pnode->m_addr_name};
2959 if (!addrName.empty()) {
2960 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(),
static_cast<const CService&
>(pnode->addr));
2965 for (
const auto& addr : lAddresses) {
2970 auto it = mapConnected.find(service);
2971 if (it != mapConnected.end()) {
2972 if (!include_connected) {
2981 auto it = mapConnectedByName.find(addr.m_added_node);
2982 if (it != mapConnectedByName.end()) {
2983 if (!include_connected) {
2988 addedNode.
fInbound = it->second.first;
2991 ret.emplace_back(std::move(addedNode));
3016 info.m_params.m_added_node.c_str(),
3018 info.m_params.m_use_v2transport,
3036 const char* pszDest,
3039 const std::optional<Proxy>& proxy_override)
3054 bool banned_or_discouraged =
m_banman && (
m_banman->IsDiscouraged(addrConnect) ||
m_banman->IsBanned(addrConnect));
3071 m_nodes.push_back(pnode);
3090 std::optional<Proxy> clearnet_proxy;
3096 if (clearnet_proxy.has_value()) {
3110 return std::nullopt;
3115 proxy = clearnet_proxy;
3136 new_value = current_value > n ? current_value - n : 0;
3137 }
while (!
m_num_to_open.compare_exchange_strong(current_value, new_value));
3152 return std::nullopt;
3163 bool fMoreWork =
false;
3172 if (pnode->fDisconnect)
3177 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
3192 fMsgProcWake =
false;
3198 static constexpr auto err_wait_begin = 1s;
3199 static constexpr auto err_wait_cap = 5min;
3200 auto err_wait = err_wait_begin;
3202 bool advertising_listen_addr =
false;
3205 auto SleepOnFailure = [&]() {
3207 if (err_wait < err_wait_cap) {
3215 if (advertising_listen_addr && conn.
me.
IsValid()) {
3217 advertising_listen_addr =
false;
3223 if (!advertising_listen_addr) {
3225 advertising_listen_addr =
true;
3235 err_wait = err_wait_begin;
3243 size_t addrman_num_bad_addresses{0};
3259 std::optional<Proxy> proxy;
3261 if (!net.has_value()) {
3262 LogWarning(
"Unable to open -privatebroadcast connections: neither Tor nor I2P is reachable");
3267 const auto [addr,
_] =
addrman.get().Select(
false, {net.value()});
3269 if (!addr.IsValid() ||
IsLocal(addr)) {
3270 ++addrman_num_bad_addresses;
3271 if (addrman_num_bad_addresses > 100) {
3277 addrman_num_bad_addresses = 0;
3279 auto target_str{addr.ToStringAddrPort()};
3280 if (proxy.has_value()) {
3281 target_str +=
" through the proxy at " + proxy->ToString();
3288 std::move(conn_max_grant),
3297 if (remaining == 0) {
3300 LogDebug(
BCLog::PRIVBROADCAST,
"Failed to connect to %s, will retry to a different address; remaining connections to open: %d", target_str, remaining);
3312 struct sockaddr_storage sockaddr;
3313 socklen_t len =
sizeof(sockaddr);
3314 if (!addrBind.
GetSockAddr((
struct sockaddr*)&sockaddr, &len))
3330 if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &nOne,
sizeof(
int)) ==
SOCKET_ERROR) {
3339 if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, &nOne,
sizeof(
int)) ==
SOCKET_ERROR) {
3345 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
3346 if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &nProtLevel,
sizeof(
int)) ==
SOCKET_ERROR) {
3353 if (sock->Bind(
reinterpret_cast<struct sockaddr*
>(&sockaddr), len) ==
SOCKET_ERROR) {
3356 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s is probably already running."), addrBind.
ToStringAddrPort(), CLIENT_NAME);
3383 LogInfo(
"%s: %s\n", __func__, addr.ToStringAddr());
3389 LogInfo(
"%s: %s\n", __func__, active);
3407 bool network_active,
3408 std::shared_ptr<CThreadInterrupt> interrupt_net)
3425 return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
3460 for (
const auto& addrBind : options.
vBinds) {
3465 for (
const auto& addrBind : options.
vWhiteBinds) {
3470 for (
const auto& addr_bind : options.
onion_binds) {
3482 struct in_addr inaddr_any;
3483 inaddr_any.s_addr = htonl(INADDR_ANY);
3500 _(
"Failed to listen on any port. Use -listen=0 if you want this."),
3513 std::vector<std::string> seed_nodes = connOptions.
vSeedNodes;
3514 if (!seed_nodes.empty()) {
3524 LogInfo(
"%i block-relay-only anchors will be tried for connections.\n",
m_anchors.size());
3551 fMsgProcWake =
false;
3558 LogInfo(
"DNS seeding disabled\n");
3568 _(
"Cannot provide specific connections and have addrman find outgoing connections at the same time."),
3576 [
this, connect = connOptions.
m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });
3627 (*m_interrupt_net)();
3685 std::vector<CNode*> nodes;
3687 for (
CNode* pnode : nodes) {
3689 pnode->CloseSocketDisconnect();
3718 std::vector<CAddress> addresses =
addrman.get().GetAddr(max_addresses, max_pct, network, filtered);
3720 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3721 [
this](
const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
3768 const bool resolved_is_valid{resolved.
IsValid()};
3771 for (
const auto& it : m_added_node_params) {
3775 m_added_node_params.push_back(add);
3782 for (
auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
3783 if (
node == it->m_added_node) {
3784 m_added_node_params.erase(it);
3797 return (m_added_node_params.size() < 24
3798 && std::any_of(m_added_node_params.cbegin(), m_added_node_params.cend(),
3799 [&](
const auto& p) { return p.m_added_node == addr_str || p.m_added_node == addr_port_str; }));
3806 return m_nodes.size();
3809 for (
const auto& pnode : m_nodes) {
3822 return mapLocalHost;
3834 vstats.reserve(m_nodes.size());
3835 for (
CNode* pnode : m_nodes) {
3836 vstats.emplace_back();
3837 pnode->CopyStats(vstats.back());
3838 vstats.back().m_mapped_as =
GetMappedAS(pnode->addr);
3845 auto it = std::ranges::find_if(m_nodes, [&strNode](
CNode*
node) {
return node->m_addr_name == strNode; });
3846 if (it != m_nodes.end()) {
3849 node->fDisconnect =
true;
3857 bool disconnected =
false;
3859 for (
CNode* pnode : m_nodes) {
3860 if (subnet.
Match(pnode->addr)) {
3862 pnode->fDisconnect =
true;
3863 disconnected =
true;
3866 return disconnected;
3877 for(
CNode* pnode : m_nodes) {
3878 if (
id == pnode->GetId()) {
3880 pnode->fDisconnect =
true;
3897 nTotalBytesSent += bytes;
3903 nMaxOutboundCycleStartTime = now;
3904 nMaxOutboundTotalBytesSentInCycle = 0;
3907 nMaxOutboundTotalBytesSentInCycle += bytes;
3936 if (nMaxOutboundCycleStartTime.count() == 0)
3941 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
3951 if (historicalBlockServingLimit)
3984 return nTotalBytesSent;
3994 if (use_v2transport) {
3995 return std::make_unique<V2Transport>(
id, !inbound);
3997 return std::make_unique<V1Transport>(
id);
4002 std::shared_ptr<Sock> sock,
4004 uint64_t nKeyedNetGroupIn,
4005 uint64_t nLocalHostNonceIn,
4007 const std::string& addrNameIn,
4010 uint64_t network_key,
4019 m_addr_name{addrNameIn.empty() ?
addr.ToStringAddrPort() : addrNameIn},
4029 m_i2p_sam_session{
std::move(node_opts.i2p_sam_session)}
4034 mapRecvBytesPerMsgType[msg] = 0;
4049 size_t nSizeAdded = 0;
4053 nSizeAdded += msg.GetMemoryUsage();
4057 m_msg_process_queue.splice(m_msg_process_queue.end(),
vRecvMsg);
4058 m_msg_process_queue_size += nSizeAdded;
4065 if (m_msg_process_queue.empty())
return std::nullopt;
4067 std::list<CNetMessage> msgs;
4069 msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
4070 m_msg_process_queue_size -= msgs.front().GetMemoryUsage();
4073 return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
4108 size_t nMessageSize = msg.data.size();
4123 size_t nBytesSent = 0;
4128 const auto& [to_send, more, _msg_type] =
4130 const bool queue_was_empty{to_send.empty() && pnode->vSendMsg.empty()};
4133 pnode->m_send_memusage += msg.GetMemoryUsage();
4136 pnode->vSendMsg.push_back(std::move(msg));
4145 if (queue_was_empty && more) {
4154 CNode* found =
nullptr;
4156 for (
auto&& pnode : m_nodes) {
4157 if(pnode->
GetId() ==
id) {
4172 std::vector<unsigned char> vchNetGroup(
m_netgroupman.GetGroup(address));
4183 decltype(m_reconnections) todo;
4186 if (m_reconnections.empty())
break;
4187 todo.splice(todo.end(), m_reconnections, m_reconnections.begin());
4190 auto& item = *todo.begin();
4197 std::move(item.grant),
4198 item.destination.empty() ?
nullptr : item.destination.c_str(),
4200 item.use_v2transport,
4201 item.proxy_override);
4209 std::vector<CNetAddr> clearnet_addrs;
4210 clearnet_addrs.reserve(v4_addrs.size() + v6_addrs.size());
4211 std::transform(v4_addrs.begin(), v4_addrs.end(), std::back_inserter(clearnet_addrs),
4212 [](
const CAddress& addr) { return static_cast<CNetAddr>(addr); });
4213 std::transform(v6_addrs.begin(), v6_addrs.end(), std::back_inserter(clearnet_addrs),
4214 [](
const CAddress& addr) { return static_cast<CNetAddr>(addr); });
4220 const std::string& msg_type,
4221 std::span<const unsigned char> data,
4232 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
4234 fs::path base_path =
gArgs.GetDataDirNet() /
"message_capture" / fs::u8path(clean_addr);
4235 fs::create_directories(base_path);
4237 fs::path path = base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
4241 f << std::span{msg_type};
4245 uint32_t size = data.size();
4250 throw std::ios_base::failure(
4251 strprintf(
"Error closing %s after write, file contents are likely incomplete", fs::PathToString(path)));
4255std::function<void(
const CAddress& addr,
4256 const std::string& msg_type,
4257 std::span<const unsigned char> data,
bool DumpPeerAddresses(const ArgsManager &args, const AddrMan &addr)
std::vector< CAddress > ReadAnchors(const fs::path &anchors_db_path)
Read the anchor IP address database (anchors.dat).
void DumpAnchors(const fs::path &anchors_db_path, const std::vector< CAddress > &anchors)
Dump the anchor IP address database (anchors.dat).
const CChainParams & Params()
Return the currently selected parameters.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
Non-refcounted RAII wrapper for FILE*.
std::span< const std::byte > GetSendGarbageTerminator() const noexcept
Get the Garbage Terminator to send.
static constexpr unsigned GARBAGE_TERMINATOR_LEN
static constexpr unsigned LENGTH_LEN
static constexpr unsigned EXPANSION
void Encrypt(std::span< const std::byte > contents, std::span< const std::byte > aad, bool ignore, std::span< std::byte > output) noexcept
Encrypt a packet.
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. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const MessageStartChars & MessageStart() const
RAII helper to atomically create a copy of m_nodes and add a reference to each of the nodes.
const std::vector< CNode * > & Nodes() const
std::atomic_bool m_outbound_tor_ok_at_least_once
Remember if we ever established at least one outbound connection to a Tor peer, including sending and...
std::atomic_size_t m_num_to_open
Number of ConnectionType::PRIVATE_BROADCAST connections to open.
void NumToOpenAdd(size_t n)
Increment the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
std::optional< Proxy > ProxyForIPv4or6() const
Check if private broadcast can be done to IPv4 or IPv6 peers and if so via which proxy.
size_t NumToOpenSub(size_t n)
Decrement the number of new connections of type ConnectionType::PRIVATE_BROADCAST to be opened by CCo...
void NumToOpenWait() const
Wait for the number of needed connections to become greater than 0.
size_t NumToOpen() const
Get the pending number of connections to open.
std::optional< Network > PickNetwork(std::optional< Proxy > &proxy) const
Choose a network to open a connection to.
std::unordered_set< Network > GetReachableEmptyNetworks() const
Return reachable networks for which we have no addresses in addrman and therefore may require loading...
std::condition_variable condMsgProc
std::thread threadMessageHandler
bool AlreadyConnectedToHost(std::string_view host) const
Determine whether we're already connected to a given "host:port".
std::reference_wrapper< AddrMan > addrman
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
void DisconnectNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex
m_max_outbound_full_relay
void DeleteNode(CNode *pnode)
bool AttemptToEvictConnection()
Try to find a connection to evict when the node is full.
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::microseconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
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
const bool use_v2transport(GetLocalServices() &NODE_P2P_V2)
class CConnman::PrivateBroadcast m_private_broadcast
uint16_t GetDefaultPort(Network net) const
void PerformReconnections() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex
Attempt reconnections, if m_reconnections non-empty.
std::thread threadI2PAcceptIncoming
std::vector< CAddress > GetAddresses(CNode &requestor, size_t max_addresses, size_t max_pct)
Return addresses from the per-requestor cache.
void SetTryNewOutboundPeer(bool flag)
CNode * ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport, const std::optional< Proxy > &proxy_override) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
Open a new P2P connection.
std::atomic< bool > flagInterruptMsgProc
void CreateNodeFromAcceptedSocket(std::unique_ptr< Sock > &&sock, NetPermissionFlags permission_flags, const CService &addr_bind, const CService &addr)
Create a CNode object from a socket that has just been accepted and add the node to the m_nodes membe...
void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
std::map< CNetAddr, LocalServiceInfo > getNetLocalAddresses() const
void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
int GetFullOutboundConnCount() const
std::atomic< NodeId > nLastNodeId
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
uint64_t GetMaxOutboundTarget() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
std::thread threadDNSAddressSeed
void SocketHandlerConnected(const std::vector< CNode * > &nodes, const Sock::EventsPerSock &events_per_sock) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
Do the read/write for connected sockets that are ready for IO.
void ThreadI2PAcceptIncoming()
void StartExtraBlockRelayPeers()
const NetGroupManager & m_netgroupman
bool DisconnectNode(std::string_view node)
std::vector< CAddress > m_anchors
Addresses that were saved during the previous clean shutdown.
std::chrono::seconds GetMaxOutboundTimeframe() const
uint64_t CalculateKeyedNetGroup(const CNetAddr &ad) const
unsigned int nPrevNodeCount
void AddWhitelistPermissionFlags(NetPermissionFlags &flags, std::optional< CNetAddr > addr, const std::vector< NetWhitelistPermissions > &ranges) const
void NotifyNumConnectionsChanged()
ServiceFlags GetLocalServices() const
bool AddNode(const AddedNodeParams &add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
std::atomic_bool m_try_another_outbound_peer
flag for deciding to connect to an extra outbound peer, in excess of m_max_outbound_full_relay This t...
bool InitBinds(const Options &options)
vWhitelistedRangeOutgoing
void AddAddrFetch(const std::string &strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex)
std::vector< ListenSocket > vhListenSocket
bool AlreadyConnectedToAddress(const CNetAddr &addr) const
Determine whether we're already connected to a given address.
std::vector< CAddress > GetCurrentBlockRelayOnlyConns() const
Return vector of current BLOCK_RELAY peers.
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
bool AddConnection(const std::string &address, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
Attempts to open a connection.
Mutex m_total_bytes_sent_mutex
std::vector< AddedNodeInfo > GetAddedNodeInfo(bool include_connected) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex
bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions)
std::thread threadOpenConnections
size_t GetNodeCount(ConnectionDirection) const
void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex)
uint32_t GetMappedAS(const CNetAddr &addr) const
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
Mutex m_addr_fetches_mutex
Mutex m_reconnections_mutex
Mutex protecting m_reconnections.
bool OpenNetworkConnection(const CAddress &addrConnect, bool fCountFailure, CountingSemaphoreGrant<> &&grant_outbound, const char *pszDest, ConnectionType conn_type, bool use_v2transport, const std::optional< Proxy > &proxy_override) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
Open a new P2P connection and initialize it with the PeerManager at m_msgproc.
void GetNodeStats(std::vector< CNodeStats > &vstats) const
bool Start(CScheduler &scheduler, const Options &options) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
const uint64_t nSeed0
SipHasher seeds for deterministic randomness.
void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
Check connected and listening sockets for IO readiness and process them accordingly.
int GetExtraFullOutboundCount() const
std::chrono::seconds GetMaxOutboundTimeLeftInCycle_() const EXCLUSIVE_LOCKS_REQUIRED(m_total_bytes_sent_mutex)
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
m_max_outbound_block_relay
static bool NodeFullyConnected(const CNode *pnode)
std::unique_ptr< std::counting_semaphore<> > semOutbound
const CChainParams & m_params
void SetNetworkActive(bool active)
bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex)
bool AddedNodesContain(const CAddress &addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
std::chrono::seconds GetMaxOutboundTimeLeftInCycle() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
const std::shared_ptr< CThreadInterrupt > m_interrupt_net
This is signaled when network activity should cease.
m_max_automatic_connections
std::thread threadPrivateBroadcast
void ThreadOpenConnections(std::vector< std::string > connect, std::span< const std::string > seed_nodes) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
bool RemoveAddedNode(std::string_view node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
bool fAddressesInitialized
std::vector< CAddress > GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return randomly selected addresses.
std::thread threadOpenAddedConnections
Mutex m_added_nodes_mutex
vWhitelistedRangeIncoming
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
void RecordBytesSent(uint64_t bytes) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
bool CheckIncomingNonce(uint64_t nonce)
void Init(const Options &connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex
Mutex m_unused_i2p_sessions_mutex
Mutex protecting m_i2p_sam_sessions.
uint64_t GetTotalBytesSent() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
std::unique_ptr< std::counting_semaphore<> > semAddnode
void ThreadPrivateBroadcast() EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
bool MaybePickPreferredNetwork(std::optional< Network > &network)
Search for a "preferred" network, a reachable network to which we currently don't have any OUTBOUND_F...
void RecordBytesRecv(uint64_t bytes)
void StopNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex)
uint64_t GetOutboundTargetBytesLeft() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
std::list< CNode * > m_nodes_disconnected
std::unique_ptr< i2p::sam::Session > m_i2p_sam_session
I2P SAM session.
std::map< uint64_t, CachedAddrResponse > m_addr_response_caches
Addr responses stored in different caches per (network, local socket) prevent cross-network node iden...
Sock::EventsPerSock GenerateWaitSockets(std::span< CNode *const > nodes)
Generate a collection of sockets to check for IO readiness.
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.
bool InactivityCheck(const CNode &node, std::chrono::microseconds now) const
Return true if the peer is inactive and should be disconnected.
void SocketHandlerListening(const Sock::EventsPerSock &events_per_sock)
Accept incoming connections, one from each read-ready listening socket.
CConnman(uint64_t seed0, uint64_t seed1, AddrMan &addrman, const NetGroupManager &netgroupman, const CChainParams ¶ms, bool network_active=true, std::shared_ptr< CThreadInterrupt > interrupt_net=std::make_shared< CThreadInterrupt >())
bool AlreadyConnectedToAddressPort(const CService &addr_port) const
Determine whether we're already connected to a given address:port.
std::thread threadSocketHandler
void AcceptConnection(const ListenSocket &hListenSocket)
bool BindListenPort(const CService &bindAddr, bilingual_str &strError, NetPermissionFlags permissions)
An encapsulated private key.
Network GetNetClass() const
std::string ToStringAddr() const
void SetIP(const CNetAddr &ip)
std::vector< unsigned char > GetAddrBytes() const
bool SetSpecial(std::string_view addr)
Parse a Tor or I2P address and set this object to it.
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.
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
DataStream m_recv
received message data
Information about a peer.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
const std::string m_dest
The pszDest argument provided to ConnectNode().
std::atomic< int > nVersion
bool IsInboundConn() const
CountingSemaphoreGrant grantOutbound
std::atomic_bool fPauseRecv
const std::string m_addr_name
bool IsConnectedThroughPrivacyNet() const
Whether this peer connected through a privacy network.
void CopyStats(CNodeStats &stats) EXCLUSIVE_LOCKS_REQUIRED(!m_subver_mutex
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
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
const bool m_prefer_evict
bool ReceiveMsgBytes(std::span< const uint8_t > msg_bytes, bool &complete) EXCLUSIVE_LOCKS_REQUIRED(!cs_vRecv)
Receive bytes from the buffer and deserialize them into messages.
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
const uint64_t nKeyedNetGroup
CNode(NodeId id, std::shared_ptr< Sock > sock, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CService &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion, uint64_t network_key, CNodeOptions &&node_opts={})
void MarkReceivedMsgsForProcessing() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Move all messages from the received queue to the processing queue.
const uint64_t m_network_key
Network key used to prevent fingerprinting our node across networks.
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.
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
const uint64_t nLocalHostNonce
std::atomic< std::chrono::microseconds > m_last_ping_time
Last measured round-trip time.
bool IsManualOrFullOutboundConn() const
bool IsPrivateBroadcastConn() const
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const NetPermissionFlags m_permission_flags
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::microseconds > m_min_ping_time
Lowest measured round-trip time.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_recv
const std::optional< Proxy > m_proxy_override
Proxy to use regardless of global proxy settings if reconnecting to this node.
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 CloseSocketDisconnect() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex)
std::atomic< std::chrono::seconds > m_last_send
std::string m_session_id
BIP324 session id string in hex, if any.
TransportProtocolType m_transport_type
Transport protocol type.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
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
General SipHash-2-4 implementation.
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
RAII-style semaphore lock.
Double ended buffer combining vector and stream-like interfaces.
void fillrand(std::span< std::byte > output) noexcept
Fill a byte span with random bytes.
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)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
static bool TryParse(const std::string &str, NetWhitebindPermissions &output, bilingual_str &error)
Wrapper that overrides the GetParams() function of a stream.
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.
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().
Minimal stream for reading from an existing byte array by std::span.
std::tuple< std::span< const uint8_t >, bool, const std::string & > BytesToSend
Return type for GetBytesToSend, consisting of:
bool SetMessageToSend(CSerializedNetMsg &msg) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Set the next message to send.
Info GetInfo() const noexcept override
Retrieve information about this transport.
int readData(std::span< const uint8_t > msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Mutex m_send_mutex
Lock for sending state.
const MessageStartChars m_magic_bytes
size_t GetSendMemoryUsage() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Return the memory usage of this transport attributable to buffered data to send.
const uint256 & GetMessageHash() const EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
void MarkBytesSent(size_t bytes_sent) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Report how many bytes returned by the last GetBytesToSend() have been sent.
int readHeader(std::span< const uint8_t > msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
bool CompleteInternal() const noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
V1Transport(NodeId node_id) noexcept
BytesToSend GetBytesToSend(bool have_next_message) const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Get bytes to send on the wire, if any, along with other information about it.
void Reset() EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Mutex m_recv_mutex
Lock for receive state.
CNetMessage GetReceivedMessage(std::chrono::microseconds time, bool &reject_message) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Retrieve a completed message from transport.
void MarkBytesSent(size_t bytes_sent) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Report how many bytes returned by the last GetBytesToSend() have been sent.
static constexpr uint32_t MAX_GARBAGE_LEN
const NodeId m_nodeid
NodeId (for debug logging).
size_t GetMaxBytesToProcess() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Determine how many received bytes can be processed in one go (not allowed in V1 state).
BIP324Cipher m_cipher
Cipher state.
size_t GetSendMemoryUsage() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Return the memory usage of this transport attributable to buffered data to send.
void ProcessReceivedMaybeV1Bytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex
Process bytes in m_recv_buffer, while in KEY_MAYBE_V1 state.
SendState
State type that controls the sender side.
@ READY
Normal sending state.
@ AWAITING_KEY
Waiting for the other side's public key.
@ V1
This transport is using v1 fallback.
@ MAYBE_V1
(Responder only) Not sending until v1 or v2 is detected.
V1Transport m_v1_fallback
Encapsulate a V1Transport to fall back to.
static constexpr size_t V1_PREFIX_LEN
The length of the V1 prefix to match bytes initially received by responders with to determine if thei...
void StartSendingHandshake() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_send_mutex)
Put our public key + garbage in the send buffer.
bool ProcessReceivedPacketBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Process bytes in m_recv_buffer, while in VERSION/APP state.
bool ProcessReceivedKeyBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex
Process bytes in m_recv_buffer, while in KEY state.
const bool m_initiating
Whether we are the initiator side.
Info GetInfo() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Retrieve information about this transport.
BytesToSend GetBytesToSend(bool have_next_message) const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Get bytes to send on the wire, if any, along with other information about it.
void SetReceiveState(RecvState recv_state) noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Change the receive state.
bool ProcessReceivedGarbageBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Process bytes in m_recv_buffer, while in GARB_GARBTERM state.
bool ReceivedMessageComplete() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Returns true if the current message is complete (so GetReceivedMessage can be called).
CNetMessage GetReceivedMessage(std::chrono::microseconds time, bool &reject_message) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Retrieve a completed message from transport.
static constexpr std::array< std::byte, 0 > VERSION_CONTENTS
Contents of the version packet to send.
static std::optional< std::string > GetMessageType(std::span< const uint8_t > &contents) noexcept
Given a packet's contents, find the message type (if valid), and strip it from contents.
bool ReceivedBytes(std::span< const uint8_t > &msg_bytes) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex
Feed wire bytes to the transport.
bool ShouldReconnectV1() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex
Whether upon disconnections, a reconnect with V1 is warranted.
bool SetMessageToSend(CSerializedNetMsg &msg) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Set the next message to send.
V2Transport(NodeId nodeid, bool initiating) noexcept
Construct a V2 transport with securely generated random keys.
RecvState
State type that defines the current contents of the receive buffer and/or how the next received bytes...
@ GARB_GARBTERM
Garbage and garbage terminator.
@ V1
Nothing (this transport is using v1 fallback).
@ KEY_MAYBE_V1
(Responder only) either v2 public key or v1 header.
@ APP_READY
Nothing (an application packet is available for GetMessage()).
void SetSendState(SendState send_state) noexcept EXCLUSIVE_LOCKS_REQUIRED(m_send_mutex)
Change the send state.
constexpr unsigned char * begin()
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
void push_back(const T &value)
#define WSAGetLastError()
#define COMPAT_IN6ADDR_ANY_INIT
std::string ConnectionTypeAsString(ConnectionType conn_type)
Convert ConnectionType enum to a string value.
ConnectionType
Different types of connections to a peer.
@ PRIVATE_BROADCAST
Private broadcast connections are short-lived and only opened to privacy networks (Tor,...
@ BLOCK_RELAY
We use block-relay-only connections to help prevent against partition attacks.
@ MANUAL
We open manual connections to addresses that users explicitly requested via the addnode RPC or the -a...
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
@ FEELER
Feeler connections are short-lived connections made to check that a node is alive.
@ INBOUND
Inbound connections are those initiated by a peer.
@ ADDR_FETCH
AddrFetch connections are short lived connections used to solicit addresses from peers.
@ V1
Unencrypted, plaintext protocol.
@ DETECTING
Peer could be v1 or v2.
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE
The maximum allowed size for a serialized block, in bytes (only for buffer size limits).
uint32_t ReadLE32(const B *ptr)
static CService ip(uint32_t i)
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 std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
CKey GenerateRandomKey(bool compressed) noexcept
#define LogDebug(category,...)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
constexpr const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
constexpr const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
constexpr const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
constexpr const char * TX
The tx message transmits a single transaction.
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
constexpr const char * BLOCK
The block message transmits a single serialized block.
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
constexpr const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
FILE * fopen(const fs::path &p, const char *mode)
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
void TraceThread(std::string_view thread_name, std::function< void()> thread_func)
A wrapper for do-something-once thread functions.
static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE
Number of DNS seeds to query when the number of connections is low.
bool IsLocal(const CService &addr)
check whether a given address is potentially local
static const uint64_t RANDOMIZER_ID_NETGROUP
static const uint64_t SELECT_TIMEOUT_MILLISECONDS
static const uint64_t RANDOMIZER_ID_NETWORKKEY
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 auto EXTRA_NETWORK_PEER_INTERVAL
Frequency to attempt extra connections to reachable networks we're not connected to yet.
static constexpr int SEED_OUTBOUND_CONNECTION_THRESHOLD
Minimum number of outbound connections under which we will keep fetching our address seeds.
bool AddLocal(const CService &addr_, int nScore)
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.
static bool IsPeerAddrLocalGood(CNode *pnode)
static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS
How long to delay before querying DNS seeds.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
const std::string NET_MESSAGE_TYPE_OTHER
static std::unique_ptr< Transport > MakeTransport(NodeId id, bool use_v2transport, bool inbound) noexcept
const char *const ANCHORS_DATABASE_FILENAME
Anchor IP address database file name.
static std::vector< CAddress > ConvertSeeds(const std::vector< uint8_t > &vSeedsIn)
Convert the serialized seeds into usable address objects.
static void CaptureMessageToFile(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)
CService GetLocalAddress(const CNode &peer)
GlobalMutex g_maplocalhost_mutex
static std::optional< CService > GetLocal(const CNode &peer)
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS
static int GetnScore(const CService &addr)
static bool IsOutboundMessageAllowedInPrivateBroadcast(std::string_view type) noexcept
Private broadcast connections only need to send certain message types.
static CNetCleanup instance_of_cnetcleanup
static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME
The default timeframe for -maxuploadtarget.
bool SeenLocal(const CService &addr)
vote for a local address
static constexpr bool DEFAULT_PRIVATE_BROADCAST
Default for -privatebroadcast.
bool IsLocal(const CService &addr)
check whether a given address is potentially local
void RemoveLocal(const CService &addr)
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
bool AddLocal(const CService &addr, int nScore=LOCAL_NONE)
static constexpr bool DEFAULT_FIXEDSEEDS
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH
Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable).
static constexpr auto EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL
Run the extra block-relay-only connection loop once every 5 minutes.
const std::string NET_MESSAGE_TYPE_OTHER
static constexpr bool DEFAULT_FORCEDNSSEED
static constexpr bool DEFAULT_DNSSEED
GlobalMutex g_maplocalhost_mutex
static constexpr std::chrono::hours ASMAP_HEALTH_CHECK_INTERVAL
Interval for ASMap Health Check.
static constexpr auto FEELER_INTERVAL
Run the feeler connection loop once every 2 minutes.
std::function< void(const CAddress &addr, const std::string &msg_type, std::span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
static const int MAX_OUTBOUND_FULL_RELAY_CONNECTIONS
Maximum number of automatic outgoing nodes over which we'll relay everything (blocks,...
static const int MAX_BLOCK_RELAY_ONLY_CONNECTIONS
Maximum number of block-relay-only outgoing connections.
void Discover()
Look up IP addresses from all interfaces on the machine and add them to the list of local addresses t...
static constexpr uint16_t I2P_SAM31_PORT
SAM 3.1 and earlier do not support specifying ports and force the port to 0.
@ 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.
std::string GetNetworkName(enum Network net)
CThreadInterrupt g_socks5_interrupt
Interrupt SOCKS5 reads or writes.
CService GetBindAddress(const Sock &sock)
Get the bind address for a socket as CService.
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.
CService MaybeFlipIPv6toCJDNS(const CService &service)
If an IPv6 address belongs to the address range used by the CJDNS network and the CJDNS network is re...
ReachableNets g_reachable_nets
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::array ALL_NET_MESSAGE_TYPES
All known message types (see above).
constexpr ServiceFlags SeedsServiceFlags()
State independent service flags.
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.
uint256 GetRandHash() noexcept
Generate a random uint256.
void ser_writedata32(Stream &s, uint32_t obj)
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
void ser_writedata64(Stream &s, uint64_t obj)
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
auto MakeByteSpan(const V &v) noexcept
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
T & SpanPopBack(std::span< T > &span)
A span is an object that can refer to a contiguous sequence of objects.
auto MakeWritableByteSpan(V &&v) noexcept
unsigned char * UCharCast(char *c)
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....
std::vector< unsigned char > data
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
An ElligatorSwift-encoded public key.
static constexpr size_t size()
static time_point now() noexcept
Return current system time or mocked time, if set.
Auxiliary requested/occurred events to wait for in WaitMany().
std::optional< uint256 > session_id
TransportProtocolType transport_type
An established connection with another peer.
std::unique_ptr< Sock > sock
Connected socket.
CService me
Our I2P address.
CService peer
The peer's I2P address.
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
AnnotatedMixin< std::mutex > Mutex
Wrapped mutex: supports waiting but not recursive locking.
#define WITH_LOCK(cs, code)
#define AssertLockHeld(cs)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define TRACEPOINT(context,...)
#define TRACEPOINT_SEMAPHORE(context, event)
consteval auto _(util::TranslatedLiteral str)
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.
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
T Now()
Return the current time point cast to the given precision.
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
void ClearShrink(V &v) noexcept
Clear a vector (or std::deque) and release its allocated memory.