6 #include <bitcoin-build-config.h> 44 #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS 54 #include <unordered_map> 141 m_addr_fetches.push_back(strDest);
147 for (
const std::string& bind_arg :
gArgs.
GetArgs(
"-bind")) {
148 constexpr uint16_t dummy_port = 0;
150 const std::optional<CService> bind_addr{
Lookup(bind_arg, dummy_port,
false)};
151 if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port)
return bind_addr->GetPort();
156 for (
const std::string& whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
173 if (!
fListen)
return std::nullopt;
175 std::optional<CService> addr;
177 int nBestReachability = -1;
180 for (
const auto& [local_addr, local_service_info] : mapLocalHost) {
188 const int nScore{local_service_info.nScore};
189 const int nReachability{local_addr.GetReachabilityFrom(peer.
addr)};
190 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) {
191 addr.emplace(
CService{local_addr, local_service_info.nPort});
192 nBestReachability = nReachability;
201 static std::vector<CAddress>
ConvertSeeds(
const std::vector<uint8_t> &vSeedsIn)
207 const auto one_week{7 * 24h};
208 std::vector<CAddress> vSeedsOut;
217 vSeedsOut.push_back(addr);
234 const auto it = mapLocalHost.find(addr);
235 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
256 if (
node.IsInboundConn()) {
265 addrLocal.SetIP(
node.GetAddrLocal());
268 if (addrLocal.IsRoutable()) {
281 if (!addr.IsRoutable())
290 LogPrintf(
"AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
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);
298 info.
nPort = addr.GetPort();
314 mapLocalHost.erase(addr);
321 const auto it = mapLocalHost.find(addr);
322 if (it == mapLocalHost.end())
return false;
332 return mapLocalHost.count(addr) > 0;
338 for (
CNode* pnode : m_nodes) {
339 if (static_cast<CNetAddr>(pnode->addr) ==
ip) {
349 for (
CNode* pnode : m_nodes) {
350 if (pnode->m_addr_name == addrName) {
360 for (
CNode* pnode : m_nodes) {
361 if (static_cast<CService>(pnode->addr) == addr) {
376 for (
const CNode* pnode : m_nodes) {
377 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() ==
nonce)
387 struct sockaddr_storage sockaddr_bind;
388 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
389 if (!sock.
GetSockName((
struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
390 addr_bind.
SetSockAddr((
const struct sockaddr*)&sockaddr_bind, sockaddr_bind_len);
402 if (pszDest ==
nullptr) {
410 LogPrintf(
"Failed to open new connection, already connected\n");
418 Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.
nTime));
421 const uint16_t default_port{pszDest !=
nullptr ?
GetDefaultPort(pszDest) :
425 std::vector<CAddress> connect_to{};
428 if (!resolved.empty()) {
432 for (
const auto& r : resolved) {
447 connect_to.push_back(addrConnect);
451 connect_to.push_back(addrConnect);
455 connect_to.push_back(addrConnect);
459 std::unique_ptr<Sock> sock;
463 std::unique_ptr<i2p::sam::Session> i2p_transient_session;
465 for (
auto& target_addr: connect_to) {
466 if (target_addr.IsValid()) {
467 const bool use_proxy{
GetProxy(target_addr.GetNetwork(), proxy)};
468 bool proxyConnectionFailed =
false;
470 if (target_addr.IsI2P() && use_proxy) {
472 bool connected{
false};
475 connected =
m_i2p_sam_session->Connect(target_addr, conn, proxyConnectionFailed);
479 if (m_unused_i2p_sessions.empty()) {
480 i2p_transient_session =
481 std::make_unique<i2p::sam::Session>(proxy, &
interruptNet);
483 i2p_transient_session.swap(m_unused_i2p_sessions.front());
484 m_unused_i2p_sessions.pop();
487 connected = i2p_transient_session->Connect(target_addr, conn, proxyConnectionFailed);
491 m_unused_i2p_sessions.emplace(i2p_transient_session.release());
497 sock = std::move(conn.
sock);
500 }
else if (use_proxy) {
502 sock =
ConnectThroughProxy(proxy, target_addr.ToStringAddr(), target_addr.GetPort(), proxyConnectionFailed);
507 if (!proxyConnectionFailed) {
514 uint16_t port{default_port};
516 bool proxyConnectionFailed;
540 pszDest ? pszDest :
"",
545 .i2p_sam_session = std::move(i2p_transient_session),
575 m_i2p_sam_session.reset();
579 for (
const auto& subnet : ranges) {
580 if (subnet.m_subnet.Match(addr)) {
603 if (
Assume(!m_addr_local.IsValid())) {
604 m_addr_local = addrLocalIn;
619 #define X(name) stats.name = name 642 X(mapSendBytesPerMsgType);
647 X(mapRecvBytesPerMsgType);
669 const auto time = GetTime<std::chrono::microseconds>();
671 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
672 nRecvBytes += msg_bytes.
size();
673 while (msg_bytes.
size() > 0) {
682 bool reject_message{
false};
684 if (reject_message) {
693 auto i = mapRecvBytesPerMsgType.find(
msg.m_type);
694 if (i == mapRecvBytesPerMsgType.end()) {
697 assert(i != mapRecvBytesPerMsgType.end());
698 i->second +=
msg.m_raw_message_size;
717 return strprintf(
"disconnecting peer=%d%s",
739 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
741 memcpy(&hdrbuf[nHdrPos], msg_bytes.
data(), nCopy);
752 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 {
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 {
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();
918 const 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;
975 const V2MessageMap V2_MESSAGE_MAP;
977 std::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());
1001 : m_cipher{key, ent32}, m_initiating{initiating}, m_nodeid{nodeid},
1002 m_v1_fallback{nodeid},
1003 m_recv_state{initiating ?
RecvState::KEY : RecvState::KEY_MAYBE_V1},
1004 m_send_garbage{std::move(garbage)},
1005 m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
1007 Assume(m_send_garbage.size() <= MAX_GARBAGE_LEN);
1011 StartSendingHandshake();
1023 switch (m_recv_state) {
1024 case RecvState::KEY_MAYBE_V1:
1028 Assume(recv_state == RecvState::GARB_GARBTERM);
1030 case RecvState::GARB_GARBTERM:
1034 Assume(recv_state == RecvState::APP);
1036 case RecvState::APP:
1037 Assume(recv_state == RecvState::APP_READY);
1039 case RecvState::APP_READY:
1040 Assume(recv_state == RecvState::APP);
1047 m_recv_state = recv_state;
1054 switch (m_send_state) {
1055 case SendState::MAYBE_V1:
1056 Assume(send_state == SendState::V1 || send_state == SendState::AWAITING_KEY);
1058 case SendState::AWAITING_KEY:
1059 Assume(send_state == SendState::READY);
1061 case SendState::READY:
1067 m_send_state = send_state;
1088 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};
1089 std::copy(std::begin(
Params().MessageStart()), std::end(
Params().MessageStart()), v1_prefix.begin());
1090 Assume(m_recv_buffer.size() <= v1_prefix.size());
1091 if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), v1_prefix.begin())) {
1098 }
else if (m_recv_buffer.size() == v1_prefix.size()) {
1105 Assume(feedback.empty());
1130 static constexpr std::array<uint8_t, 12> MATCH = {
'v',
'e',
'r',
's',
'i',
'o',
'n', 0, 0, 0, 0, 0};
1131 static constexpr
size_t OFFSET = std::tuple_size_v<MessageStartChars>;
1132 if (!
m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
1133 if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
1151 m_recv_buffer.clear();
1185 m_recv_aad = std::move(m_recv_buffer);
1187 m_recv_buffer.clear();
1213 static constexpr
size_t MAX_CONTENTS_LEN =
1220 if (m_recv_len > MAX_CONTENTS_LEN) {
1228 m_recv_decode_buffer.resize(m_recv_len);
1247 switch (m_recv_state) {
1276 switch (m_recv_state) {
1326 static constexpr
size_t MAX_RESERVE_AHEAD = 256 * 1024;
1329 if (m_recv_state == RecvState::V1)
return m_v1_fallback.ReceivedBytes(msg_bytes);
1335 while (!msg_bytes.empty()) {
1337 size_t max_read = GetMaxBytesToProcess();
1340 if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
1341 switch (m_recv_state) {
1342 case RecvState::KEY_MAYBE_V1:
1344 case RecvState::GARB_GARBTERM:
1350 case RecvState::APP: {
1356 size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
1357 m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
1360 case RecvState::APP_READY:
1362 Assume(m_recv_buffer.empty());
1372 max_read = std::min(msg_bytes.size(), max_read);
1374 m_recv_buffer.insert(m_recv_buffer.end(),
UCharCast(msg_bytes.data()),
UCharCast(msg_bytes.data() + max_read));
1375 msg_bytes = msg_bytes.subspan(max_read);
1378 switch (m_recv_state) {
1379 case RecvState::KEY_MAYBE_V1:
1380 ProcessReceivedMaybeV1Bytes();
1381 if (m_recv_state == RecvState::V1)
return true;
1385 if (!ProcessReceivedKeyBytes())
return false;
1388 case RecvState::GARB_GARBTERM:
1389 if (!ProcessReceivedGarbageBytes())
return false;
1393 case RecvState::APP:
1394 if (!ProcessReceivedPacketBytes())
return false;
1397 case RecvState::APP_READY:
1414 if (contents.size() == 0)
return std::nullopt;
1415 uint8_t first_byte = contents[0];
1416 contents = contents.subspan(1);
1418 if (first_byte != 0) {
1420 if (first_byte < std::size(V2_MESSAGE_IDS)) {
1422 return V2_MESSAGE_IDS[first_byte];
1425 return std::nullopt;
1430 return std::nullopt;
1433 size_t msg_type_len{0};
1436 if (contents[msg_type_len] <
' ' || contents[msg_type_len] > 0x7F) {
1441 std::string
ret{
reinterpret_cast<const char*
>(contents.data()), msg_type_len};
1444 if (contents[msg_type_len] != 0)
return {};
1456 if (m_recv_state == RecvState::V1)
return m_v1_fallback.GetReceivedMessage(time, reject_message);
1458 Assume(m_recv_state == RecvState::APP_READY);
1460 auto msg_type = GetMessageType(contents);
1465 reject_message =
false;
1466 msg.m_type = std::move(*msg_type);
1468 msg.m_message_size = contents.size();
1469 msg.m_recv.resize(contents.size());
1470 std::copy(contents.begin(), contents.end(),
UCharCast(
msg.m_recv.data()));
1472 LogDebug(
BCLog::NET,
"V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(), m_nodeid);
1473 reject_message =
true;
1476 SetReceiveState(RecvState::APP);
1485 if (m_send_state == SendState::V1)
return m_v1_fallback.SetMessageToSend(
msg);
1489 if (!(m_send_state == SendState::READY && m_send_buffer.empty()))
return false;
1491 std::vector<uint8_t> contents;
1492 auto short_message_id = V2_MESSAGE_MAP(
msg.m_type);
1493 if (short_message_id) {
1494 contents.resize(1 +
msg.data.size());
1495 contents[0] = *short_message_id;
1496 std::copy(
msg.data.begin(),
msg.data.end(), contents.begin() + 1);
1501 std::copy(
msg.m_type.begin(),
msg.m_type.end(), contents.data() + 1);
1507 m_send_type =
msg.m_type;
1517 if (m_send_state == SendState::V1)
return m_v1_fallback.GetBytesToSend(have_next_message);
1519 if (m_send_state == SendState::MAYBE_V1)
Assume(m_send_buffer.empty());
1520 Assume(m_send_pos <= m_send_buffer.size());
1525 have_next_message && m_send_state == SendState::READY,
1534 if (m_send_state == SendState::V1)
return m_v1_fallback.MarkBytesSent(bytes_sent);
1536 if (m_send_state == SendState::AWAITING_KEY && m_send_pos == 0 && bytes_sent > 0) {
1540 m_send_pos += bytes_sent;
1541 Assume(m_send_pos <= m_send_buffer.size());
1543 m_sent_v1_header_worth =
true;
1546 if (m_send_pos == m_send_buffer.size()) {
1563 if (!m_recv_buffer.empty())
return false;
1566 return m_sent_v1_header_worth;
1601 auto it =
node.vSendMsg.begin();
1602 size_t nSentSize = 0;
1603 bool data_left{
false};
1604 std::optional<bool> expected_more;
1607 if (it !=
node.vSendMsg.end()) {
1611 size_t memusage = it->GetMemoryUsage();
1612 if (
node.m_transport->SetMessageToSend(*it)) {
1618 const auto& [
data, more, msg_type] =
node.m_transport->GetBytesToSend(it !=
node.vSendMsg.end());
1622 if (expected_more.has_value())
Assume(!
data.empty() == *expected_more);
1623 expected_more = more;
1624 data_left = !
data.empty();
1626 if (!
data.empty()) {
1640 nBytes =
node.m_sock->Send(reinterpret_cast<const char*>(
data.data()),
data.size(),
flags);
1643 node.m_last_send = GetTime<std::chrono::seconds>();
1644 node.nSendBytes += nBytes;
1646 node.m_transport->MarkBytesSent(nBytes);
1648 if (!msg_type.empty()) {
1649 node.AccountForSentBytes(msg_type, nBytes);
1651 nSentSize += nBytes;
1652 if ((
size_t)nBytes !=
data.size()) {
1662 node.CloseSocketDisconnect();
1671 if (it ==
node.vSendMsg.end()) {
1674 node.vSendMsg.erase(
node.vSendMsg.begin(), it);
1675 return {nSentSize, data_left};
1688 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1693 if (
node->fDisconnect)
1697 .m_connected =
node->m_connected,
1698 .m_min_ping_time =
node->m_min_ping_time,
1699 .m_last_block_time =
node->m_last_block_time,
1700 .m_last_tx_time =
node->m_last_tx_time,
1701 .fRelevantServices =
node->m_has_all_wanted_services,
1702 .m_relay_txs =
node->m_relays_txs.load(),
1703 .fBloomFilter =
node->m_bloom_filter_loaded.load(),
1704 .nKeyedNetGroup =
node->nKeyedNetGroup,
1705 .prefer_evict =
node->m_prefer_evict,
1706 .m_is_local =
node->addr.IsLocal(),
1707 .m_network =
node->ConnectedThroughNetwork(),
1709 .m_conn_type =
node->m_conn_type,
1711 vEvictionCandidates.push_back(candidate);
1714 const std::optional<NodeId> node_id_to_evict =
SelectNodeToEvict(std::move(vEvictionCandidates));
1715 if (!node_id_to_evict) {
1719 for (
CNode* pnode : m_nodes) {
1720 if (pnode->GetId() == *node_id_to_evict) {
1721 LogDebug(
BCLog::NET,
"selected %s connection for eviction, %s", pnode->ConnectionTypeAsString(), pnode->DisconnectMsg(
fLogIPs));
1724 pnode->m_addr_name.c_str(),
1725 pnode->ConnectionTypeAsString().c_str(),
1726 pnode->ConnectedThroughNetwork(),
1727 Ticks<std::chrono::seconds>(pnode->m_connected));
1728 pnode->fDisconnect =
true;
1736 struct sockaddr_storage sockaddr;
1737 socklen_t len =
sizeof(sockaddr);
1738 auto sock = hListenSocket.
sock->Accept((
struct sockaddr*)&sockaddr, &len);
1749 if (!addr.
SetSockAddr((
const struct sockaddr*)&sockaddr, len)) {
1774 for (
const CNode* pnode : m_nodes) {
1775 if (pnode->IsInboundConn()) nInbound++;
1784 if (!sock->IsSelectable()) {
1792 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
1793 LogDebug(
BCLog::NET,
"connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
1817 LogDebug(
BCLog::NET,
"failed to find an eviction candidate - connection dropped (full)\n");
1842 .prefer_evict = discouraged,
1847 m_msgproc->InitializeNode(*pnode, local_services);
1850 m_nodes.push_back(pnode);
1867 std::optional<int> max_connections;
1868 switch (conn_type) {
1888 return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](
CNode*
node) {
return node->m_conn_type == conn_type; }););
1891 if (max_connections != std::nullopt && existing_connections >= max_connections)
return false;
1895 if (!grant)
return false;
1908 decltype(m_reconnections) reconnections_to_add;
1915 for (
CNode* pnode : m_nodes) {
1916 if (!pnode->fDisconnect) {
1918 pnode->fDisconnect =
true;
1924 std::vector<CNode*> nodes_copy = m_nodes;
1925 for (
CNode* pnode : nodes_copy)
1927 if (pnode->fDisconnect)
1930 m_nodes.erase(
remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());
1935 if (pnode->m_transport->ShouldReconnectV1()) {
1936 reconnections_to_add.push_back({
1937 .addr_connect = pnode->addr,
1938 .grant = std::move(pnode->grantOutbound),
1939 .destination = pnode->m_dest,
1940 .conn_type = pnode->m_conn_type,
1941 .use_v2transport =
false});
1942 LogDebug(
BCLog::NET,
"retrying with v1 transport protocol for peer=%d\n", pnode->GetId());
1946 pnode->grantOutbound.Release();
1949 pnode->CloseSocketDisconnect();
1952 if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];
1963 for (
CNode* pnode : nodes_disconnected_copy)
1966 if (pnode->GetRefCount() <= 0) {
1975 m_reconnections.splice(m_reconnections.end(), std::move(reconnections_to_add));
1984 nodes_size = m_nodes.size();
2003 const auto now{GetTime<std::chrono::seconds>()};
2004 const auto last_send{
node.m_last_send.load()};
2005 const auto last_recv{
node.m_last_recv.load()};
2009 bool has_received{last_recv.count() != 0};
2010 bool has_sent{last_send.count() != 0};
2012 if (!has_received || !has_sent) {
2013 std::string has_never;
2014 if (!has_received) has_never +=
", never received from peer";
2015 if (!has_sent) has_never +=
", never sent to peer";
2017 "socket no message in first %i seconds%s, %s\n",
2027 "socket sending timeout: %is, %s\n",
count_seconds(now - last_send),
2035 "socket receive timeout: %is, %s\n",
count_seconds(now - last_recv),
2041 if (!
node.fSuccessfullyConnected) {
2058 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
2061 for (
CNode* pnode : nodes) {
2062 bool select_recv = !pnode->fPauseRecv;
2065 LOCK(pnode->cs_vSend);
2069 const auto& [to_send, more, _msg_type] = pnode->m_transport->GetBytesToSend(!pnode->vSendMsg.empty());
2070 select_send = !to_send.empty() || more;
2072 if (!select_recv && !select_send)
continue;
2074 LOCK(pnode->m_sock_mutex);
2075 if (pnode->m_sock) {
2077 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
2081 return events_per_sock;
2100 if (events_per_sock.empty() || !events_per_sock.begin()->first->WaitMany(timeout, events_per_sock)) {
2117 for (
CNode* pnode : nodes) {
2124 bool recvSet =
false;
2125 bool sendSet =
false;
2126 bool errorSet =
false;
2128 LOCK(pnode->m_sock_mutex);
2129 if (!pnode->m_sock) {
2132 const auto it = events_per_sock.find(pnode->m_sock);
2133 if (it != events_per_sock.end()) {
2136 errorSet = it->second.occurred &
Sock::ERR;
2153 if (data_left) recvSet =
false;
2157 if (recvSet || errorSet)
2160 uint8_t pchBuf[0x10000];
2163 LOCK(pnode->m_sock_mutex);
2164 if (!pnode->m_sock) {
2167 nBytes = pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
2171 bool notify =
false;
2172 if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
2174 "receiving message bytes failed, %s\n",
2177 pnode->CloseSocketDisconnect();
2181 pnode->MarkReceivedMsgsForProcessing();
2185 else if (nBytes == 0)
2188 if (!pnode->fDisconnect) {
2191 pnode->CloseSocketDisconnect();
2193 else if (nBytes < 0)
2199 if (!pnode->fDisconnect) {
2202 pnode->CloseSocketDisconnect();
2217 const auto it = events_per_sock.find(listen_socket.sock);
2218 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
2240 fMsgProcWake =
true;
2247 int outbound_connection_count = 0;
2251 constexpr std::chrono::seconds SEEDNODE_TIMEOUT = 30
s;
2252 LogPrintf(
"-seednode enabled. Trying the provided seeds for %d seconds before defaulting to the dnsseeds.\n", SEEDNODE_TIMEOUT.count());
2260 LogPrintf(
"Couldn't connect to enough peers via seed nodes. Handing fetch logic to the DNS seeds.\n");
2266 LogPrintf(
"P2P peers available. Finished fetching data from seed nodes.\n");
2274 std::shuffle(seeds.begin(), seeds.end(), rng);
2275 int seeds_right_now = 0;
2279 seeds_right_now = seeds.size();
2284 seeds_right_now = seeds.size();
2304 for (
const std::string& seed : seeds) {
2305 if (seeds_right_now == 0) {
2309 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
2310 std::chrono::seconds to_wait = seeds_wait_time;
2311 while (to_wait.count() > 0) {
2321 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2322 LogPrintf(
"P2P peers available. Finished DNS seeding.\n");
2324 LogPrintf(
"P2P peers available. Skipped DNS seeding.\n");
2336 LogPrintf(
"Waiting for network to be reactivated before querying DNS seeds.\n");
2342 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
2348 std::vector<CAddress> vAdd;
2350 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
2359 unsigned int nMaxIPs = 32;
2360 const auto addresses{
LookupHost(host, nMaxIPs,
true)};
2361 if (!addresses.empty()) {
2365 vAdd.push_back(addr);
2378 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2380 LogPrintf(
"Skipping DNS seeds. Enough peers have been found\n");
2386 const auto start{SteadyClock::now()};
2391 addrman.
Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
2397 std::string strDest;
2400 if (m_addr_fetches.empty())
2402 strDest = m_addr_fetches.front();
2403 m_addr_fetches.pop_front();
2423 LogDebug(
BCLog::NET,
"setting try another outbound peer=%s\n", flag ?
"true" :
"false");
2438 for (
const CNode* pnode : m_nodes) {
2439 if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
2453 int full_outbound_peers = 0;
2456 for (
const CNode* pnode : m_nodes) {
2457 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
2458 ++full_outbound_peers;
2467 int block_relay_peers = 0;
2470 for (
const CNode* pnode : m_nodes) {
2471 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
2472 ++block_relay_peers;
2481 std::unordered_set<Network> networks{};
2482 for (
int n = 0; n <
NET_MAX; n++) {
2486 networks.insert(net);
2495 return m_network_conn_counts[net] > 1;
2504 for (
const auto net : nets) {
2520 if (!connect.empty())
2525 for (int64_t nLoop = 0;; nLoop++)
2527 for (
const std::string& strAddr : connect)
2531 for (
int i = 0; i < 10 && i < nLoop; i++)
2544 auto start = GetTime<std::chrono::microseconds>();
2552 const bool use_seednodes{!
gArgs.
GetArgs(
"-seednode").empty()};
2556 constexpr std::chrono::seconds ADD_NEXT_SEEDNODE = 10
s;
2558 if (!add_fixed_seeds) {
2559 LogPrintf(
"Fixed seeds are disabled\n");
2564 if (add_addr_fetch) {
2565 add_addr_fetch =
false;
2570 LogInfo(
"Empty addrman, adding seednode (%s) to addrfetch\n", seed);
2572 LogInfo(
"Couldn't connect to peers from addrman after %d seconds. Adding seednode (%s) to addrfetch\n", ADD_NEXT_SEEDNODE.count(), seed);
2588 if (add_fixed_seeds && !fixed_seed_networks.empty()) {
2593 bool add_fixed_seeds_now =
false;
2595 if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
2596 add_fixed_seeds_now =
true;
2597 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
2601 else if (!dnsseed && !use_seednodes) {
2603 if (m_added_node_params.empty()) {
2604 add_fixed_seeds_now =
true;
2605 LogPrintf(
"Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
2609 if (add_fixed_seeds_now) {
2617 seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
2618 [&fixed_seed_networks](
const CAddress& addr) {
return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
2623 add_fixed_seeds =
false;
2624 LogPrintf(
"Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
2634 int nOutboundFullRelay = 0;
2635 int nOutboundBlockRelay = 0;
2636 int outbound_privacy_network_peers = 0;
2637 std::set<std::vector<unsigned char>> outbound_ipv46_peer_netgroups;
2641 for (
const CNode* pnode : m_nodes) {
2642 if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
2643 if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
2646 switch (pnode->m_conn_type) {
2659 const CAddress address{pnode->addr};
2660 if (address.IsTor() || address.IsI2P() || address.IsCJDNS()) {
2668 ++outbound_privacy_network_peers;
2679 add_addr_fetch =
true;
2684 auto now = GetTime<std::chrono::microseconds>();
2685 bool anchor =
false;
2686 bool fFeeler =
false;
2687 std::optional<Network> preferred_net;
2733 }
else if (now > next_feeler) {
2739 now > next_extra_network_peer &&
2790 std::tie(addr, addr_last_try) =
addrman.
Select(
true, reachable_nets);
2799 std::tie(addr, addr_last_try) =
addrman.
Select(
true, reachable_nets);
2806 std::tie(addr, addr_last_try) = preferred_net.has_value()
2826 if (current_time - addr_last_try < 10min && nTries < 30) {
2849 preferred_net.has_value() ?
"network-specific " :
"",
2874 const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(
m_max_automatic_connections - 1, 2)};
2884 std::vector<CAddress>
ret;
2886 for (
const CNode* pnode : m_nodes) {
2887 if (pnode->IsBlockOnlyConn()) {
2888 ret.push_back(pnode->addr);
2897 std::vector<AddedNodeInfo>
ret;
2899 std::list<AddedNodeParams> lAddresses(0);
2902 ret.reserve(m_added_node_params.size());
2903 std::copy(m_added_node_params.cbegin(), m_added_node_params.cend(), std::back_inserter(lAddresses));
2908 std::map<CService, bool> mapConnected;
2909 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2912 for (
const CNode* pnode : m_nodes) {
2913 if (pnode->addr.IsValid()) {
2914 mapConnected[pnode->addr] = pnode->IsInboundConn();
2916 std::string addrName{pnode->m_addr_name};
2917 if (!addrName.empty()) {
2918 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(),
static_cast<const CService&
>(pnode->addr));
2923 for (
const auto& addr : lAddresses) {
2926 if (service.IsValid()) {
2928 auto it = mapConnected.find(service);
2929 if (it != mapConnected.end()) {
2930 if (!include_connected) {
2933 addedNode.resolvedAddress = service;
2934 addedNode.fConnected =
true;
2935 addedNode.fInbound = it->second;
2939 auto it = mapConnectedByName.find(addr.m_added_node);
2940 if (it != mapConnectedByName.end()) {
2941 if (!include_connected) {
2944 addedNode.resolvedAddress = it->second.second;
2945 addedNode.fConnected =
true;
2946 addedNode.fInbound = it->second.first;
2949 ret.emplace_back(std::move(addedNode));
3000 bool banned_or_discouraged =
m_banman && (
m_banman->IsDiscouraged(addrConnect) ||
m_banman->IsBanned(addrConnect));
3004 }
else if (
FindNode(std::string(pszDest)))
3016 m_nodes.push_back(pnode);
3038 bool fMoreWork =
false;
3046 for (
CNode* pnode : snap.Nodes()) {
3047 if (pnode->fDisconnect)
3052 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
3067 fMsgProcWake =
false;
3073 static constexpr
auto err_wait_begin = 1
s;
3074 static constexpr
auto err_wait_cap = 5min;
3075 auto err_wait = err_wait_begin;
3077 bool advertising_listen_addr =
false;
3080 auto SleepOnFailure = [&]() {
3082 if (err_wait < err_wait_cap) {
3090 if (advertising_listen_addr && conn.
me.
IsValid()) {
3092 advertising_listen_addr =
false;
3098 if (!advertising_listen_addr) {
3100 advertising_listen_addr =
true;
3110 err_wait = err_wait_begin;
3119 struct sockaddr_storage sockaddr;
3120 socklen_t len =
sizeof(sockaddr);
3121 if (!addrBind.
GetSockAddr((
struct sockaddr*)&sockaddr, &len))
3152 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
3153 if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (
const char*)&nProtLevel,
sizeof(
int)) ==
SOCKET_ERROR) {
3160 if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) ==
SOCKET_ERROR) {
3163 strError =
strprintf(
_(
"Unable to bind to %s on this computer. %s is probably already running."), addrBind.
ToStringAddrPort(), CLIENT_NAME);
3190 LogPrintf(
"%s: %s\n", __func__, addr.ToStringAddr());
3196 LogPrintf(
"%s: %s\n", __func__, active);
3211 : addrman(addrman_in)
3212 , m_netgroupman{netgroupman}
3217 SetTryNewOutboundPeer(
false);
3219 Options connOptions;
3221 SetNetworkActive(network_active);
3226 return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
3261 for (
const auto& addrBind : options.
vBinds) {
3266 for (
const auto& addrBind : options.
vWhiteBinds) {
3271 for (
const auto& addr_bind : options.
onion_binds) {
3283 struct in_addr inaddr_any;
3284 inaddr_any.s_addr = htonl(INADDR_ANY);
3301 _(
"Failed to listen on any port. Use -listen=0 if you want this."),
3314 std::vector<std::string> seed_nodes = connOptions.
vSeedNodes;
3315 if (!seed_nodes.empty()) {
3325 LogPrintf(
"%i block-relay-only anchors will be tried for connections.\n",
m_anchors.size());
3352 fMsgProcWake =
false;
3369 _(
"Cannot provide specific connections and have addrman find outgoing connections at the same time."),
3377 [
this, connect = connOptions.
m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });
3473 std::vector<CNode*> nodes;
3475 for (
CNode* pnode : nodes) {
3477 pnode->CloseSocketDisconnect();
3503 std::vector<CAddress>
CConnman::GetAddresses(
size_t max_addresses,
size_t max_pct, std::optional<Network> network,
const bool filtered)
const 3505 std::vector<CAddress> addresses =
addrman.
GetAddr(max_addresses, max_pct, network, filtered);
3507 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3519 .Write(local_socket_bytes)
3524 const auto current_time = GetTime<std::chrono::microseconds>();
3562 const bool resolved_is_valid{resolved.
IsValid()};
3565 for (
const auto& it : m_added_node_params) {
3569 m_added_node_params.push_back(add);
3576 for (
auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
3577 if (strNode == it->m_added_node) {
3578 m_added_node_params.erase(it);
3591 return (m_added_node_params.size() < 24
3592 && std::any_of(m_added_node_params.cbegin(), m_added_node_params.cend(),
3593 [&](
const auto& p) {
return p.m_added_node == addr_str || p.m_added_node == addr_port_str; }));
3600 return m_nodes.size();
3603 for (
const auto& pnode : m_nodes) {
3616 return mapLocalHost;
3628 vstats.reserve(m_nodes.size());
3629 for (
CNode* pnode : m_nodes) {
3630 vstats.emplace_back();
3631 pnode->CopyStats(vstats.back());
3632 vstats.back().m_mapped_as =
GetMappedAS(pnode->addr);
3641 pnode->fDisconnect =
true;
3649 bool disconnected =
false;
3651 for (
CNode* pnode : m_nodes) {
3652 if (subnet.
Match(pnode->addr)) {
3654 pnode->fDisconnect =
true;
3655 disconnected =
true;
3658 return disconnected;
3669 for(
CNode* pnode : m_nodes) {
3670 if (
id == pnode->GetId()) {
3672 pnode->fDisconnect =
true;
3689 nTotalBytesSent += bytes;
3691 const auto now = GetTime<std::chrono::seconds>();
3695 nMaxOutboundCycleStartTime = now;
3696 nMaxOutboundTotalBytesSentInCycle = 0;
3699 nMaxOutboundTotalBytesSentInCycle += bytes;
3728 if (nMaxOutboundCycleStartTime.count() == 0)
3732 const auto now = GetTime<std::chrono::seconds>();
3733 return (cycleEndTime < now) ? 0
s : cycleEndTime - now;
3743 if (historicalBlockServingLimit)
3776 return nTotalBytesSent;
3786 if (use_v2transport) {
3787 return std::make_unique<V2Transport>(id, !inbound);
3789 return std::make_unique<V1Transport>(id);
3794 std::shared_ptr<Sock> sock,
3796 uint64_t nKeyedNetGroupIn,
3797 uint64_t nLocalHostNonceIn,
3799 const std::string& addrNameIn,
3804 m_permission_flags{node_opts.permission_flags},
3806 m_connected{GetTime<std::chrono::seconds>()},
3808 addrBind{addrBindIn},
3809 m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
3811 m_inbound_onion{inbound_onion},
3812 m_prefer_evict{node_opts.prefer_evict},
3813 nKeyedNetGroup{nKeyedNetGroupIn},
3814 m_conn_type{conn_type_in},
3816 nLocalHostNonce{nLocalHostNonceIn},
3817 m_recv_flood_size{node_opts.recv_flood_size},
3818 m_i2p_sam_session{std::move(node_opts.i2p_sam_session)}
3823 mapRecvBytesPerMsgType[
msg] = 0;
3838 size_t nSizeAdded = 0;
3842 nSizeAdded +=
msg.GetMemoryUsage();
3846 m_msg_process_queue.splice(m_msg_process_queue.end(),
vRecvMsg);
3847 m_msg_process_queue_size += nSizeAdded;
3854 if (m_msg_process_queue.empty())
return std::nullopt;
3856 std::list<CNetMessage> msgs;
3858 msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
3859 m_msg_process_queue_size -= msgs.front().GetMemoryUsage();
3862 return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
3873 size_t nMessageSize =
msg.data.size();
3888 size_t nBytesSent = 0;
3893 const auto& [to_send, more, _msg_type] =
3895 const bool queue_was_empty{to_send.empty() && pnode->vSendMsg.empty()};
3898 pnode->m_send_memusage +=
msg.GetMemoryUsage();
3901 pnode->vSendMsg.push_back(std::move(
msg));
3910 if (queue_was_empty && more) {
3919 CNode* found =
nullptr;
3921 for (
auto&& pnode : m_nodes) {
3922 if(pnode->
GetId() == id) {
3948 decltype(m_reconnections) todo;
3951 if (m_reconnections.empty())
break;
3952 todo.splice(todo.end(), m_reconnections, m_reconnections.begin());
3955 auto& item = *todo.begin();
3962 std::move(item.grant),
3963 item.destination.empty() ? nullptr : item.destination.c_str(),
3965 item.use_v2transport);
3973 std::vector<CNetAddr> clearnet_addrs;
3974 clearnet_addrs.reserve(v4_addrs.size() + v6_addrs.size());
3975 std::transform(v4_addrs.begin(), v4_addrs.end(), std::back_inserter(clearnet_addrs),
3977 std::transform(v6_addrs.begin(), v6_addrs.end(), std::back_inserter(clearnet_addrs),
3984 const std::string& msg_type,
3992 auto now = GetTime<std::chrono::microseconds>();
3996 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
4001 fs::path path = base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
4005 f <<
Span{msg_type};
4009 uint32_t size =
data.size();
4014 std::function<void(
const CAddress& addr,
4015 const std::string& msg_type,
const std::vector< std::string > & DNSSeeds() const
Return the list of hostnames to look up for DNS seeds.
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
Wrapper that overrides the GetParams() function of a stream.
bool RemoveAddedNode(const std::string &node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
std::vector< CService > vBinds
std::atomic< bool > flagInterruptMsgProc
std::vector< unsigned char > GetGroup(const CNetAddr &address) const
Get the canonical identifier of the network group for address.
Span< const std::byte > GetSendGarbageTerminator() const noexcept
Get the Garbage Terminator to send.
std::vector< CAddress > m_addrs_response_cache
static const int MAX_BLOCK_RELAY_ONLY_CONNECTIONS
Maximum number of block-relay-only outgoing connections.
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Mutex m_send_mutex
Lock for sending state.
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
size_t Size(std::optional< Network > net=std::nullopt, std::optional< bool > in_new=std::nullopt) const
Return size information about addrman.
static constexpr auto FEELER_SLEEP_WINDOW
const uint256 & GetMessageHash() const EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
constexpr const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
std::atomic_bool fPauseSend
AddrFetch connections are short lived connections used to solicit addresses from peers.
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH
Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable).
BIP324Cipher m_cipher
Cipher state.
bool m_i2p_accept_incoming
void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
std::atomic< bool > fNetworkActive
bool ProcessReceivedKeyBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex
Process bytes in m_recv_buffer, while in KEY 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.
static void AddFlag(NetPermissionFlags &flags, NetPermissionFlags f)
ServiceFlags
nServices flags
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.
bool SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
Set CService from a network sockaddr.
bool AddedNodesContain(const CAddress &addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
Info GetInfo() const noexcept override
Retrieve information about this transport.
Inbound connections are those initiated by a peer.
FILE * fopen(const fs::path &p, const char *mode)
A set of addresses that represent the hash of a string or FQDN.
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 ...
Dummy value to indicate the number of NET_* constants.
constexpr C * end() const noexcept
void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
Check connected and listening sockets for IO readiness and process them accordingly.
Unencrypted, plaintext protocol.
NetPermissionFlags permission_flags
bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions)
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...
Feeler connections are short-lived connections made to check that a node is alive.
Mutex m_total_bytes_sent_mutex
void ASMapHealthCheck(const std::vector< CNetAddr > &clearnet_addrs) const
Analyze and log current health of ASMap based buckets.
std::shared_ptr< Sock > sock
std::list< CNode * > m_nodes_disconnected
void ser_writedata64(Stream &s, uint64_t obj)
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.
bool SplitHostPort(std::string_view in, uint16_t &portOut, std::string &hostOut)
Splits socket address string into host string and port value.
bool sleep_for(Clock::duration rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut)
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...
void SetReceiveState(RecvState recv_state) noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Change the receive state.
CService GetLocalAddress(const CNode &peer)
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
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.
std::string LogIP(bool log_ip) const
Helper function to optionally log the IP address.
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
static void ClearFlag(NetPermissionFlags &flags, NetPermissionFlags f)
ClearFlag is only called with f == NetPermissionFlags::Implicit.
bool SetMessageToSend(CSerializedNetMsg &msg) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Set the next message to send.
const std::string NET_MESSAGE_TYPE_OTHER
std::vector< unsigned char > data
static constexpr size_t size()
void ThreadOpenConnections(std::vector< std::string > connect, Span< const std::string > seed_nodes) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
Nothing (this transport is using v1 fallback).
vWhitelistedRangeOutgoing
const ConnectionType m_conn_type
uint64_t GetTotalBytesRecv() const
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::unordered_set< Network > GetReachableEmptyNetworks() const
Return reachable networks for which we have no addresses in addrman and therefore may require loadin...
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
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.
bool GetProxy(enum Network net, Proxy &proxyInfoOut)
static CService GetBindAddress(const Sock &sock)
Get the bind address for a socket as CService.
std::vector< AddedNodeInfo > GetAddedNodeInfo(bool include_connected) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
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.
void ser_writedata32(Stream &s, uint32_t obj)
static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME
The default timeframe for -maxuploadtarget.
constexpr const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
constexpr std::size_t size() const noexcept
bool AlreadyConnectedToAddress(const CAddress &addr)
Determine whether we're already connected to a given address, in order to avoid initiating duplicate ...
static constexpr SerParams V2_NETWORK
RAII-style semaphore lock.
void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
V1Transport(const NodeId node_id) noexcept
CService me
Our I2P address.
bool BindListenPort(const CService &bindAddr, bilingual_str &strError, NetPermissionFlags permissions)
constexpr const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected...
static constexpr uint32_t MAX_GARBAGE_LEN
constexpr const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
bool DumpPeerAddresses(const ArgsManager &args, const AddrMan &addr)
static const unsigned char VERSION[]
void Initialize(const EllSwiftPubKey &their_pubkey, bool initiator, bool self_decrypt=false) noexcept
Initialize when the other side's public key is received.
const NodeId m_nodeid
NodeId (for debug logging).
void Discover()
Look up IP addresses from all interfaces on the machine and add them to the list of local addresses t...
bool ProcessReceivedPacketBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Process bytes in m_recv_buffer, while in VERSION/APP state.
unsigned DecryptLength(Span< const std::byte > input) noexcept
Decrypt the length of a packet.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
bool IsConnectedThroughPrivacyNet() const
Whether this peer connected through a privacy network.
void DisconnectNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex
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={})
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 ...
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void SetTryNewOutboundPeer(bool flag)
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...
memcpy(result.begin(), stream.data(), stream.size())
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
bool SetSpecial(const std::string &addr)
Parse a Tor or I2P address and set this object to it.
void RecordBytesSent(uint64_t bytes) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
bool IsPrivacyNet() const
Whether this object is a privacy network.
constexpr const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message...
static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE
bool SeenLocal(const CService &addr)
vote for a local address
constexpr const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
vWhitelistedRangeIncoming
An established connection with another peer.
Network GetNetClass() const
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).
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.
m_max_outbound_block_relay
static std::optional< CService > GetLocal(const CNode &peer)
consteval auto _(util::TranslatedLiteral str)
V1Transport m_v1_fallback
Encapsulate a V1Transport to fall back to.
static std::vector< CAddress > ConvertSeeds(const std::vector< uint8_t > &vSeedsIn)
Convert the serialized seeds into usable address objects.
These are the default connections that we use to connect with the network.
void GetNodeStats(std::vector< CNodeStats > &vstats) const
Non-refcounted RAII wrapper for FILE*.
bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex)
#define WSAGetLastError()
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
std::list< CNetMessage > vRecvMsg
bool GetTryNewOutboundPeer() const
void DumpAnchors(const fs::path &anchors_db_path, const std::vector< CAddress > &anchors)
Dump the anchor IP address database (anchors.dat)
void NotifyNumConnectionsChanged()
enum Network GetNetwork() const
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 ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions...
std::string ToStringAddrPort() const
SendState
State type that controls the sender side.
std::map< uint64_t, CachedAddrResponse > m_addr_response_caches
Addr responses stored in different caches per (network, local socket) prevent cross-network node iden...
void Init(const Options &connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex
uint64_t GetMaxOutboundTarget() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
constexpr const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
static constexpr Event SEND
If passed to Wait(), then it will wait for readiness to send to the socket.
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
Stochastic address manager.
constexpr const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
void AddSocketPermissionFlags(NetPermissionFlags &flags) const
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
uint16_t GetDefaultPort() const
bool ReceivedMessageComplete() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Returns true if the current message is complete (so GetReceivedMessage can be called).
constexpr unsigned char * begin()
std::string ToStringAddr() const
bool ReceiveMsgBytes(Span< const uint8_t > msg_bytes, bool &complete) EXCLUSIVE_LOCKS_REQUIRED(!cs_vRecv)
Receive bytes from the buffer and deserialize them into messages.
Mutex m_unused_i2p_sessions_mutex
Mutex protecting m_i2p_sam_sessions.
bool DisconnectNode(const std::string &node)
static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
CKey GenerateRandomKey(bool compressed) noexcept
int GetExtraBlockRelayCount() const
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
TransportProtocolType m_transport_type
Transport protocol type.
void RecordBytesRecv(uint64_t bytes)
void fillrand(Span< std::byte > output) noexcept
Fill a byte Span with random bytes.
uint32_t ReadLE32(const B *ptr)
constexpr const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
requires StdChronoDuration< typename Chrono::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).
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
std::string ToString() const
std::chrono::steady_clock Clock
static constexpr auto EXTRA_NETWORK_PEER_INTERVAL
Frequency to attempt extra connections to reachable networks we're not connected to yet...
std::thread threadI2PAcceptIncoming
std::tuple< Span< const uint8_t >, bool, const std::string &> BytesToSend
Return type for GetBytesToSend, consisting of:
bool CompleteInternal() const noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
DataStream m_recv
received message data
bool IsBadPort(uint16_t port)
Determine if a port is "bad" from the perspective of attempting to connect to a node on that port...
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
Span< const std::byte > GetSessionID() const noexcept
Get the Session ID.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::optional< uint256 > session_id
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
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.
static constexpr uint16_t I2P_SAM31_PORT
SAM 3.1 and earlier do not support specifying ports and force the port to 0.
std::chrono::microseconds m_cache_entry_expiration
static bool NodeFullyConnected(const CNode *pnode)
unsigned int nPrevNodeCount
bool UsingASMap() const
Indicates whether ASMap is being used for clearnet bucketing.
std::map< CNetAddr, LocalServiceInfo > getNetLocalAddresses() const
static constexpr unsigned GARBAGE_TERMINATOR_LEN
static const uint64_t RANDOMIZER_ID_NETGROUP
bool InactivityCheck(const CNode &node) const
Return true if the peer is inactive and should be disconnected.
std::condition_variable condMsgProc
std::atomic_bool m_start_extra_block_relay_peers
flag for initiating extra block-relay-only peer connections.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
constexpr ServiceFlags SeedsServiceFlags()
State independent service flags.
constexpr const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
bool IsManualOrFullOutboundConn() const
const EllSwiftPubKey & GetOurPubKey() const noexcept
Retrieve our public key.
Mutex m_added_nodes_mutex
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
constexpr const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
We open manual connections to addresses that users explicitly requested via the addnode RPC or the -a...
std::unique_ptr< Sock > ConnectDirectly(const CService &dest, bool manual_connection)
Create a socket and try to connect to the specified service.
constexpr const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
CNode * ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
const uint64_t nSeed0
SipHasher seeds for deterministic randomness.
bool ShouldReconnectV1() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex
Whether upon disconnections, a reconnect with V1 is warranted.
static std::unique_ptr< Transport > MakeTransport(NodeId id, bool use_v2transport, bool inbound) noexcept
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::thread threadOpenAddedConnections
std::string ConnectionTypeAsString(ConnectionType conn_type)
Convert ConnectionType enum to a string value.
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
void PerformReconnections() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex
Attempt reconnections, if m_reconnections non-empty.
std::vector< CAddress > ReadAnchors(const fs::path &anchors_db_path)
Read the anchor IP address database (anchors.dat)
void StartExtraBlockRelayPeers()
Double ended buffer combining vector and stream-like interfaces.
CNode * FindNode(const CNetAddr &ip)
constexpr const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter...
ServiceFlags GetLocalServices() const
Used to convey which local services we are offering peers during node connection. ...
bool AddLocal(const CService &addr_, int nScore)
void SocketHandlerListening(const Sock::EventsPerSock &events_per_sock)
Accept incoming connections, one from each read-ready listening socket.
TransportProtocolType transport_type
static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE
Number of DNS seeds to query when the number of connections is low.
constexpr const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
A combination of a network address (CNetAddr) and a (TCP) port.
Transport protocol agnostic message container.
std::vector< std::string > vSeedNodes
std::vector< std::string > m_specified_outgoing
void OpenNetworkConnection(const CAddress &addrConnect, bool fCountFailure, CSemaphoreGrant &&grant_outbound, const char *strDest, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex)
void SetSendState(SendState send_state) noexcept EXCLUSIVE_LOCKS_REQUIRED(m_send_mutex)
Change the send state.
std::unique_ptr< CSemaphore > semOutbound
std::thread threadMessageHandler
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as connection attempted to.
An ElligatorSwift-encoded public key.
std::unordered_set< Network > All() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
int GetExtraFullOutboundCount() const
A CService with information about it as peer.
std::vector< CAddress > GetCurrentBlockRelayOnlyConns() const
Return vector of current BLOCK_RELAY peers.
static int GetnScore(const CService &addr)
static constexpr bool DEFAULT_FIXEDSEEDS
void ClearShrink(V &v) noexcept
Clear a vector (or std::deque) and release its allocated memory.
uint32_t GetMappedAS(const CNetAddr &address) const
Get the autonomous system on the BGP path to address.
static bool IsPeerAddrLocalGood(CNode *pnode)
#define LogPrintLevel(category, level,...)
static CService ip(uint32_t i)
constexpr const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks...
Do not call AddLocal() for our special addresses, e.g., for incoming Tor connections, to prevent gossiping them over the network.
int readData(Span< const uint8_t > msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_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 ReceivedBytes(Span< const uint8_t > &msg_bytes) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex
Feed wire bytes to the transport.
(Responder only) either v2 public key or v1 header.
bool InitBinds(const Options &options)
void SetNetworkActive(bool active)
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...
#define WAIT_LOCK(cs, name)
CThreadInterrupt g_socks5_interrupt
Interrupt SOCKS5 reads or writes.
static constexpr bool DEFAULT_DNSSEED
const CChainParams & m_params
Mutex m_recv_mutex
Lock for receive state.
const bool m_initiating
Whether we are the initiator side.
static void CaptureMessageToFile(const CAddress &addr, const std::string &msg_type, Span< const unsigned char > data, bool is_incoming)
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
constexpr const char * BLOCK
The block message transmits a single serialized block.
std::atomic< bool > m_bip152_highbandwidth_to
constexpr const char * GETDATA
The getdata message requests one or more data objects from another node.
const NetPermissionFlags m_permission_flags
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
bool SetMessageToSend(CSerializedNetMsg &msg) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Set the next message to send.
static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
void ProcessReceivedMaybeV1Bytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex
Process bytes in m_recv_buffer, while in KEY_MAYBE_V1 state.
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...
std::atomic_bool fDisconnect
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
void AddAddrFetch(const std::string &strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex)
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...
NetPermissionFlags m_flags
const bool use_v2transport(GetLocalServices() &NODE_P2P_V2)
static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS
Maximum number of block-relay-only anchor connections.
Waiting for the other side's public key.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
RecursiveMutex m_nodes_mutex
const size_t m_recv_flood_size
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
bool Decrypt(Span< const std::byte > input, Span< const std::byte > aad, bool &ignore, Span< std::byte > contents) noexcept
Decrypt a packet.
static constexpr std::chrono::hours ASMAP_HEALTH_CHECK_INTERVAL
Interval for ASMap Health Check.
constexpr int64_t count_seconds(std::chrono::seconds t)
void DeleteNode(CNode *pnode)
static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS
How long to delay before querying DNS seeds.
static constexpr Event ERR
Ignored if passed to Wait(), but could be set in the occurred events if an exceptional condition has ...
std::unique_ptr< i2p::sam::Session > m_i2p_sam_session
I2P SAM session.
constexpr const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool CheckIncomingNonce(uint64_t nonce)
void CloseSocketDisconnect() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex)
constexpr const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex
bool Match(const CNetAddr &addr) const
Info GetInfo() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Retrieve information about this transport.
Mutex m_addr_fetches_mutex
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 StartSendingHandshake() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_send_mutex)
Put our public key + garbage in the send buffer.
std::atomic< std::chrono::seconds > m_last_send
constexpr const char * BLOCKTXN
Contains a BlockTransactions.
std::atomic< NodeId > nLastNodeId
constexpr C * begin() const noexcept
bool GetNameProxy(Proxy &nameProxyOut)
constexpr const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
Garbage and garbage terminator.
std::chrono::seconds GetMaxOutboundTimeLeftInCycle() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
std::vector< CService > onion_binds
static time_point now() noexcept
Return current system time or mocked time, if set.
size_t GetNodeCount(ConnectionDirection) const
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.
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
std::pair< CAddress, NodeSeconds > SelectTriedCollision()
Randomly select an address in the tried table that another address is attempting to evict...
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
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 * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
std::string ToString() const
m_max_automatic_connections
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
const std::array ALL_NET_MESSAGE_TYPES
All known message types (see above).
#define LogDebug(category,...)
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
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...
static const uint64_t SELECT_TIMEOUT_MILLISECONDS
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range) noexcept
Return the time point advanced by a uniform random duration.
std::thread threadOpenConnections
bool AttemptToEvictConnection()
Try to find a connection to evict when the node is full.
uint64_t GetTotalBytesSent() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
V2Transport(NodeId nodeid, bool initiating) noexcept
Construct a V2 transport with securely generated random keys.
uint32_t GetMappedAS(const CNetAddr &addr) const
static std::optional< std::string > GetMessageType(Span< const uint8_t > &contents) noexcept
Given a packet's contents, find the message type (if valid), and strip it from contents.
bool ProcessReceivedGarbageBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Process bytes in m_recv_buffer, while in GARB_GARBTERM state.
constexpr C * data() const noexcept
const CChainParams & Params()
Return the currently selected parameters.
CSemaphoreGrant grantOutbound
constexpr const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
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.
constexpr const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
#define TRACEPOINT(context,...)
GlobalMutex g_maplocalhost_mutex
const MessageStartChars & MessageStart() const
std::atomic< std::chrono::seconds > m_last_recv
bool fAddressesInitialized
T & SpanPopBack(Span< T > &span)
Pop the last element off a span, and return a reference to that element.
std::thread threadDNSAddressSeed
bool MaybePickPreferredNetwork(std::optional< Network > &network)
Search for a "preferred" network, a reachable network to which we currently don't have any OUTBOUND_F...
static constexpr int SEED_OUTBOUND_CONNECTION_THRESHOLD
Minimum number of outbound connections under which we will keep fetching our address seeds...
int GetFullOutboundConnCount() const
bool Start(CScheduler &scheduler, const Options &options) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex
uint256 GetRandHash() noexcept
Generate a random uint256.
Span< const std::byte > MakeByteSpan(V &&v) noexcept
std::vector< ListenSocket > vhListenSocket
std::chrono::seconds GetMaxOutboundTimeframe() const
std::pair< CAddress, NodeSeconds > Select(bool new_only=false, const std::unordered_set< Network > &networks={}) const
Choose an address to connect to.
static const uint64_t RANDOMIZER_ID_ADDRCACHE
bool ReceivedBytes(Span< const uint8_t > &msg_bytes) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Feed wire bytes to the transport.
CService GetAddrLocal() const EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
CNetMessage GetReceivedMessage(std::chrono::microseconds time, bool &reject_message) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Retrieve a completed message from transport.
constexpr bool empty() const noexcept
static constexpr bool DEFAULT_FORCEDNSSEED
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
std::vector< CNetAddr > GetLocalAddresses()
Return all local non-loopback IPv4 and IPv6 network addresses.
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span
Like the Span constructor, but for (const) unsigned char member types only.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
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...
#define AssertLockNotHeld(cs)
std::string m_session_id
BIP324 session id string in hex, if any.
static constexpr auto FEELER_INTERVAL
Run the feeler connection loop once every 2 minutes.
RecvState
State type that defines the current contents of the receive buffer and/or how the next received bytes...
void Encrypt(Span< const std::byte > contents, Span< const std::byte > aad, bool ignore, Span< std::byte > output) noexcept
Encrypt a packet.
std::atomic< int > nVersion
Sock::EventsPerSock GenerateWaitSockets(Span< CNode *const > nodes)
Generate a collection of sockets to check for IO readiness.
bool AddNode(const AddedNodeParams &add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
Nothing (an application packet is available for GetMessage()).
void MarkReceivedMsgsForProcessing() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Move all messages from the received queue to the processing queue.
static constexpr auto EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL
Run the extra block-relay-only connection loop once every 5 minutes.
std::string ConnectionTypeAsString() const
ConnectionType
Different types of connections to a peer.
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
std::string DisconnectMsg(bool log_ip) const
Helper function to log disconnects.
CConnman(uint64_t seed0, uint64_t seed1, AddrMan &addrman, const NetGroupManager &netgroupman, const CChainParams ¶ms, bool network_active=true)
static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL
unsigned char * UCharCast(char *c)
Mutex m_msg_process_queue_mutex
std::atomic< bool > m_bip152_highbandwidth_from
void ThreadI2PAcceptIncoming()
const std::vector< uint8_t > & FixedSeeds() const
RAII helper class that manages a socket and closes it automatically when it goes out of scope...
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE
The maximum allowed size for a serialized block, in bytes (only for buffer size limits) ...
constexpr const char * TX
The tx message transmits a single transaction.
Mutex m_reconnections_mutex
Mutex protecting m_reconnections.
std::pair< size_t, bool > SocketSendData(CNode &node) const EXCLUSIVE_LOCKS_REQUIRED(node.cs_vSend)
(Try to) send data from node's vSendMsg.
CNetMessage GetReceivedMessage(std::chrono::microseconds time, bool &reject_message) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Retrieve a completed message from transport.
RAII helper to atomically create a copy of m_nodes and add a reference to each of the nodes...
std::function< std::unique_ptr< Sock >int, int, int)> CreateSock
Socket factory.
static const int MAX_OUTBOUND_FULL_RELAY_CONNECTIONS
Maximum number of automatic outgoing nodes over which we'll relay everything (blocks, tx, addrs, etc)
BindFlags
Used to pass flags to the Bind() function.
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
An encapsulated private key.
void AcceptConnection(const ListenSocket &hListenSocket)
A Span is an object that can refer to a contiguous sequence of objects.
static bool TryParse(const std::string &str, NetWhitebindPermissions &output, bilingual_str &error)
Different type to mark Mutex at global scope.
std::string GetNetworkName(enum Network net)
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...
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Information about a peer.
static CNetCleanup instance_of_cnetcleanup
Span< const std::byte > GetReceiveGarbageTerminator() const noexcept
Get the expected Garbage Terminator to receive.
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::thread threadSocketHandler
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct, difficult-to-forge characteristics.
Simple class for background tasks that should be run periodically or once "after a while"...
std::atomic< std::chrono::microseconds > m_last_ping_time
Last measured round-trip time.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
bool SetInternal(const std::string &name)
Create an "internal" address that represents a name or FQDN.
void AddWhitelistPermissionFlags(NetPermissionFlags &flags, const CNetAddr &addr, const std::vector< NetWhitelistPermissions > &ranges) const
std::map< CNetAddr, LocalServiceInfo > mapLocalHost GUARDED_BY(g_maplocalhost_mutex)
Network ConnectedThroughNetwork() const
Get network the peer connected through.
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.
sa_family_t GetSAFamily() const
Get the address family.
std::vector< CAddress > m_anchors
Addresses that were saved during the previous clean shutdown.
uint64_t CalculateKeyedNetGroup(const CNetAddr &ad) const
static path u8path(const std::string &utf8_str)
virtual int GetSockName(sockaddr *name, socklen_t *name_len) const
getsockname(2) wrapper.
static constexpr unsigned EXPANSION
std::atomic< std::chrono::microseconds > m_min_ping_time
Lowest measured round-trip time.
const NetGroupManager & m_netgroupman
TRACEPOINT_SEMAPHORE(net, closed_connection)
std::atomic< uint64_t > nTotalBytesRecv
Auxiliary requested/occurred events to wait for in WaitMany().
const std::string m_addr_name
std::atomic_bool fPauseRecv
std::unique_ptr< CSemaphore > semAddnode
std::unique_ptr< Sock > sock
Connected socket.
Span(T *, EndOrSize) -> Span< T >
const MessageStartChars m_magic_bytes
CThreadInterrupt interruptNet
This is signaled when network activity should cease.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
bool ReceivedMessageComplete() const override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Returns true if the current message is complete (so GetReceivedMessage can be called).
static constexpr std::array< std::byte, 0 > VERSION_CONTENTS
Contents of the version packet to send.
CService peer
The peer's I2P address.
bool IsInboundConn() const
bool m_use_addrman_outgoing
std::vector< NetWhitebindPermissions > vWhiteBinds
static constexpr unsigned LENGTH_LEN
uint16_t GetDefaultPort(Network net) const
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
constexpr const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
int readHeader(Span< const uint8_t > msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
bool bind_on_any
True if the user did not specify -bind= or -whitebind= and thus we should bind on 0...
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.
constexpr const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
const char *const ANCHORS_DATABASE_FILENAME
Anchor IP address database file name.
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...
m_max_outbound_full_relay
void Reset() EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
Cache responses to addr requests to minimize privacy leak.
std::vector< unsigned char > GetAddrBytes() const
void RemoveLocal(const CService &addr)
This transport is using v1 fallback.
We use block-relay-only connections to help prevent against partition attacks.
bool IsLocal(const CService &addr)
check whether a given address is potentially local
void CopyStats(CNodeStats &stats) EXCLUSIVE_LOCKS_REQUIRED(!m_subver_mutex
ReachableNets g_reachable_nets
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.
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 TraceThread(std::string_view thread_name, std::function< void()> thread_func)
A wrapper for do-something-once thread functions.
Addresses from these networks are not publicly routable on the global Internet.