6#include <bitcoin-build-config.h>
47#include <unordered_map>
57static_assert (MAX_BLOCK_RELAY_ONLY_ANCHORS <= static_cast<size_t>(
MAX_BLOCK_RELAY_ONLY_CONNECTIONS),
"MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
134 m_addr_fetches.push_back(strDest);
140 for (
const std::string& bind_arg :
gArgs.
GetArgs(
"-bind")) {
141 constexpr uint16_t dummy_port = 0;
143 const std::optional<CService> bind_addr{
Lookup(bind_arg, dummy_port,
false)};
144 if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port)
return bind_addr->GetPort();
149 for (
const std::string& whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
166 if (!
fListen)
return std::nullopt;
168 std::optional<CService> addr;
170 int nBestReachability = -1;
173 for (
const auto& [local_addr, local_service_info] : mapLocalHost) {
181 const int nScore{local_service_info.nScore};
182 const int nReachability{local_addr.GetReachabilityFrom(peer.
addr)};
183 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) {
184 addr.emplace(
CService{local_addr, local_service_info.nPort});
185 nBestReachability = nReachability;
194static std::vector<CAddress>
ConvertSeeds(
const std::vector<uint8_t> &vSeedsIn)
200 const auto one_week{7 * 24h};
201 std::vector<CAddress> vSeedsOut;
210 vSeedsOut.push_back(addr);
227 const auto it = mapLocalHost.find(addr);
228 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
249 if (
node.IsInboundConn()) {
258 addrLocal.SetIP(
node.GetAddrLocal());
261 if (addrLocal.IsRoutable()) {
274 if (!addr.IsRoutable())
283 LogPrintf(
"AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
287 const auto [it, is_newly_added] = mapLocalHost.emplace(addr,
LocalServiceInfo());
289 if (is_newly_added || nScore >= info.
nScore) {
290 info.
nScore = nScore + (is_newly_added ? 0 : 1);
291 info.
nPort = addr.GetPort();
307 mapLocalHost.erase(addr);
314 const auto it = mapLocalHost.find(addr);
315 if (it == mapLocalHost.end())
return false;
325 return mapLocalHost.count(addr) > 0;
331 for (
CNode* pnode : m_nodes) {
332 if (
static_cast<CNetAddr>(pnode->addr) ==
ip) {
342 for (
CNode* pnode : m_nodes) {
343 if (pnode->m_addr_name == addrName) {
353 for (
CNode* pnode : m_nodes) {
354 if (
static_cast<CService>(pnode->addr) == addr) {
369 for (
const CNode* pnode : m_nodes) {
370 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() ==
nonce)
380 struct sockaddr_storage sockaddr_bind;
381 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
382 if (!sock.
GetSockName((
struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
383 addr_bind.
SetSockAddr((
const struct sockaddr*)&sockaddr_bind, sockaddr_bind_len);
395 if (pszDest ==
nullptr) {
403 LogPrintf(
"Failed to open new connection, already connected\n");
411 Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.
nTime));
414 const uint16_t default_port{pszDest !=
nullptr ?
GetDefaultPort(pszDest) :
418 std::vector<CAddress> connect_to{};
421 if (!resolved.empty()) {
425 for (
const auto& r : resolved) {
440 connect_to.push_back(addrConnect);
444 connect_to.push_back(addrConnect);
448 connect_to.push_back(addrConnect);
452 std::unique_ptr<Sock> sock;
456 std::unique_ptr<i2p::sam::Session> i2p_transient_session;
458 for (
auto& target_addr: connect_to) {
459 if (target_addr.IsValid()) {
460 const bool use_proxy{
GetProxy(target_addr.GetNetwork(), proxy)};
461 bool proxyConnectionFailed =
false;
463 if (target_addr.IsI2P() && use_proxy) {
465 bool connected{
false};
468 connected =
m_i2p_sam_session->Connect(target_addr, conn, proxyConnectionFailed);
472 if (m_unused_i2p_sessions.empty()) {
473 i2p_transient_session =
474 std::make_unique<i2p::sam::Session>(proxy, &
interruptNet);
476 i2p_transient_session.swap(m_unused_i2p_sessions.front());
477 m_unused_i2p_sessions.pop();
480 connected = i2p_transient_session->Connect(target_addr, conn, proxyConnectionFailed);
484 m_unused_i2p_sessions.emplace(i2p_transient_session.release());
490 sock = std::move(conn.
sock);
493 }
else if (use_proxy) {
495 sock =
ConnectThroughProxy(proxy, target_addr.ToStringAddr(), target_addr.GetPort(), proxyConnectionFailed);
500 if (!proxyConnectionFailed) {
507 uint16_t port{default_port};
509 bool proxyConnectionFailed;
533 pszDest ? pszDest :
"",
538 .i2p_sam_session = std::move(i2p_transient_session),
568 m_i2p_sam_session.reset();
572 for (
const auto& subnet : ranges) {
573 if (subnet.m_subnet.Match(addr)) {
596 if (
Assume(!m_addr_local.IsValid())) {
597 m_addr_local = addrLocalIn;
612#define X(name) stats.name = name
635 X(mapSendBytesPerMsgType);
640 X(mapRecvBytesPerMsgType);
662 const auto time = GetTime<std::chrono::microseconds>();
664 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
665 nRecvBytes += msg_bytes.size();
666 while (msg_bytes.size() > 0) {
675 bool reject_message{
false};
677 if (reject_message) {
686 auto i = mapRecvBytesPerMsgType.find(
msg.m_type);
687 if (i == mapRecvBytesPerMsgType.end()) {
690 assert(i != mapRecvBytesPerMsgType.end());
691 i->second +=
msg.m_raw_message_size;
710 return strprintf(
"disconnecting peer=%d%s",
732 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
734 memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy);
745 catch (
const std::exception&) {
773 unsigned int nRemaining = hdr.nMessageSize - nDataPos;
774 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
776 if (vRecv.size() < nDataPos + nCopy) {
778 vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
781 hasher.Write(msg_bytes.first(nCopy));
782 memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy);
792 if (data_hash.IsNull())
793 hasher.Finalize(data_hash);
801 reject_message =
false;
807 msg.m_type = hdr.GetMessageType();
809 msg.m_message_size = hdr.nMessageSize;
819 LogDebug(
BCLog::NET,
"Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
824 reject_message =
true;
825 }
else if (!hdr.IsMessageTypeValid()) {
828 reject_message =
true;
841 if (m_sending_header || m_bytes_sent < m_message_to_send.data.size())
return false;
851 m_header_to_send.clear();
855 m_message_to_send = std::move(
msg);
856 m_sending_header =
true;
865 if (m_sending_header) {
866 return {std::span{m_header_to_send}.subspan(m_bytes_sent),
869 have_next_message || !m_message_to_send.data.empty(),
870 m_message_to_send.m_type
873 return {std::span{m_message_to_send.data}.subspan(m_bytes_sent),
877 m_message_to_send.m_type
886 m_bytes_sent += bytes_sent;
887 if (m_sending_header && m_bytes_sent == m_header_to_send.size()) {
889 m_sending_header =
false;
891 }
else if (!m_sending_header && m_bytes_sent == m_message_to_send.data.size()) {
903 return m_message_to_send.GetMemoryUsage();
913const std::array<std::string, 33> V2_MESSAGE_IDS = {
952 std::unordered_map<std::string, uint8_t> m_map;
955 V2MessageMap() noexcept
957 for (
size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
958 m_map.emplace(V2_MESSAGE_IDS[i], i);
962 std::optional<uint8_t> operator()(
const std::string& message_name)
const noexcept
964 auto it = m_map.find(message_name);
965 if (it == m_map.end())
return std::nullopt;
970const V2MessageMap V2_MESSAGE_MAP;
972std::vector<uint8_t> GenerateRandomGarbage() noexcept
974 std::vector<uint8_t>
ret;
987 Assume(m_send_buffer.empty());
991 std::copy(m_send_garbage.begin(), m_send_garbage.end(), m_send_buffer.begin() +
EllSwiftPubKey::size());
996 : m_cipher{key, ent32}, m_initiating{initiating}, m_nodeid{nodeid},
997 m_v1_fallback{nodeid},
998 m_recv_state{initiating ?
RecvState::KEY : RecvState::KEY_MAYBE_V1},
999 m_send_garbage{std::move(garbage)},
1000 m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
1002 Assume(m_send_garbage.size() <= MAX_GARBAGE_LEN);
1006 StartSendingHandshake();
1018 switch (m_recv_state) {
1019 case RecvState::KEY_MAYBE_V1:
1023 Assume(recv_state == RecvState::GARB_GARBTERM);
1025 case RecvState::GARB_GARBTERM:
1029 Assume(recv_state == RecvState::APP);
1031 case RecvState::APP:
1032 Assume(recv_state == RecvState::APP_READY);
1034 case RecvState::APP_READY:
1035 Assume(recv_state == RecvState::APP);
1042 m_recv_state = recv_state;
1049 switch (m_send_state) {
1050 case SendState::MAYBE_V1:
1051 Assume(send_state == SendState::V1 || send_state == SendState::AWAITING_KEY);
1053 case SendState::AWAITING_KEY:
1054 Assume(send_state == SendState::READY);
1056 case SendState::READY:
1062 m_send_state = send_state;
1083 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};
1084 std::copy(std::begin(
Params().MessageStart()), std::end(
Params().MessageStart()), v1_prefix.begin());
1085 Assume(m_recv_buffer.size() <= v1_prefix.size());
1086 if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), v1_prefix.begin())) {
1093 }
else if (m_recv_buffer.size() == v1_prefix.size()) {
1096 std::span<const uint8_t> feedback{m_recv_buffer};
1100 Assume(feedback.empty());
1125 static constexpr std::array<uint8_t, 12> MATCH = {
'v',
'e',
'r',
's',
'i',
'o',
'n', 0, 0, 0, 0, 0};
1126 static constexpr size_t OFFSET = std::tuple_size_v<MessageStartChars>;
1127 if (!
m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
1128 if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
1130 HexStr(std::span(m_recv_buffer).first(OFFSET)));
1146 m_recv_buffer.clear();
1180 m_recv_aad = std::move(m_recv_buffer);
1182 m_recv_buffer.clear();
1208 static constexpr size_t MAX_CONTENTS_LEN =
1215 if (m_recv_len > MAX_CONTENTS_LEN) {
1223 m_recv_decode_buffer.resize(m_recv_len);
1242 switch (m_recv_state) {
1271 switch (m_recv_state) {
1321 static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024;
1324 if (m_recv_state == RecvState::V1)
return m_v1_fallback.ReceivedBytes(msg_bytes);
1330 while (!msg_bytes.empty()) {
1332 size_t max_read = GetMaxBytesToProcess();
1335 if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
1336 switch (m_recv_state) {
1337 case RecvState::KEY_MAYBE_V1:
1339 case RecvState::GARB_GARBTERM:
1345 case RecvState::APP: {
1351 size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
1352 m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
1355 case RecvState::APP_READY:
1357 Assume(m_recv_buffer.empty());
1367 max_read = std::min(msg_bytes.size(), max_read);
1369 m_recv_buffer.insert(m_recv_buffer.end(),
UCharCast(msg_bytes.data()),
UCharCast(msg_bytes.data() + max_read));
1370 msg_bytes = msg_bytes.subspan(max_read);
1373 switch (m_recv_state) {
1374 case RecvState::KEY_MAYBE_V1:
1375 ProcessReceivedMaybeV1Bytes();
1376 if (m_recv_state == RecvState::V1)
return true;
1380 if (!ProcessReceivedKeyBytes())
return false;
1383 case RecvState::GARB_GARBTERM:
1384 if (!ProcessReceivedGarbageBytes())
return false;
1388 case RecvState::APP:
1389 if (!ProcessReceivedPacketBytes())
return false;
1392 case RecvState::APP_READY:
1409 if (contents.size() == 0)
return std::nullopt;
1410 uint8_t first_byte = contents[0];
1411 contents = contents.subspan(1);
1413 if (first_byte != 0) {
1415 if (first_byte < std::size(V2_MESSAGE_IDS)) {
1417 return V2_MESSAGE_IDS[first_byte];
1420 return std::nullopt;
1425 return std::nullopt;
1428 size_t msg_type_len{0};
1431 if (contents[msg_type_len] <
' ' || contents[msg_type_len] > 0x7F) {
1436 std::string
ret{
reinterpret_cast<const char*
>(contents.data()), msg_type_len};
1439 if (contents[msg_type_len] != 0)
return {};
1451 if (m_recv_state == RecvState::V1)
return m_v1_fallback.GetReceivedMessage(time, reject_message);
1453 Assume(m_recv_state == RecvState::APP_READY);
1454 std::span<const uint8_t> contents{m_recv_decode_buffer};
1455 auto msg_type = GetMessageType(contents);
1460 reject_message =
false;
1461 msg.m_type = std::move(*msg_type);
1463 msg.m_message_size = contents.size();
1464 msg.m_recv.resize(contents.size());
1465 std::copy(contents.begin(), contents.end(),
UCharCast(
msg.m_recv.data()));
1467 LogDebug(
BCLog::NET,
"V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(), m_nodeid);
1468 reject_message =
true;
1471 SetReceiveState(RecvState::APP);
1480 if (m_send_state == SendState::V1)
return m_v1_fallback.SetMessageToSend(
msg);
1484 if (!(m_send_state == SendState::READY && m_send_buffer.empty()))
return false;
1486 std::vector<uint8_t> contents;
1487 auto short_message_id = V2_MESSAGE_MAP(
msg.m_type);
1488 if (short_message_id) {
1489 contents.resize(1 +
msg.data.size());
1490 contents[0] = *short_message_id;
1491 std::copy(
msg.data.begin(),
msg.data.end(), contents.begin() + 1);
1496 std::copy(
msg.m_type.begin(),
msg.m_type.end(), contents.data() + 1);
1502 m_send_type =
msg.m_type;
1512 if (m_send_state == SendState::V1)
return m_v1_fallback.GetBytesToSend(have_next_message);
1514 if (m_send_state == SendState::MAYBE_V1)
Assume(m_send_buffer.empty());
1515 Assume(m_send_pos <= m_send_buffer.size());
1517 std::span{m_send_buffer}.subspan(m_send_pos),
1520 have_next_message && m_send_state == SendState::READY,
1529 if (m_send_state == SendState::V1)
return m_v1_fallback.MarkBytesSent(bytes_sent);
1531 if (m_send_state == SendState::AWAITING_KEY && m_send_pos == 0 && bytes_sent > 0) {
1535 m_send_pos += bytes_sent;
1536 Assume(m_send_pos <= m_send_buffer.size());
1538 m_sent_v1_header_worth =
true;
1541 if (m_send_pos == m_send_buffer.size()) {
1558 if (!m_recv_buffer.empty())
return false;
1561 return m_sent_v1_header_worth;
1596 auto it =
node.vSendMsg.begin();
1597 size_t nSentSize = 0;
1598 bool data_left{
false};
1599 std::optional<bool> expected_more;
1602 if (it !=
node.vSendMsg.end()) {
1606 size_t memusage = it->GetMemoryUsage();
1607 if (
node.m_transport->SetMessageToSend(*it)) {
1613 const auto& [
data, more, msg_type] =
node.m_transport->GetBytesToSend(it !=
node.vSendMsg.end());
1617 if (expected_more.has_value())
Assume(!
data.empty() == *expected_more);
1618 expected_more = more;
1619 data_left = !
data.empty();
1621 if (!
data.empty()) {
1635 nBytes =
node.m_sock->Send(
reinterpret_cast<const char*
>(
data.data()),
data.size(),
flags);
1638 node.m_last_send = GetTime<std::chrono::seconds>();
1639 node.nSendBytes += nBytes;
1641 node.m_transport->MarkBytesSent(nBytes);
1643 if (!msg_type.empty()) {
1644 node.AccountForSentBytes(msg_type, nBytes);
1646 nSentSize += nBytes;
1647 if ((
size_t)nBytes !=
data.size()) {
1657 node.CloseSocketDisconnect();
1666 if (it ==
node.vSendMsg.end()) {
1669 node.vSendMsg.erase(
node.vSendMsg.begin(), it);
1670 return {nSentSize, data_left};
1683 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1688 if (
node->fDisconnect)
1692 .m_connected =
node->m_connected,
1693 .m_min_ping_time =
node->m_min_ping_time,
1694 .m_last_block_time =
node->m_last_block_time,
1695 .m_last_tx_time =
node->m_last_tx_time,
1696 .fRelevantServices =
node->m_has_all_wanted_services,
1697 .m_relay_txs =
node->m_relays_txs.load(),
1698 .fBloomFilter =
node->m_bloom_filter_loaded.load(),
1699 .nKeyedNetGroup =
node->nKeyedNetGroup,
1700 .prefer_evict =
node->m_prefer_evict,
1701 .m_is_local =
node->addr.IsLocal(),
1702 .m_network =
node->ConnectedThroughNetwork(),
1704 .m_conn_type =
node->m_conn_type,
1706 vEvictionCandidates.push_back(candidate);
1709 const std::optional<NodeId> node_id_to_evict =
SelectNodeToEvict(std::move(vEvictionCandidates));
1710 if (!node_id_to_evict) {
1714 for (
CNode* pnode : m_nodes) {
1715 if (pnode->GetId() == *node_id_to_evict) {
1716 LogDebug(
BCLog::NET,
"selected %s connection for eviction, %s", pnode->ConnectionTypeAsString(), pnode->DisconnectMsg(
fLogIPs));
1719 pnode->m_addr_name.c_str(),
1720 pnode->ConnectionTypeAsString().c_str(),
1721 pnode->ConnectedThroughNetwork(),
1722 Ticks<std::chrono::seconds>(pnode->m_connected));
1723 pnode->fDisconnect =
true;
1731 struct sockaddr_storage sockaddr;
1732 socklen_t len =
sizeof(sockaddr);
1733 auto sock = hListenSocket.
sock->Accept((
struct sockaddr*)&sockaddr, &len);
1744 if (!addr.
SetSockAddr((
const struct sockaddr*)&sockaddr, len)) {
1769 for (
const CNode* pnode : m_nodes) {
1770 if (pnode->IsInboundConn()) nInbound++;
1779 if (!sock->IsSelectable()) {
1787 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
1788 LogDebug(
BCLog::NET,
"connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
1812 LogDebug(
BCLog::NET,
"failed to find an eviction candidate - connection dropped (full)\n");
1837 .prefer_evict = discouraged,
1842 m_msgproc->InitializeNode(*pnode, local_services);
1845 m_nodes.push_back(pnode);
1862 std::optional<int> max_connections;
1863 switch (conn_type) {
1883 return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](
CNode*
node) { return node->m_conn_type == conn_type; }););
1886 if (max_connections != std::nullopt && existing_connections >= max_connections)
return false;
1890 if (!grant)
return false;
1903 decltype(m_reconnections) reconnections_to_add;
1909 if (!network_active) {
1911 for (
CNode* pnode : m_nodes) {
1912 if (!pnode->fDisconnect) {
1914 pnode->fDisconnect =
true;
1920 std::vector<CNode*> nodes_copy = m_nodes;
1921 for (
CNode* pnode : nodes_copy)
1923 if (pnode->fDisconnect)
1926 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());
1931 if (network_active && pnode->m_transport->ShouldReconnectV1()) {
1932 reconnections_to_add.push_back({
1933 .addr_connect = pnode->addr,
1934 .grant = std::move(pnode->grantOutbound),
1935 .destination = pnode->m_dest,
1936 .conn_type = pnode->m_conn_type,
1937 .use_v2transport =
false});
1938 LogDebug(
BCLog::NET,
"retrying with v1 transport protocol for peer=%d\n", pnode->GetId());
1942 pnode->grantOutbound.Release();
1945 pnode->CloseSocketDisconnect();
1948 if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];
1959 for (
CNode* pnode : nodes_disconnected_copy)
1962 if (pnode->GetRefCount() <= 0) {
1971 m_reconnections.splice(m_reconnections.end(), std::move(reconnections_to_add));
1980 nodes_size = m_nodes.size();
1999 const auto now{GetTime<std::chrono::seconds>()};
2000 const auto last_send{
node.m_last_send.load()};
2001 const auto last_recv{
node.m_last_recv.load()};
2005 bool has_received{last_recv.count() != 0};
2006 bool has_sent{last_send.count() != 0};
2008 if (!has_received || !has_sent) {
2009 std::string has_never;
2010 if (!has_received) has_never +=
", never received from peer";
2011 if (!has_sent) has_never +=
", never sent to peer";
2013 "socket no message in first %i seconds%s, %s\n",
2023 "socket sending timeout: %is, %s\n",
count_seconds(now - last_send),
2031 "socket receive timeout: %is, %s\n",
count_seconds(now - last_recv),
2037 if (!
node.fSuccessfullyConnected) {
2054 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
2057 for (
CNode* pnode : nodes) {
2058 bool select_recv = !pnode->fPauseRecv;
2061 LOCK(pnode->cs_vSend);
2065 const auto& [to_send, more, _msg_type] = pnode->m_transport->GetBytesToSend(!pnode->vSendMsg.empty());
2066 select_send = !to_send.empty() || more;
2068 if (!select_recv && !select_send)
continue;
2070 LOCK(pnode->m_sock_mutex);
2071 if (pnode->m_sock) {
2073 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
2077 return events_per_sock;
2096 if (events_per_sock.empty() || !events_per_sock.begin()->first->WaitMany(timeout, events_per_sock)) {
2113 for (
CNode* pnode : nodes) {
2120 bool recvSet =
false;
2121 bool sendSet =
false;
2122 bool errorSet =
false;
2124 LOCK(pnode->m_sock_mutex);
2125 if (!pnode->m_sock) {
2128 const auto it = events_per_sock.find(pnode->m_sock);
2129 if (it != events_per_sock.end()) {
2132 errorSet = it->second.occurred &
Sock::ERR;
2149 if (data_left) recvSet =
false;
2153 if (recvSet || errorSet)
2156 uint8_t pchBuf[0x10000];
2159 LOCK(pnode->m_sock_mutex);
2160 if (!pnode->m_sock) {
2163 nBytes = pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
2167 bool notify =
false;
2168 if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
2170 "receiving message bytes failed, %s\n",
2173 pnode->CloseSocketDisconnect();
2177 pnode->MarkReceivedMsgsForProcessing();
2181 else if (nBytes == 0)
2184 if (!pnode->fDisconnect) {
2187 pnode->CloseSocketDisconnect();
2189 else if (nBytes < 0)
2195 if (!pnode->fDisconnect) {
2198 pnode->CloseSocketDisconnect();
2213 const auto it = events_per_sock.find(listen_socket.sock);
2214 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
2236 fMsgProcWake =
true;
2243 int outbound_connection_count = 0;
2247 constexpr std::chrono::seconds SEEDNODE_TIMEOUT = 30
s;
2248 LogPrintf(
"-seednode enabled. Trying the provided seeds for %d seconds before defaulting to the dnsseeds.\n", SEEDNODE_TIMEOUT.count());
2256 LogPrintf(
"Couldn't connect to enough peers via seed nodes. Handing fetch logic to the DNS seeds.\n");
2262 LogPrintf(
"P2P peers available. Finished fetching data from seed nodes.\n");
2270 std::shuffle(seeds.begin(), seeds.end(), rng);
2271 int seeds_right_now = 0;
2275 seeds_right_now = seeds.size();
2280 seeds_right_now = seeds.size();
2300 for (
const std::string& seed : seeds) {
2301 if (seeds_right_now == 0) {
2305 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
2306 std::chrono::seconds to_wait = seeds_wait_time;
2307 while (to_wait.count() > 0) {
2317 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2318 LogPrintf(
"P2P peers available. Finished DNS seeding.\n");
2320 LogPrintf(
"P2P peers available. Skipped DNS seeding.\n");
2332 LogPrintf(
"Waiting for network to be reactivated before querying DNS seeds.\n");
2338 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
2344 std::vector<CAddress> vAdd;
2346 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
2355 unsigned int nMaxIPs = 32;
2356 const auto addresses{
LookupHost(host, nMaxIPs,
true)};
2357 if (!addresses.empty()) {
2361 vAdd.push_back(addr);
2374 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2376 LogPrintf(
"Skipping DNS seeds. Enough peers have been found\n");
2382 const auto start{SteadyClock::now()};
2387 addrman.
Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
2393 std::string strDest;
2396 if (m_addr_fetches.empty())
2398 strDest = m_addr_fetches.front();
2399 m_addr_fetches.pop_front();
2419 LogDebug(
BCLog::NET,
"setting try another outbound peer=%s\n", flag ?
"true" :
"false");
2434 for (
const CNode* pnode : m_nodes) {
2435 if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
2449 int full_outbound_peers = 0;
2452 for (
const CNode* pnode : m_nodes) {
2453 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
2454 ++full_outbound_peers;
2463 int block_relay_peers = 0;
2466 for (
const CNode* pnode : m_nodes) {
2467 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
2468 ++block_relay_peers;
2477 std::unordered_set<Network> networks{};
2478 for (
int n = 0; n <
NET_MAX; n++) {
2482 networks.insert(net);
2491 return m_network_conn_counts[net] > 1;
2500 for (
const auto net : nets) {
2516 if (!connect.empty())
2521 for (int64_t nLoop = 0;; nLoop++)
2523 for (
const std::string& strAddr : connect)
2527 for (
int i = 0; i < 10 && i < nLoop; i++)
2540 auto start = GetTime<std::chrono::microseconds>();
2548 const bool use_seednodes{!
gArgs.
GetArgs(
"-seednode").empty()};
2551 bool add_addr_fetch{
addrman.
Size() == 0 && !seed_nodes.empty()};
2552 constexpr std::chrono::seconds ADD_NEXT_SEEDNODE = 10
s;
2554 if (!add_fixed_seeds) {
2555 LogPrintf(
"Fixed seeds are disabled\n");
2560 if (add_addr_fetch) {
2561 add_addr_fetch =
false;
2566 LogInfo(
"Empty addrman, adding seednode (%s) to addrfetch\n", seed);
2568 LogInfo(
"Couldn't connect to peers from addrman after %d seconds. Adding seednode (%s) to addrfetch\n", ADD_NEXT_SEEDNODE.count(), seed);
2584 if (add_fixed_seeds && !fixed_seed_networks.empty()) {
2589 bool add_fixed_seeds_now =
false;
2591 if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
2592 add_fixed_seeds_now =
true;
2593 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
2597 else if (!dnsseed && !use_seednodes) {
2599 if (m_added_node_params.empty()) {
2600 add_fixed_seeds_now =
true;
2601 LogPrintf(
"Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
2605 if (add_fixed_seeds_now) {
2613 seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
2614 [&fixed_seed_networks](
const CAddress& addr) { return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
2619 add_fixed_seeds =
false;
2620 LogPrintf(
"Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
2630 int nOutboundFullRelay = 0;
2631 int nOutboundBlockRelay = 0;
2632 int outbound_privacy_network_peers = 0;
2633 std::set<std::vector<unsigned char>> outbound_ipv46_peer_netgroups;
2637 for (
const CNode* pnode : m_nodes) {
2638 if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
2639 if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
2642 switch (pnode->m_conn_type) {
2655 const CAddress address{pnode->addr};
2656 if (address.IsTor() || address.IsI2P() || address.IsCJDNS()) {
2664 ++outbound_privacy_network_peers;
2675 add_addr_fetch =
true;
2680 auto now = GetTime<std::chrono::microseconds>();
2681 bool anchor =
false;
2682 bool fFeeler =
false;
2683 std::optional<Network> preferred_net;
2729 }
else if (now > next_feeler) {
2735 now > next_extra_network_peer &&
2786 std::tie(addr, addr_last_try) =
addrman.
Select(
true, reachable_nets);
2795 std::tie(addr, addr_last_try) =
addrman.
Select(
true, reachable_nets);
2802 std::tie(addr, addr_last_try) = preferred_net.has_value()
2822 if (current_time - addr_last_try < 10min && nTries < 30) {
2845 preferred_net.has_value() ?
"network-specific " :
"",
2870 const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(
m_max_automatic_connections - 1, 2)};
2880 std::vector<CAddress>
ret;
2882 for (
const CNode* pnode : m_nodes) {
2883 if (pnode->IsBlockOnlyConn()) {
2884 ret.push_back(pnode->addr);
2893 std::vector<AddedNodeInfo>
ret;
2895 std::list<AddedNodeParams> lAddresses(0);
2898 ret.reserve(m_added_node_params.size());
2899 std::copy(m_added_node_params.cbegin(), m_added_node_params.cend(), std::back_inserter(lAddresses));
2904 std::map<CService, bool> mapConnected;
2905 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2908 for (
const CNode* pnode : m_nodes) {
2909 if (pnode->addr.IsValid()) {
2910 mapConnected[pnode->addr] = pnode->IsInboundConn();
2912 std::string addrName{pnode->m_addr_name};
2913 if (!addrName.empty()) {
2914 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(),
static_cast<const CService&
>(pnode->addr));
2919 for (
const auto& addr : lAddresses) {
2922 if (service.IsValid()) {
2924 auto it = mapConnected.find(service);
2925 if (it != mapConnected.end()) {
2926 if (!include_connected) {
2929 addedNode.resolvedAddress = service;
2930 addedNode.fConnected =
true;
2931 addedNode.fInbound = it->second;
2935 auto it = mapConnectedByName.find(addr.m_added_node);
2936 if (it != mapConnectedByName.end()) {
2937 if (!include_connected) {
2940 addedNode.resolvedAddress = it->second.second;
2941 addedNode.fConnected =
true;
2942 addedNode.fInbound = it->second.first;
2945 ret.emplace_back(std::move(addedNode));
2996 bool banned_or_discouraged =
m_banman && (
m_banman->IsDiscouraged(addrConnect) ||
m_banman->IsBanned(addrConnect));
3000 }
else if (
FindNode(std::string(pszDest)))
3012 m_nodes.push_back(pnode);
3034 bool fMoreWork =
false;
3042 for (
CNode* pnode : snap.Nodes()) {
3043 if (pnode->fDisconnect)
3048 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
3063 fMsgProcWake =
false;
3069 static constexpr auto err_wait_begin = 1
s;
3070 static constexpr auto err_wait_cap = 5min;
3071 auto err_wait = err_wait_begin;
3073 bool advertising_listen_addr =
false;
3076 auto SleepOnFailure = [&]() {
3078 if (err_wait < err_wait_cap) {
3086 if (advertising_listen_addr && conn.
me.
IsValid()) {
3088 advertising_listen_addr =
false;
3094 if (!advertising_listen_addr) {
3096 advertising_listen_addr =
true;
3106 err_wait = err_wait_begin;
3115 struct sockaddr_storage sockaddr;
3116 socklen_t len =
sizeof(sockaddr);
3117 if (!addrBind.
GetSockAddr((
struct sockaddr*)&sockaddr, &len))
3148 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
3149 if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (
const char*)&nProtLevel,
sizeof(
int)) ==
SOCKET_ERROR) {
3156 if (sock->Bind(
reinterpret_cast<struct sockaddr*
>(&sockaddr), len) ==
SOCKET_ERROR) {
3159 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s is probably already running."), addrBind.
ToStringAddrPort(), CLIENT_NAME);
3186 LogPrintf(
"%s: %s\n", __func__, addr.ToStringAddr());
3192 LogPrintf(
"%s: %s\n", __func__, active);
3207 : addrman(addrman_in)
3208 , m_netgroupman{netgroupman}
3222 return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
3257 for (
const auto& addrBind : options.
vBinds) {
3262 for (
const auto& addrBind : options.
vWhiteBinds) {
3267 for (
const auto& addr_bind : options.
onion_binds) {
3279 struct in_addr inaddr_any;
3280 inaddr_any.s_addr = htonl(INADDR_ANY);
3297 _(
"Failed to listen on any port. Use -listen=0 if you want this."),
3310 std::vector<std::string> seed_nodes = connOptions.
vSeedNodes;
3311 if (!seed_nodes.empty()) {
3321 LogPrintf(
"%i block-relay-only anchors will be tried for connections.\n",
m_anchors.size());
3348 fMsgProcWake =
false;
3365 _(
"Cannot provide specific connections and have addrman find outgoing connections at the same time."),
3373 [
this, connect = connOptions.
m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });
3469 std::vector<CNode*> nodes;
3471 for (
CNode* pnode : nodes) {
3473 pnode->CloseSocketDisconnect();
3499std::vector<CAddress>
CConnman::GetAddresses(
size_t max_addresses,
size_t max_pct, std::optional<Network> network,
const bool filtered)
const
3501 std::vector<CAddress> addresses =
addrman.
GetAddr(max_addresses, max_pct, network, filtered);
3503 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3504 [
this](
const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
3515 .
Write(local_socket_bytes)
3520 const auto current_time = GetTime<std::chrono::microseconds>();
3558 const bool resolved_is_valid{resolved.
IsValid()};
3561 for (
const auto& it : m_added_node_params) {
3565 m_added_node_params.push_back(add);
3572 for (
auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
3573 if (strNode == it->m_added_node) {
3574 m_added_node_params.erase(it);
3587 return (m_added_node_params.size() < 24
3588 && std::any_of(m_added_node_params.cbegin(), m_added_node_params.cend(),
3589 [&](
const auto& p) { return p.m_added_node == addr_str || p.m_added_node == addr_port_str; }));
3596 return m_nodes.size();
3599 for (
const auto& pnode : m_nodes) {
3612 return mapLocalHost;
3624 vstats.reserve(m_nodes.size());
3625 for (
CNode* pnode : m_nodes) {
3626 vstats.emplace_back();
3627 pnode->CopyStats(vstats.back());
3628 vstats.back().m_mapped_as =
GetMappedAS(pnode->addr);
3637 pnode->fDisconnect =
true;
3645 bool disconnected =
false;
3647 for (
CNode* pnode : m_nodes) {
3648 if (subnet.
Match(pnode->addr)) {
3650 pnode->fDisconnect =
true;
3651 disconnected =
true;
3654 return disconnected;
3665 for(
CNode* pnode : m_nodes) {
3666 if (
id == pnode->GetId()) {
3668 pnode->fDisconnect =
true;
3685 nTotalBytesSent += bytes;
3687 const auto now = GetTime<std::chrono::seconds>();
3691 nMaxOutboundCycleStartTime = now;
3692 nMaxOutboundTotalBytesSentInCycle = 0;
3695 nMaxOutboundTotalBytesSentInCycle += bytes;
3724 if (nMaxOutboundCycleStartTime.count() == 0)
3728 const auto now = GetTime<std::chrono::seconds>();
3729 return (cycleEndTime < now) ? 0
s : cycleEndTime - now;
3739 if (historicalBlockServingLimit)
3772 return nTotalBytesSent;
3782 if (use_v2transport) {
3783 return std::make_unique<V2Transport>(
id, !inbound);
3785 return std::make_unique<V1Transport>(
id);
3790 std::shared_ptr<Sock> sock,
3792 uint64_t nKeyedNetGroupIn,
3793 uint64_t nLocalHostNonceIn,
3795 const std::string& addrNameIn,
3800 m_permission_flags{node_opts.permission_flags},
3802 m_connected{
GetTime<
std::chrono::seconds>()},
3804 addrBind{addrBindIn},
3805 m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
3807 m_inbound_onion{inbound_onion},
3808 m_prefer_evict{node_opts.prefer_evict},
3809 nKeyedNetGroup{nKeyedNetGroupIn},
3810 m_conn_type{conn_type_in},
3812 nLocalHostNonce{nLocalHostNonceIn},
3813 m_recv_flood_size{node_opts.recv_flood_size},
3814 m_i2p_sam_session{
std::move(node_opts.i2p_sam_session)}
3819 mapRecvBytesPerMsgType[
msg] = 0;
3834 size_t nSizeAdded = 0;
3838 nSizeAdded +=
msg.GetMemoryUsage();
3842 m_msg_process_queue.splice(m_msg_process_queue.end(),
vRecvMsg);
3843 m_msg_process_queue_size += nSizeAdded;
3850 if (m_msg_process_queue.empty())
return std::nullopt;
3852 std::list<CNetMessage> msgs;
3854 msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
3855 m_msg_process_queue_size -= msgs.front().GetMemoryUsage();
3858 return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
3869 size_t nMessageSize =
msg.data.size();
3884 size_t nBytesSent = 0;
3889 const auto& [to_send, more, _msg_type] =
3891 const bool queue_was_empty{to_send.empty() && pnode->vSendMsg.empty()};
3894 pnode->m_send_memusage +=
msg.GetMemoryUsage();
3897 pnode->vSendMsg.push_back(std::move(
msg));
3906 if (queue_was_empty && more) {
3915 CNode* found =
nullptr;
3917 for (
auto&& pnode : m_nodes) {
3918 if(pnode->
GetId() ==
id) {
3944 decltype(m_reconnections) todo;
3947 if (m_reconnections.empty())
break;
3948 todo.splice(todo.end(), m_reconnections, m_reconnections.begin());
3951 auto& item = *todo.begin();
3958 std::move(item.grant),
3959 item.destination.empty() ?
nullptr : item.destination.c_str(),
3961 item.use_v2transport);
3969 std::vector<CNetAddr> clearnet_addrs;
3970 clearnet_addrs.reserve(v4_addrs.size() + v6_addrs.size());
3971 std::transform(v4_addrs.begin(), v4_addrs.end(), std::back_inserter(clearnet_addrs),
3972 [](
const CAddress& addr) { return static_cast<CNetAddr>(addr); });
3973 std::transform(v6_addrs.begin(), v6_addrs.end(), std::back_inserter(clearnet_addrs),
3974 [](
const CAddress& addr) { return static_cast<CNetAddr>(addr); });
3980 const std::string& msg_type,
3981 std::span<const unsigned char>
data,
3988 auto now = GetTime<std::chrono::microseconds>();
3992 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3997 fs::path path = base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
4001 f << std::span{msg_type};
4005 uint32_t size =
data.size();
4010std::function<void(
const CAddress& addr,
4011 const std::string& msg_type,
4012 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.
std::pair< CAddress, NodeSeconds > Select(bool new_only=false, const std::unordered_set< Network > &networks={}) const
Choose an address to connect to.
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as connection attempted to.
size_t Size(std::optional< Network > net=std::nullopt, std::optional< bool > in_new=std::nullopt) const
Return size information about addrman.
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
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< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Non-refcounted RAII wrapper for FILE*.
bool Decrypt(std::span< const std::byte > input, std::span< const std::byte > aad, bool &ignore, std::span< std::byte > contents) noexcept
Decrypt a packet.
std::span< const std::byte > GetSendGarbageTerminator() const noexcept
Get the Garbage Terminator to send.
static constexpr unsigned GARBAGE_TERMINATOR_LEN
unsigned DecryptLength(std::span< const std::byte > input) noexcept
Decrypt the length of a packet.
std::span< const std::byte > GetSessionID() const noexcept
Get the Session ID.
const EllSwiftPubKey & GetOurPubKey() const noexcept
Retrieve our public key.
std::span< const std::byte > GetReceiveGarbageTerminator() const noexcept
Get the expected Garbage Terminator to receive.
static constexpr unsigned LENGTH_LEN
static constexpr unsigned EXPANSION
void Initialize(const EllSwiftPubKey &their_pubkey, bool initiator, bool self_decrypt=false) noexcept
Initialize when the other side's public key is received.
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
uint16_t GetDefaultPort() const
const std::vector< std::string > & DNSSeeds() const
Return the list of hostnames to look up for DNS seeds.
const std::vector< uint8_t > & FixedSeeds() const
RAII helper to atomically create a copy of m_nodes and add a reference to each of the nodes.
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
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 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.
CConnman(uint64_t seed0, uint64_t seed1, AddrMan &addrman, const NetGroupManager &netgroupman, const CChainParams ¶ms, bool network_active=true)
bool GetTryNewOutboundPeer() const
const bool use_v2transport(GetLocalServices() &NODE_P2P_V2)
uint16_t GetDefaultPort(Network net) const
void PerformReconnections() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex
Attempt reconnections, if m_reconnections non-empty.
std::thread threadI2PAcceptIncoming
void SetTryNewOutboundPeer(bool flag)
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
CThreadInterrupt interruptNet
This is signaled when network activity should cease.
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)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
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
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 NotifyNumConnectionsChanged()
ServiceFlags GetLocalServices() const
Used to convey which local services we are offering peers during node connection.
bool AddNode(const AddedNodeParams &add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
bool DisconnectNode(const std::string &node)
std::atomic_bool m_try_another_outbound_peer
flag for deciding to connect to an extra outbound peer, in excess of m_max_outbound_full_relay This t...
bool InitBinds(const Options &options)
CNode * ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
vWhitelistedRangeOutgoing
void AddAddrFetch(const std::string &strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex)
std::vector< ListenSocket > vhListenSocket
std::vector< CAddress > GetCurrentBlockRelayOnlyConns() const
Return vector of current BLOCK_RELAY peers.
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
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
uint32_t GetMappedAS(const CNetAddr &addr) 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)
Mutex m_reconnections_mutex
Mutex protecting m_reconnections.
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)
returns the time left in the current max outbound cycle in case of no limit, it will always return 0
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)
m_max_automatic_connections
void ThreadOpenConnections(std::vector< std::string > connect, std::span< const std::string > seed_nodes) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
bool fAddressesInitialized
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
std::thread threadOpenAddedConnections
Mutex m_added_nodes_mutex
vWhitelistedRangeIncoming
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
void AddWhitelistPermissionFlags(NetPermissionFlags &flags, const CNetAddr &addr, const std::vector< NetWhitelistPermissions > &ranges) const
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
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)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
uint64_t GetOutboundTargetBytesLeft() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
response the bytes left in the current max outbound cycle in case of no limit, it will always respons...
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.
void SocketHandlerListening(const Sock::EventsPerSock &events_per_sock)
Accept incoming connections, one from each read-ready listening socket.
std::thread threadSocketHandler
void OpenNetworkConnection(const CAddress &addrConnect, bool fCountFailure, CountingSemaphoreGrant<> &&grant_outbound, const char *strDest, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
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
bool SetSpecial(const std::string &addr)
Parse a Tor or I2P address and set this object to it.
std::vector< unsigned char > GetAddrBytes() const
bool IsPrivacyNet() const
Whether this object is a privacy network.
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.
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.
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.
void MarkReceivedMsgsForProcessing() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Move all messages from the received queue to the processing queue.
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.
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, CNodeOptions &&node_opts={})
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
std::atomic< std::chrono::microseconds > m_last_ping_time
Last measured round-trip time.
bool IsManualOrFullOutboundConn() 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
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
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
std::string ToString() const
bool Match(const CNetAddr &addr) const
std::chrono::steady_clock Clock
bool sleep_for(Clock::duration rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut)
RAII-style semaphore lock.
Double ended buffer combining vector and stream-like interfaces.
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
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.
bool UsingASMap() const
Indicates whether ASMap is being used for clearnet bucketing.
void ASMapHealthCheck(const std::vector< CNetAddr > &clearnet_addrs) const
Analyze and log current health of ASMap based buckets.
std::vector< unsigned char > GetGroup(const CNetAddr &address) const
Get the canonical identifier of the network group for address.
uint32_t GetMappedAS(const CNetAddr &address) const
Get the autonomous system on the BGP path to address.
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)
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.
std::unordered_set< Network > All() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
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().
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)
V1Transport(const NodeId node_id) noexcept
bool CompleteInternal() const noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
bool ReceivedBytes(std::span< const uint8_t > &msg_bytes) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Feed wire bytes to the 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 Reset() EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Mutex m_recv_mutex
Lock for receive state.
bool ReceivedMessageComplete() const 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) 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.
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()
#define WSAGetLastError()
std::string ConnectionTypeAsString(ConnectionType conn_type)
Convert ConnectionType enum to a string value.
ConnectionType
Different types of connections to a peer.
@ BLOCK_RELAY
We use block-relay-only connections to help prevent against partition attacks.
@ MANUAL
We open manual connections to addresses that users explicitly requested via the addnode RPC or the -a...
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
@ FEELER
Feeler connections are short-lived connections made to check that a node is alive.
@ INBOUND
Inbound connections are those initiated by a peer.
@ ADDR_FETCH
AddrFetch connections are short lived connections used to solicit addresses from peers.
@ 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,...
static path u8path(const std::string &utf8_str)
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...
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 LogPrintLevel(category, level,...)
#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 * 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,...
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.
static const unsigned char VERSION[]
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
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.
static CService GetBindAddress(const Sock &sock)
Get the bind address for a socket as CService.
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.
static const uint64_t RANDOMIZER_ID_ADDRCACHE
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
TRACEPOINT_SEMAPHORE(net, closed_connection)
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
std::map< CNetAddr, LocalServiceInfo > mapLocalHost GUARDED_BY(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 CNetCleanup instance_of_cnetcleanup
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 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 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.
static constexpr bool DEFAULT_FORCEDNSSEED
static constexpr bool DEFAULT_DNSSEED
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.
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.
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.
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....
NetPermissionFlags permission_flags
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)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define TRACEPOINT(context,...)
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.
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
void ClearShrink(V &v) noexcept
Clear a vector (or std::deque) and release its allocated memory.