6 #if defined(HAVE_CONFIG_H)
45 #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
54 #include <unordered_map>
132 m_addr_fetches.push_back(strDest);
138 for (
const std::string& bind_arg :
gArgs.
GetArgs(
"-bind")) {
139 constexpr uint16_t dummy_port = 0;
141 const std::optional<CService> bind_addr{
Lookup(bind_arg, dummy_port,
false)};
142 if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port)
return bind_addr->GetPort();
147 for (
const std::string& whitebind_arg :
gArgs.
GetArgs(
"-whitebind")) {
164 if (!
fListen)
return std::nullopt;
166 std::optional<CService> addr;
168 int nBestReachability = -1;
171 for (
const auto& [local_addr, local_service_info] : mapLocalHost) {
179 const int nScore{local_service_info.nScore};
180 const int nReachability{local_addr.GetReachabilityFrom(peer.
addr)};
181 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) {
182 addr.emplace(
CService{local_addr, local_service_info.nPort});
183 nBestReachability = nReachability;
192 static std::vector<CAddress>
ConvertSeeds(
const std::vector<uint8_t> &vSeedsIn)
198 const auto one_week{7 * 24h};
199 std::vector<CAddress> vSeedsOut;
209 vSeedsOut.push_back(addr);
226 const auto it = mapLocalHost.find(addr);
227 return (it != mapLocalHost.end()) ? it->second.nScore : 0;
248 if (
node.IsInboundConn()) {
257 addrLocal.SetIP(
node.GetAddrLocal());
260 if (addrLocal.IsRoutable()) {
273 if (!addr.IsRoutable())
282 LogPrintf(
"AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
286 const auto [it, is_newly_added] = mapLocalHost.emplace(addr,
LocalServiceInfo());
288 if (is_newly_added || nScore >= info.
nScore) {
289 info.
nScore = nScore + (is_newly_added ? 0 : 1);
290 info.
nPort = addr.GetPort();
306 mapLocalHost.erase(addr);
313 const auto it = mapLocalHost.find(addr);
314 if (it == mapLocalHost.end())
return false;
324 return mapLocalHost.count(addr) > 0;
330 for (
CNode* pnode : m_nodes) {
331 if (
static_cast<CNetAddr>(pnode->addr) ==
ip) {
341 for (
CNode* pnode : m_nodes) {
342 if (pnode->m_addr_name == addrName) {
352 for (
CNode* pnode : m_nodes) {
353 if (
static_cast<CService>(pnode->addr) == addr) {
368 for (
const CNode* pnode : m_nodes) {
369 if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() ==
nonce)
379 struct sockaddr_storage sockaddr_bind;
380 socklen_t sockaddr_bind_len =
sizeof(sockaddr_bind);
381 if (!sock.
GetSockName((
struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
382 addr_bind.
SetSockAddr((
const struct sockaddr*)&sockaddr_bind);
394 if (pszDest ==
nullptr) {
402 LogPrintf(
"Failed to open new connection, already connected\n");
410 Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.
nTime));
413 const uint16_t default_port{pszDest !=
nullptr ?
GetDefaultPort(pszDest) :
417 std::vector<CAddress> connect_to{};
420 if (!resolved.empty()) {
424 for (
const auto& r : resolved) {
439 connect_to.push_back(addrConnect);
443 connect_to.push_back(addrConnect);
447 connect_to.push_back(addrConnect);
451 std::unique_ptr<Sock> sock;
455 std::unique_ptr<i2p::sam::Session> i2p_transient_session;
457 for (
auto& target_addr: connect_to) {
458 if (target_addr.IsValid()) {
459 const bool use_proxy{
GetProxy(target_addr.GetNetwork(), proxy)};
460 bool proxyConnectionFailed =
false;
462 if (target_addr.IsI2P() && use_proxy) {
464 bool connected{
false};
467 connected =
m_i2p_sam_session->Connect(target_addr, conn, proxyConnectionFailed);
471 if (m_unused_i2p_sessions.empty()) {
472 i2p_transient_session =
473 std::make_unique<i2p::sam::Session>(proxy, &
interruptNet);
475 i2p_transient_session.swap(m_unused_i2p_sessions.front());
476 m_unused_i2p_sessions.pop();
479 connected = i2p_transient_session->Connect(target_addr, conn, proxyConnectionFailed);
483 m_unused_i2p_sessions.emplace(i2p_transient_session.release());
489 sock = std::move(conn.
sock);
492 }
else if (use_proxy) {
494 sock =
ConnectThroughProxy(proxy, target_addr.ToStringAddr(), target_addr.GetPort(), proxyConnectionFailed);
499 if (!proxyConnectionFailed) {
506 uint16_t port{default_port};
508 bool proxyConnectionFailed;
532 pszDest ? pszDest :
"",
537 .i2p_sam_session = std::move(i2p_transient_session),
560 m_i2p_sam_session.reset();
564 for (
const auto& subnet : ranges) {
565 if (subnet.m_subnet.Match(addr)) {
588 if (addrLocal.IsValid()) {
589 LogError(
"Addr local already set for node: %i. Refusing to change from %s to %s\n",
id, addrLocal.ToStringAddrPort(), addrLocalIn.
ToStringAddrPort());
591 addrLocal = addrLocalIn;
606 #define X(name) stats.name = name
630 X(mapSendBytesPerMsgType);
635 X(mapRecvBytesPerMsgType);
657 const auto time = GetTime<std::chrono::microseconds>();
659 m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
660 nRecvBytes += msg_bytes.
size();
661 while (msg_bytes.
size() > 0) {
670 bool reject_message{
false};
672 if (reject_message) {
681 auto i = mapRecvBytesPerMsgType.find(
msg.m_type);
682 if (i == mapRecvBytesPerMsgType.end()) {
685 assert(i != mapRecvBytesPerMsgType.end());
686 i->second +=
msg.m_raw_message_size;
715 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
717 memcpy(&hdrbuf[nHdrPos], msg_bytes.
data(), nCopy);
728 catch (
const std::exception&) {
754 unsigned int nRemaining = hdr.nMessageSize - nDataPos;
755 unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.
size());
757 if (vRecv.size() < nDataPos + nCopy) {
759 vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
762 hasher.Write(msg_bytes.
first(nCopy));
763 memcpy(&vRecv[nDataPos], msg_bytes.
data(), nCopy);
773 if (data_hash.IsNull())
774 hasher.Finalize(data_hash);
782 reject_message =
false;
788 msg.m_type = hdr.GetCommand();
790 msg.m_message_size = hdr.nMessageSize;
800 LogPrint(
BCLog::NET,
"Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
805 reject_message =
true;
806 }
else if (!hdr.IsCommandValid()) {
809 reject_message =
true;
822 if (m_sending_header || m_bytes_sent < m_message_to_send.data.size())
return false;
832 m_header_to_send.clear();
836 m_message_to_send = std::move(
msg);
837 m_sending_header =
true;
846 if (m_sending_header) {
847 return {
Span{m_header_to_send}.
subspan(m_bytes_sent),
850 have_next_message || !m_message_to_send.data.empty(),
851 m_message_to_send.m_type
854 return {
Span{m_message_to_send.
data}.subspan(m_bytes_sent),
858 m_message_to_send.m_type
867 m_bytes_sent += bytes_sent;
868 if (m_sending_header && m_bytes_sent == m_header_to_send.size()) {
870 m_sending_header =
false;
872 }
else if (!m_sending_header && m_bytes_sent == m_message_to_send.data.size()) {
884 return m_message_to_send.GetMemoryUsage();
894 const std::array<std::string, 33> V2_MESSAGE_IDS = {
933 std::unordered_map<std::string, uint8_t> m_map;
936 V2MessageMap() noexcept
938 for (
size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
939 m_map.emplace(V2_MESSAGE_IDS[i], i);
943 std::optional<uint8_t> operator()(
const std::string& message_name)
const noexcept
945 auto it = m_map.find(message_name);
946 if (it == m_map.end())
return std::nullopt;
951 const V2MessageMap V2_MESSAGE_MAP;
953 std::vector<uint8_t> GenerateRandomGarbage() noexcept
955 std::vector<uint8_t>
ret;
968 Assume(m_send_buffer.empty());
972 std::copy(m_send_garbage.begin(), m_send_garbage.end(), m_send_buffer.begin() +
EllSwiftPubKey::size());
977 : m_cipher{key, ent32}, m_initiating{initiating}, m_nodeid{nodeid},
978 m_v1_fallback{nodeid},
979 m_recv_state{initiating ?
RecvState::KEY : RecvState::KEY_MAYBE_V1},
980 m_send_garbage{std::move(garbage)},
981 m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
983 Assume(m_send_garbage.size() <= MAX_GARBAGE_LEN);
987 StartSendingHandshake();
999 switch (m_recv_state) {
1000 case RecvState::KEY_MAYBE_V1:
1004 Assume(recv_state == RecvState::GARB_GARBTERM);
1006 case RecvState::GARB_GARBTERM:
1010 Assume(recv_state == RecvState::APP);
1012 case RecvState::APP:
1013 Assume(recv_state == RecvState::APP_READY);
1015 case RecvState::APP_READY:
1016 Assume(recv_state == RecvState::APP);
1023 m_recv_state = recv_state;
1030 switch (m_send_state) {
1031 case SendState::MAYBE_V1:
1032 Assume(send_state == SendState::V1 || send_state == SendState::AWAITING_KEY);
1034 case SendState::AWAITING_KEY:
1035 Assume(send_state == SendState::READY);
1037 case SendState::READY:
1043 m_send_state = send_state;
1064 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};
1065 std::copy(std::begin(
Params().MessageStart()), std::end(
Params().MessageStart()), v1_prefix.begin());
1066 Assume(m_recv_buffer.size() <= v1_prefix.size());
1067 if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), v1_prefix.begin())) {
1074 }
else if (m_recv_buffer.size() == v1_prefix.size()) {
1081 Assume(feedback.empty());
1106 static constexpr std::array<uint8_t, 12> MATCH = {
'v',
'e',
'r',
's',
'i',
'o',
'n', 0, 0, 0, 0, 0};
1107 static constexpr
size_t OFFSET = std::tuple_size_v<MessageStartChars>;
1108 if (!
m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
1109 if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
1127 m_recv_buffer.clear();
1161 m_recv_aad = std::move(m_recv_buffer);
1163 m_recv_buffer.clear();
1189 static constexpr
size_t MAX_CONTENTS_LEN =
1196 if (m_recv_len > MAX_CONTENTS_LEN) {
1204 m_recv_decode_buffer.resize(m_recv_len);
1223 switch (m_recv_state) {
1252 switch (m_recv_state) {
1302 static constexpr
size_t MAX_RESERVE_AHEAD = 256 * 1024;
1305 if (m_recv_state == RecvState::V1)
return m_v1_fallback.ReceivedBytes(msg_bytes);
1311 while (!msg_bytes.empty()) {
1313 size_t max_read = GetMaxBytesToProcess();
1316 if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
1317 switch (m_recv_state) {
1318 case RecvState::KEY_MAYBE_V1:
1320 case RecvState::GARB_GARBTERM:
1326 case RecvState::APP: {
1332 size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
1333 m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
1336 case RecvState::APP_READY:
1338 Assume(m_recv_buffer.empty());
1348 max_read = std::min(msg_bytes.size(), max_read);
1350 m_recv_buffer.insert(m_recv_buffer.end(),
UCharCast(msg_bytes.data()),
UCharCast(msg_bytes.data() + max_read));
1351 msg_bytes = msg_bytes.subspan(max_read);
1354 switch (m_recv_state) {
1355 case RecvState::KEY_MAYBE_V1:
1356 ProcessReceivedMaybeV1Bytes();
1357 if (m_recv_state == RecvState::V1)
return true;
1361 if (!ProcessReceivedKeyBytes())
return false;
1364 case RecvState::GARB_GARBTERM:
1365 if (!ProcessReceivedGarbageBytes())
return false;
1369 case RecvState::APP:
1370 if (!ProcessReceivedPacketBytes())
return false;
1373 case RecvState::APP_READY:
1390 if (contents.size() == 0)
return std::nullopt;
1391 uint8_t first_byte = contents[0];
1392 contents = contents.subspan(1);
1394 if (first_byte != 0) {
1396 if (first_byte < std::size(V2_MESSAGE_IDS)) {
1398 return V2_MESSAGE_IDS[first_byte];
1401 return std::nullopt;
1406 return std::nullopt;
1409 size_t msg_type_len{0};
1412 if (contents[msg_type_len] <
' ' || contents[msg_type_len] > 0x7F) {
1417 std::string
ret{
reinterpret_cast<const char*
>(contents.data()), msg_type_len};
1420 if (contents[msg_type_len] != 0)
return {};
1432 if (m_recv_state == RecvState::V1)
return m_v1_fallback.GetReceivedMessage(time, reject_message);
1434 Assume(m_recv_state == RecvState::APP_READY);
1436 auto msg_type = GetMessageType(contents);
1441 reject_message =
false;
1442 msg.m_type = std::move(*msg_type);
1444 msg.m_message_size = contents.size();
1445 msg.m_recv.resize(contents.size());
1446 std::copy(contents.begin(), contents.end(),
UCharCast(
msg.m_recv.data()));
1448 LogPrint(
BCLog::NET,
"V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(), m_nodeid);
1449 reject_message =
true;
1452 SetReceiveState(RecvState::APP);
1461 if (m_send_state == SendState::V1)
return m_v1_fallback.SetMessageToSend(
msg);
1465 if (!(m_send_state == SendState::READY && m_send_buffer.empty()))
return false;
1467 std::vector<uint8_t> contents;
1468 auto short_message_id = V2_MESSAGE_MAP(
msg.m_type);
1469 if (short_message_id) {
1470 contents.resize(1 +
msg.data.size());
1471 contents[0] = *short_message_id;
1472 std::copy(
msg.data.begin(),
msg.data.end(), contents.begin() + 1);
1477 std::copy(
msg.m_type.begin(),
msg.m_type.end(), contents.data() + 1);
1483 m_send_type =
msg.m_type;
1493 if (m_send_state == SendState::V1)
return m_v1_fallback.GetBytesToSend(have_next_message);
1495 if (m_send_state == SendState::MAYBE_V1)
Assume(m_send_buffer.empty());
1496 Assume(m_send_pos <= m_send_buffer.size());
1501 have_next_message && m_send_state == SendState::READY,
1510 if (m_send_state == SendState::V1)
return m_v1_fallback.MarkBytesSent(bytes_sent);
1512 if (m_send_state == SendState::AWAITING_KEY && m_send_pos == 0 && bytes_sent > 0) {
1516 m_send_pos += bytes_sent;
1517 Assume(m_send_pos <= m_send_buffer.size());
1519 m_sent_v1_header_worth =
true;
1522 if (m_send_pos == m_send_buffer.size()) {
1539 if (!m_recv_buffer.empty())
return false;
1542 return m_sent_v1_header_worth;
1577 auto it =
node.vSendMsg.begin();
1578 size_t nSentSize = 0;
1579 bool data_left{
false};
1580 std::optional<bool> expected_more;
1583 if (it !=
node.vSendMsg.end()) {
1587 size_t memusage = it->GetMemoryUsage();
1588 if (
node.m_transport->SetMessageToSend(*it)) {
1594 const auto& [data, more, msg_type] =
node.m_transport->GetBytesToSend(it !=
node.vSendMsg.end());
1598 if (expected_more.has_value())
Assume(!data.empty() == *expected_more);
1599 expected_more = more;
1600 data_left = !data.empty();
1602 if (!data.empty()) {
1616 nBytes =
node.m_sock->Send(
reinterpret_cast<const char*
>(data.data()), data.size(),
flags);
1619 node.m_last_send = GetTime<std::chrono::seconds>();
1620 node.nSendBytes += nBytes;
1622 node.m_transport->MarkBytesSent(nBytes);
1624 if (!msg_type.empty()) {
1625 node.AccountForSentBytes(msg_type, nBytes);
1627 nSentSize += nBytes;
1628 if ((
size_t)nBytes != data.size()) {
1638 node.CloseSocketDisconnect();
1647 if (it ==
node.vSendMsg.end()) {
1650 node.vSendMsg.erase(
node.vSendMsg.begin(), it);
1651 return {nSentSize, data_left};
1664 std::vector<NodeEvictionCandidate> vEvictionCandidates;
1669 if (
node->fDisconnect)
1673 .m_connected =
node->m_connected,
1674 .m_min_ping_time =
node->m_min_ping_time,
1675 .m_last_block_time =
node->m_last_block_time,
1676 .m_last_tx_time =
node->m_last_tx_time,
1677 .fRelevantServices =
node->m_has_all_wanted_services,
1678 .m_relay_txs =
node->m_relays_txs.load(),
1679 .fBloomFilter =
node->m_bloom_filter_loaded.load(),
1680 .nKeyedNetGroup =
node->nKeyedNetGroup,
1681 .prefer_evict =
node->m_prefer_evict,
1682 .m_is_local =
node->addr.IsLocal(),
1683 .m_network =
node->ConnectedThroughNetwork(),
1685 .m_conn_type =
node->m_conn_type,
1687 vEvictionCandidates.push_back(candidate);
1690 const std::optional<NodeId> node_id_to_evict =
SelectNodeToEvict(std::move(vEvictionCandidates));
1691 if (!node_id_to_evict) {
1695 for (
CNode* pnode : m_nodes) {
1696 if (pnode->GetId() == *node_id_to_evict) {
1697 LogPrint(
BCLog::NET,
"selected %s connection for eviction peer=%d; disconnecting\n", pnode->ConnectionTypeAsString(), pnode->GetId());
1698 pnode->fDisconnect =
true;
1706 struct sockaddr_storage sockaddr;
1707 socklen_t len =
sizeof(sockaddr);
1708 auto sock = hListenSocket.
sock->Accept((
struct sockaddr*)&sockaddr, &len);
1719 if (!addr.
SetSockAddr((
const struct sockaddr*)&sockaddr)) {
1744 for (
const CNode* pnode : m_nodes) {
1745 if (pnode->IsInboundConn()) nInbound++;
1754 if (!sock->IsSelectable()) {
1762 if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on,
sizeof(on)) ==
SOCKET_ERROR) {
1763 LogPrint(
BCLog::NET,
"connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
1787 LogPrint(
BCLog::NET,
"failed to find an eviction candidate - connection dropped (full)\n");
1811 .prefer_evict = discouraged,
1822 m_nodes.push_back(pnode);
1832 std::optional<int> max_connections;
1833 switch (conn_type) {
1853 return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](
CNode*
node) { return node->m_conn_type == conn_type; }););
1856 if (max_connections != std::nullopt && existing_connections >= max_connections)
return false;
1860 if (!grant)
return false;
1873 decltype(m_reconnections) reconnections_to_add;
1880 for (
CNode* pnode : m_nodes) {
1881 if (!pnode->fDisconnect) {
1883 pnode->fDisconnect =
true;
1889 std::vector<CNode*> nodes_copy = m_nodes;
1890 for (
CNode* pnode : nodes_copy)
1892 if (pnode->fDisconnect)
1895 m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());
1900 if (pnode->m_transport->ShouldReconnectV1()) {
1901 reconnections_to_add.push_back({
1902 .addr_connect = pnode->addr,
1903 .grant = std::move(pnode->grantOutbound),
1904 .destination = pnode->m_dest,
1905 .conn_type = pnode->m_conn_type,
1906 .use_v2transport =
false});
1907 LogPrint(
BCLog::NET,
"retrying with v1 transport protocol for peer=%d\n", pnode->GetId());
1911 pnode->grantOutbound.Release();
1914 pnode->CloseSocketDisconnect();
1917 if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];
1928 for (
CNode* pnode : nodes_disconnected_copy)
1931 if (pnode->GetRefCount() <= 0) {
1940 m_reconnections.splice(m_reconnections.end(), std::move(reconnections_to_add));
1949 nodes_size = m_nodes.size();
1968 const auto now{GetTime<std::chrono::seconds>()};
1969 const auto last_send{
node.m_last_send.load()};
1970 const auto last_recv{
node.m_last_recv.load()};
1974 if (last_recv.count() == 0 || last_send.count() == 0) {
1989 if (!
node.fSuccessfullyConnected) {
2002 events_per_sock.emplace(hListenSocket.sock,
Sock::Events{Sock::RECV});
2005 for (
CNode* pnode : nodes) {
2006 bool select_recv = !pnode->fPauseRecv;
2009 LOCK(pnode->cs_vSend);
2013 const auto& [to_send, more, _msg_type] = pnode->m_transport->GetBytesToSend(!pnode->vSendMsg.empty());
2014 select_send = !to_send.empty() || more;
2016 if (!select_recv && !select_send)
continue;
2018 LOCK(pnode->m_sock_mutex);
2019 if (pnode->m_sock) {
2021 events_per_sock.emplace(pnode->m_sock,
Sock::Events{event});
2025 return events_per_sock;
2044 if (events_per_sock.empty() || !events_per_sock.begin()->first->WaitMany(timeout, events_per_sock)) {
2061 for (
CNode* pnode : nodes) {
2068 bool recvSet =
false;
2069 bool sendSet =
false;
2070 bool errorSet =
false;
2072 LOCK(pnode->m_sock_mutex);
2073 if (!pnode->m_sock) {
2076 const auto it = events_per_sock.find(pnode->m_sock);
2077 if (it != events_per_sock.end()) {
2080 errorSet = it->second.occurred &
Sock::ERR;
2097 if (data_left) recvSet =
false;
2101 if (recvSet || errorSet)
2104 uint8_t pchBuf[0x10000];
2107 LOCK(pnode->m_sock_mutex);
2108 if (!pnode->m_sock) {
2111 nBytes = pnode->m_sock->Recv(pchBuf,
sizeof(pchBuf),
MSG_DONTWAIT);
2115 bool notify =
false;
2116 if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
2117 pnode->CloseSocketDisconnect();
2121 pnode->MarkReceivedMsgsForProcessing();
2125 else if (nBytes == 0)
2128 if (!pnode->fDisconnect) {
2131 pnode->CloseSocketDisconnect();
2133 else if (nBytes < 0)
2139 if (!pnode->fDisconnect) {
2142 pnode->CloseSocketDisconnect();
2157 const auto it = events_per_sock.find(listen_socket.sock);
2158 if (it != events_per_sock.end() && it->second.occurred &
Sock::RECV) {
2180 fMsgProcWake =
true;
2189 Shuffle(seeds.begin(), seeds.end(), rng);
2190 int seeds_right_now = 0;
2195 seeds_right_now = seeds.size();
2200 seeds_right_now = seeds.size();
2217 for (
const std::string& seed : seeds) {
2218 if (seeds_right_now == 0) {
2222 LogPrintf(
"Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
2223 std::chrono::seconds to_wait = seeds_wait_time;
2224 while (to_wait.count() > 0) {
2235 for (
const CNode* pnode : m_nodes) {
2236 if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
2239 if (nRelevant >= 2) {
2241 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2242 LogPrintf(
"P2P peers available. Finished DNS seeding.\n");
2244 LogPrintf(
"P2P peers available. Skipped DNS seeding.\n");
2256 LogPrintf(
"Waiting for network to be reactivated before querying DNS seeds.\n");
2262 LogPrintf(
"Loading addresses from DNS seed %s\n", seed);
2268 std::vector<CAddress> vAdd;
2270 std::string host =
strprintf(
"x%x.%s", requiredServiceBits, seed);
2279 unsigned int nMaxIPs = 32;
2280 const auto addresses{
LookupHost(host, nMaxIPs,
true)};
2281 if (!addresses.empty()) {
2285 vAdd.push_back(addr);
2298 LogPrintf(
"%d addresses found from DNS seeds\n", found);
2303 const auto start{SteadyClock::now()};
2308 addrman.
Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
2314 std::string strDest;
2317 if (m_addr_fetches.empty())
2319 strDest = m_addr_fetches.front();
2320 m_addr_fetches.pop_front();
2340 LogPrint(
BCLog::NET,
"setting try another outbound peer=%s\n", flag ?
"true" :
"false");
2357 int full_outbound_peers = 0;
2360 for (
const CNode* pnode : m_nodes) {
2361 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
2362 ++full_outbound_peers;
2371 int block_relay_peers = 0;
2374 for (
const CNode* pnode : m_nodes) {
2375 if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
2376 ++block_relay_peers;
2385 std::unordered_set<Network> networks{};
2386 for (
int n = 0; n <
NET_MAX; n++) {
2390 networks.insert(net);
2399 return m_network_conn_counts[net] > 1;
2408 for (
const auto net : nets) {
2424 if (!connect.empty())
2429 for (int64_t nLoop = 0;; nLoop++)
2431 for (
const std::string& strAddr : connect)
2435 for (
int i = 0; i < 10 && i < nLoop; i++)
2448 auto start = GetTime<std::chrono::microseconds>();
2458 if (!add_fixed_seeds) {
2459 LogPrintf(
"Fixed seeds are disabled\n");
2476 if (add_fixed_seeds && !fixed_seed_networks.empty()) {
2481 bool add_fixed_seeds_now =
false;
2483 if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
2484 add_fixed_seeds_now =
true;
2485 LogPrintf(
"Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
2489 else if (!dnsseed && !use_seednodes) {
2491 if (m_added_node_params.empty()) {
2492 add_fixed_seeds_now =
true;
2493 LogPrintf(
"Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
2497 if (add_fixed_seeds_now) {
2505 seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
2506 [&fixed_seed_networks](
const CAddress& addr) { return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
2511 add_fixed_seeds =
false;
2512 LogPrintf(
"Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
2522 int nOutboundFullRelay = 0;
2523 int nOutboundBlockRelay = 0;
2524 int outbound_privacy_network_peers = 0;
2525 std::set<std::vector<unsigned char>> outbound_ipv46_peer_netgroups;
2529 for (
const CNode* pnode : m_nodes) {
2530 if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
2531 if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
2534 switch (pnode->m_conn_type) {
2547 const CAddress address{pnode->addr};
2548 if (address.IsTor() || address.IsI2P() || address.IsCJDNS()) {
2556 ++outbound_privacy_network_peers;
2565 auto now = GetTime<std::chrono::microseconds>();
2566 bool anchor =
false;
2567 bool fFeeler =
false;
2568 std::optional<Network> preferred_net;
2614 }
else if (now > next_feeler) {
2620 now > next_extra_network_peer &&
2685 std::tie(addr, addr_last_try) =
addrman.
Select(
false, preferred_net);
2703 if (current_time - addr_last_try < 10min && nTries < 30) {
2726 preferred_net.has_value() ?
"network-specific " :
"",
2751 const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(
m_max_automatic_connections - 1, 2)};
2761 std::vector<CAddress>
ret;
2763 for (
const CNode* pnode : m_nodes) {
2764 if (pnode->IsBlockOnlyConn()) {
2765 ret.push_back(pnode->addr);
2774 std::vector<AddedNodeInfo>
ret;
2776 std::list<AddedNodeParams> lAddresses(0);
2779 ret.reserve(m_added_node_params.size());
2780 std::copy(m_added_node_params.cbegin(), m_added_node_params.cend(), std::back_inserter(lAddresses));
2785 std::map<CService, bool> mapConnected;
2786 std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2789 for (
const CNode* pnode : m_nodes) {
2790 if (pnode->addr.IsValid()) {
2791 mapConnected[pnode->addr] = pnode->IsInboundConn();
2793 std::string addrName{pnode->m_addr_name};
2794 if (!addrName.empty()) {
2795 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(),
static_cast<const CService&
>(pnode->addr));
2800 for (
const auto& addr : lAddresses) {
2805 auto it = mapConnected.find(service);
2806 if (it != mapConnected.end()) {
2807 if (!include_connected) {
2810 addedNode.resolvedAddress = service;
2811 addedNode.fConnected =
true;
2812 addedNode.fInbound = it->second;
2816 auto it = mapConnectedByName.find(addr.m_added_node);
2817 if (it != mapConnectedByName.end()) {
2818 if (!include_connected) {
2821 addedNode.resolvedAddress = it->second.second;
2822 addedNode.fConnected =
true;
2823 addedNode.fInbound = it->second.first;
2826 ret.emplace_back(std::move(addedNode));
2877 bool banned_or_discouraged =
m_banman && (
m_banman->IsDiscouraged(addrConnect) ||
m_banman->IsBanned(addrConnect));
2881 }
else if (
FindNode(std::string(pszDest)))
2893 m_nodes.push_back(pnode);
2908 bool fMoreWork =
false;
2916 for (
CNode* pnode : snap.Nodes()) {
2917 if (pnode->fDisconnect)
2922 fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
2937 fMsgProcWake =
false;
2943 static constexpr
auto err_wait_begin = 1s;
2944 static constexpr
auto err_wait_cap = 5min;
2945 auto err_wait = err_wait_begin;
2947 bool advertising_listen_addr =
false;
2950 auto SleepOnFailure = [&]() {
2952 if (err_wait < err_wait_cap) {
2960 if (advertising_listen_addr && conn.
me.
IsValid()) {
2962 advertising_listen_addr =
false;
2968 if (!advertising_listen_addr) {
2970 advertising_listen_addr =
true;
2981 err_wait = err_wait_begin;
2990 struct sockaddr_storage sockaddr;
2991 socklen_t len =
sizeof(sockaddr);
2992 if (!addrBind.
GetSockAddr((
struct sockaddr*)&sockaddr, &len))
3023 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
3024 if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (
const char*)&nProtLevel,
sizeof(
int)) ==
SOCKET_ERROR) {
3031 if (sock->Bind(
reinterpret_cast<struct sockaddr*
>(&sockaddr), len) ==
SOCKET_ERROR) {
3061 char pszHostName[256] =
"";
3062 if (gethostname(pszHostName,
sizeof(pszHostName)) !=
SOCKET_ERROR)
3064 const std::vector<CNetAddr> addresses{
LookupHost(pszHostName, 0,
true)};
3065 for (
const CNetAddr& addr : addresses)
3068 LogPrintf(
"%s: %s - %s\n", __func__, pszHostName, addr.ToStringAddr());
3071 #elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
3073 struct ifaddrs* myaddrs;
3074 if (getifaddrs(&myaddrs) == 0)
3076 for (
struct ifaddrs* ifa = myaddrs; ifa !=
nullptr; ifa = ifa->ifa_next)
3078 if (ifa->ifa_addr ==
nullptr)
continue;
3079 if ((ifa->ifa_flags & IFF_UP) == 0)
continue;
3080 if (strcmp(ifa->ifa_name,
"lo") == 0)
continue;
3081 if (strcmp(ifa->ifa_name,
"lo0") == 0)
continue;
3082 if (ifa->ifa_addr->sa_family == AF_INET)
3084 struct sockaddr_in* s4 = (
struct sockaddr_in*)(ifa->ifa_addr);
3089 else if (ifa->ifa_addr->sa_family == AF_INET6)
3091 struct sockaddr_in6* s6 = (
struct sockaddr_in6*)(ifa->ifa_addr);
3097 freeifaddrs(myaddrs);
3104 LogPrintf(
"%s: %s\n", __func__, active);
3119 : addrman(addrman_in)
3120 , m_netgroupman{netgroupman}
3134 return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
3169 bool fBound =
false;
3170 for (
const auto& addrBind : options.
vBinds) {
3173 for (
const auto& addrBind : options.
vWhiteBinds) {
3176 for (
const auto& addr_bind : options.
onion_binds) {
3180 struct in_addr inaddr_any;
3181 inaddr_any.s_addr = htonl(INADDR_ANY);
3182 struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
3197 _(
"Failed to listen on any port. Use -listen=0 if you want this."),
3209 for (
const auto& strDest : connOptions.
vSeedNodes) {
3219 LogPrintf(
"%i block-relay-only anchors will be tried for connections.\n",
m_anchors.size());
3246 fMsgProcWake =
false;
3263 _(
"Cannot provide specific connections and have addrman find outgoing connections at the same time."),
3367 std::vector<CNode*> nodes;
3369 for (
CNode* pnode : nodes) {
3370 pnode->CloseSocketDisconnect();
3396 std::vector<CAddress>
CConnman::GetAddresses(
size_t max_addresses,
size_t max_pct, std::optional<Network> network,
const bool filtered)
const
3398 std::vector<CAddress> addresses =
addrman.
GetAddr(max_addresses, max_pct, network, filtered);
3400 addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3401 [
this](
const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
3412 .
Write(local_socket_bytes)
3417 const auto current_time = GetTime<std::chrono::microseconds>();
3454 const bool resolved_is_valid{resolved.
IsValid()};
3457 for (
const auto& it : m_added_node_params) {
3461 m_added_node_params.push_back(add);
3468 for (
auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
3469 if (strNode == it->m_added_node) {
3470 m_added_node_params.erase(it);
3483 return (m_added_node_params.size() < 24
3484 && std::any_of(m_added_node_params.cbegin(), m_added_node_params.cend(),
3485 [&](
const auto& p) { return p.m_added_node == addr_str || p.m_added_node == addr_port_str; }));
3492 return m_nodes.size();
3495 for (
const auto& pnode : m_nodes) {
3513 vstats.reserve(m_nodes.size());
3514 for (
CNode* pnode : m_nodes) {
3515 vstats.emplace_back();
3516 pnode->CopyStats(vstats.back());
3517 vstats.back().m_mapped_as =
GetMappedAS(pnode->addr);
3526 pnode->fDisconnect =
true;
3534 bool disconnected =
false;
3536 for (
CNode* pnode : m_nodes) {
3537 if (subnet.
Match(pnode->addr)) {
3539 pnode->fDisconnect =
true;
3540 disconnected =
true;
3543 return disconnected;
3554 for(
CNode* pnode : m_nodes) {
3555 if (
id == pnode->GetId()) {
3557 pnode->fDisconnect =
true;
3574 nTotalBytesSent += bytes;
3576 const auto now = GetTime<std::chrono::seconds>();
3580 nMaxOutboundCycleStartTime = now;
3581 nMaxOutboundTotalBytesSentInCycle = 0;
3584 nMaxOutboundTotalBytesSentInCycle += bytes;
3613 if (nMaxOutboundCycleStartTime.count() == 0)
3617 const auto now = GetTime<std::chrono::seconds>();
3618 return (cycleEndTime < now) ? 0s : cycleEndTime - now;
3628 if (historicalBlockServingLimit)
3661 return nTotalBytesSent;
3671 if (use_v2transport) {
3672 return std::make_unique<V2Transport>(
id, !inbound);
3674 return std::make_unique<V1Transport>(
id);
3679 std::shared_ptr<Sock> sock,
3681 uint64_t nKeyedNetGroupIn,
3682 uint64_t nLocalHostNonceIn,
3684 const std::string& addrNameIn,
3689 m_permission_flags{node_opts.permission_flags},
3691 m_connected{
GetTime<
std::chrono::seconds>()},
3693 addrBind{addrBindIn},
3694 m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
3696 m_inbound_onion{inbound_onion},
3697 m_prefer_evict{node_opts.prefer_evict},
3698 nKeyedNetGroup{nKeyedNetGroupIn},
3699 m_conn_type{conn_type_in},
3701 nLocalHostNonce{nLocalHostNonceIn},
3702 m_recv_flood_size{node_opts.recv_flood_size},
3703 m_i2p_sam_session{
std::move(node_opts.i2p_sam_session)}
3708 mapRecvBytesPerMsgType[
msg] = 0;
3722 size_t nSizeAdded = 0;
3726 nSizeAdded +=
msg.m_raw_message_size;
3730 m_msg_process_queue.splice(m_msg_process_queue.end(),
vRecvMsg);
3731 m_msg_process_queue_size += nSizeAdded;
3738 if (m_msg_process_queue.empty())
return std::nullopt;
3740 std::list<CNetMessage> msgs;
3742 msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
3743 m_msg_process_queue_size -= msgs.front().m_raw_message_size;
3746 return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
3757 size_t nMessageSize =
msg.data.size();
3763 TRACE6(net, outbound_message,
3772 size_t nBytesSent = 0;
3777 const auto& [to_send, more, _msg_type] =
3779 const bool queue_was_empty{to_send.empty() && pnode->vSendMsg.empty()};
3782 pnode->m_send_memusage +=
msg.GetMemoryUsage();
3785 pnode->vSendMsg.push_back(std::move(
msg));
3794 if (queue_was_empty && more) {
3803 CNode* found =
nullptr;
3805 for (
auto&& pnode : m_nodes) {
3806 if(pnode->
GetId() ==
id) {
3832 decltype(m_reconnections) todo;
3835 if (m_reconnections.empty())
break;
3836 todo.splice(todo.end(), m_reconnections, m_reconnections.begin());
3839 auto& item = *todo.begin();
3846 std::move(item.grant),
3847 item.destination.empty() ?
nullptr : item.destination.c_str(),
3849 item.use_v2transport);
3857 std::vector<CNetAddr> clearnet_addrs;
3858 clearnet_addrs.reserve(v4_addrs.size() + v6_addrs.size());
3859 std::transform(v4_addrs.begin(), v4_addrs.end(), std::back_inserter(clearnet_addrs),
3860 [](
const CAddress& addr) { return static_cast<CNetAddr>(addr); });
3861 std::transform(v6_addrs.begin(), v6_addrs.end(), std::back_inserter(clearnet_addrs),
3862 [](
const CAddress& addr) { return static_cast<CNetAddr>(addr); });
3868 const std::string& msg_type,
3876 auto now = GetTime<std::chrono::microseconds>();
3880 std::replace(clean_addr.begin(), clean_addr.end(),
':',
'_');
3885 fs::path path = base_path / (is_incoming ?
"msgs_recv.dat" :
"msgs_sent.dat");
3889 f <<
Span{msg_type};
3893 uint32_t size = data.
size();
3898 std::function<void(
const CAddress& addr,
3899 const std::string& msg_type,
std::vector< CAddress > ReadAnchors(const fs::path &anchors_db_path)
Read the anchor IP address database (anchors.dat)
bool DumpPeerAddresses(const ArgsManager &args, const AddrMan &addr)
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, std::optional< Network > network=std::nullopt) 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.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Non-refcounted RAII wrapper for FILE*.
Span< const std::byte > GetSendGarbageTerminator() const noexcept
Get the Garbage Terminator to send.
Span< const std::byte > GetSessionID() const noexcept
Get the Session ID.
static constexpr unsigned GARBAGE_TERMINATOR_LEN
unsigned DecryptLength(Span< const std::byte > input) noexcept
Decrypt the length of a packet.
const EllSwiftPubKey & GetOurPubKey() const noexcept
Retrieve our public key.
bool Decrypt(Span< const std::byte > input, Span< const std::byte > aad, bool &ignore, Span< std::byte > contents) noexcept
Decrypt a packet.
void Encrypt(Span< const std::byte > contents, Span< const std::byte > aad, bool ignore, Span< std::byte > output) noexcept
Encrypt a packet.
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.
Span< const std::byte > GetReceiveGarbageTerminator() const noexcept
Get the expected Garbage Terminator to receive.
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 std::vector< std::string > & DNSSeeds() const
Return the list of hostnames to look up for DNS seeds.
const std::vector< uint8_t > & FixedSeeds() const
uint16_t GetDefaultPort() const
const MessageStartChars & MessageStart() 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 Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
Sock::EventsPerSock GenerateWaitSockets(Span< CNode *const > nodes)
Generate a collection of sockets to check for IO readiness.
CThreadInterrupt interruptNet
This is signaled when network activity should cease.
std::unique_ptr< CSemaphore > semAddnode
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
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)
std::unique_ptr< CSemaphore > semOutbound
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 ThreadOpenConnections(std::vector< std::string > connect) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex
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)
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
uint64_t CalculateKeyedNetGroup(const CAddress &ad) const
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.
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)
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)
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 CreateNodeFromAcceptedSocket(std::unique_ptr< Sock > &&sock, NetPermissionFlags permission_flags, const CAddress &addr_bind, const CAddress &addr)
Create a CNode object from a socket that has just been accepted and add the node to the m_nodes membe...
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg) 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...
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 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.
Information about a peer.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
std::atomic< int > nVersion
bool IsInboundConn() const
std::atomic_bool fPauseRecv
std::atomic< int64_t > nTimeOffset
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.
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
CSemaphoreGrant grantOutbound
void MarkReceivedMsgsForProcessing() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Move all messages from the received queue to the processing queue.
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
Mutex m_msg_process_queue_mutex
const ConnectionType m_conn_type
Network ConnectedThroughNetwork() const
Get network the peer connected through.
const size_t m_recv_flood_size
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.
std::atomic< std::chrono::microseconds > m_last_ping_time
Last measured round-trip time.
bool IsManualOrFullOutboundConn() const
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::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)
CNode(NodeId id, std::shared_ptr< Sock > sock, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion, CNodeOptions &&node_opts={})
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.
RAII-style semaphore lock.
A combination of a network address (CNetAddr) and a (TCP) port.
bool SetSockAddr(const struct sockaddr *paddr)
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)
Double ended buffer combining vector and stream-like interfaces.
Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive).
void fillrand(Span< std::byte > output)
Fill a byte Span with random bytes.
Tp rand_uniform_delay(const Tp &time, typename Tp::duration range)
Return the time point advanced by a uniform random duration.
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
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 (and hides GetVersion/GetType).
std::string ToString() const
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().
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
constexpr C * data() const noexcept
constexpr C * end() const noexcept
constexpr C * begin() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
std::tuple< Span< const uint8_t >, bool, const std::string & > BytesToSend
Return type for GetBytesToSend, consisting of:
int readData(Span< const uint8_t > msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
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.
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.
V1Transport(const NodeId node_id) noexcept
bool CompleteInternal() const noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
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)
bool ReceivedBytes(Span< const uint8_t > &msg_bytes) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)
Feed wire bytes to the transport.
Mutex m_recv_mutex
Lock for receive state.
int readHeader(Span< const uint8_t > msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)
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.
bool ReceivedBytes(Span< const uint8_t > &msg_bytes) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex
Feed wire bytes to the transport.
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(Span< const uint8_t > &contents) noexcept
Given a packet's contents, find the message type (if valid), and strip it from contents.
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()
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
#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)
static uint32_t ReadLE32(const unsigned char *ptr)
static CService ip(uint32_t i)
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
CKey GenerateRandomKey(bool compressed) noexcept
#define LogPrintLevel(category, level,...)
#define LogPrint(category,...)
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
const char * BLOCK
The block message transmits a single serialized block.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
const char * TX
The tx message transmits a single transaction.
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
const char * GETDATA
The getdata message requests one or more data objects from another node.
const char * BLOCKTXN
Contains a BlockTransactions.
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
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...
FILE * fopen(const fs::path &p, const char *mode)
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
void TraceThread(std::string_view thread_name, std::function< void()> thread_func)
A wrapper for do-something-once thread functions.
static std::vector< CAddress > ConvertSeeds(const std::vector< uint8_t > &vSeedsIn)
Convert the serialized seeds into usable address objects.
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)
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
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 CAddress GetBindAddress(const Sock &sock)
Get the bind address for a socket as CAddress.
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)
std::map< CNetAddr, LocalServiceInfo > mapLocalHost GUARDED_BY(g_maplocalhost_mutex)
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.
const std::string NET_MESSAGE_TYPE_OTHER
const char *const ANCHORS_DATABASE_FILENAME
Anchor IP address database file name.
CService GetLocalAddress(const CNode &peer)
GlobalMutex g_maplocalhost_mutex
static void CaptureMessageToFile(const CAddress &addr, const std::string &msg_type, Span< const unsigned char > data, bool is_incoming)
static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS
static int GetnScore(const CService &addr)
static std::optional< CService > GetLocal(const CNode &peer)
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.
static CNetCleanup instance_of_cnetcleanup
static std::unique_ptr< Transport > MakeTransport(NodeId id, bool use_v2transport, bool inbound) noexcept
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::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.
std::string GetNetworkName(enum Network net)
CThreadInterrupt g_socks5_interrupt
Interrupt SOCKS5 reads or writes.
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...
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::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::unique_ptr< Sock > ConnectDirectly(const CService &dest, bool manual_connection)
Create a socket and try to connect to the specified service.
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::function< std::unique_ptr< Sock >const sa_family_t &)> CreateSock
Socket factory.
const std::vector< std::string > & getAllNetMessageTypes()
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.
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en....
uint256 GetRandHash() noexcept
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
constexpr auto GetRandMillis
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
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.
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) unsigned char member types only.
unsigned char * UCharCast(char *c)
Span(T *, EndOrSize) -> Span< T >
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Cache responses to addr requests to minimize privacy leak.
std::chrono::microseconds m_cache_entry_expiration
std::vector< CAddress > m_addrs_response_cache
void AddSocketPermissionFlags(NetPermissionFlags &flags) const
std::shared_ptr< Sock > sock
std::vector< NetWhitebindPermissions > vWhiteBinds
std::vector< CService > onion_binds
std::vector< std::string > m_specified_outgoing
std::vector< CService > vBinds
bool m_i2p_accept_incoming
std::vector< std::string > vSeedNodes
bool m_use_addrman_outgoing
bool bind_on_any
True if the user did not specify -bind= or -whitebind= and thus we should bind on 0....
NetPermissionFlags permission_flags
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.
#define WAIT_LOCK(cs, name)
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
#define TRACE6(context, event, a, b, c, d, e, f)
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
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.
void ClearShrink(V &v) noexcept
Clear a vector (or std::deque) and release its allocated memory.