v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3
src/net.cpp
Before: src/net.cpp · After: src/net.cpp
File metadata
index 50988114d0b137dd47b388c2678484376612d806..b29cb951b141922e1a5b3c75fc29b7c55ff154df 100644
Download original patch · Release notes
Diff rows 1–377 of 377. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
src/net.cpp
CHANGED
|
@@ -108,7 +108,7 @@ const std::string NET_MESSAGE_TYPE_OTHER = "*other*";
|
|
|
108
108
|
|
|
109
109
|
static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
|
|
110
110
|
static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
|
|
111
|
-
static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256("addrcache")[0:8]
|
|
111
|
+
static const uint64_t RANDOMIZER_ID_NETWORKKEY = 0x0e8a2b136c592a7dULL; // SHA256("networkkey")[0:8]
|
|
112
112
|
//
|
|
113
113
|
// Global state variables
|
|
114
114
|
//
|
|
@@ -221,7 +221,7 @@ CService GetLocalAddress(const CNode& peer)
|
|
|
221
221
|
return GetLocal(peer).value_or(CService{CNetAddr(), GetListenPort()});
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
static int GetnScore(const CService& addr)
|
|
224
|
+
int GetnScore(const CService& addr)
|
|
225
225
|
{
|
|
226
226
|
LOCK(g_maplocalhost_mutex);
|
|
227
227
|
const auto it = mapLocalHost.find(addr);
|
|
@@ -283,7 +283,8 @@ bool AddLocal(const CService& addr_, int nScore)
|
|
|
283
283
|
if (!fDiscover && nScore < LOCAL_MANUAL)
|
|
284
284
|
return false;
|
|
285
285
|
|
|
286
|
-
if (!g_reachable_nets.Contains(addr))
|
|
286
|
+
// IPv4 and IPv6 cannot be connected to unless their networks are reachable, but Tor is not necessarily bidirectional
|
|
287
|
+
if (!(g_reachable_nets.Contains(addr) || addr.IsTor()))
|
|
287
288
|
return false;
|
|
288
289
|
|
|
289
290
|
LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
|
|
@@ -308,9 +309,11 @@ bool AddLocal(const CNetAddr &addr, int nScore)
|
|
|
308
309
|
|
|
309
310
|
void RemoveLocal(const CService& addr)
|
|
310
311
|
{
|
|
311
|
-
LOCK(g_maplocalhost_mutex);
|
|
312
|
-
LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort());
|
|
313
|
-
mapLocalHost.erase(addr);
|
|
312
|
+
{
|
|
313
|
+
LOCK(g_maplocalhost_mutex);
|
|
314
|
+
LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort());
|
|
315
|
+
mapLocalHost.erase(addr);
|
|
316
|
+
}
|
|
314
317
|
}
|
|
315
318
|
|
|
316
319
|
/** vote for a local address */
|
|
@@ -319,7 +322,9 @@ bool SeenLocal(const CService& addr)
|
|
|
319
322
|
LOCK(g_maplocalhost_mutex);
|
|
320
323
|
const auto it = mapLocalHost.find(addr);
|
|
321
324
|
if (it == mapLocalHost.end()) return false;
|
|
322
|
-
++it->second.nScore;
|
|
325
|
+
if (it->second.nScore < std::numeric_limits<int>::max()) {
|
|
326
|
+
++it->second.nScore;
|
|
327
|
+
}
|
|
323
328
|
return true;
|
|
324
329
|
}
|
|
325
330
|
|
|
@@ -462,6 +467,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|
|
462
467
|
std::unique_ptr<i2p::sam::Session> i2p_transient_session;
|
|
463
468
|
|
|
464
469
|
for (auto& target_addr: connect_to) {
|
|
470
|
+
if (DisableV1OnClearnet(target_addr.GetNetClass()) && !use_v2transport) {
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
465
473
|
if (target_addr.IsValid()) {
|
|
466
474
|
const bool use_proxy{GetProxy(target_addr.GetNetwork(), proxy)};
|
|
467
475
|
bool proxyConnectionFailed = false;
|
|
@@ -521,8 +529,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|
|
521
529
|
}
|
|
522
530
|
|
|
523
531
|
NetPermissionFlags permission_flags = NetPermissionFlags::None;
|
|
524
|
-
std::vector<NetWhitelistPermissions> whitelist_permissions = conn_type == ConnectionType::MANUAL ? vWhitelistedRangeOutgoing : std::vector<NetWhitelistPermissions>{};
|
|
525
|
-
AddWhitelistPermissionFlags(permission_flags, target_addr, whitelist_permissions);
|
|
532
|
+
AddWhitelistPermissionFlags(permission_flags, target_addr, vWhitelistedRangeOutgoing);
|
|
526
533
|
|
|
527
534
|
// Add node
|
|
528
535
|
NodeId id = GetNewNodeId();
|
|
@@ -530,6 +537,13 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|
|
530
537
|
if (!addr_bind.IsValid()) {
|
|
531
538
|
addr_bind = GetBindAddress(*sock);
|
|
532
539
|
}
|
|
540
|
+
uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)
|
|
541
|
+
.Write(target_addr.GetNetClass())
|
|
542
|
+
.Write(addr_bind.GetAddrBytes())
|
|
543
|
+
// For outbound connections, the port of the bound address is randomly
|
|
544
|
+
// assigned by the OS and would therefore not be useful for seeding.
|
|
545
|
+
.Write(0)
|
|
546
|
+
.Finalize();
|
|
533
547
|
CNode* pnode = new CNode(id,
|
|
534
548
|
std::move(sock),
|
|
535
549
|
target_addr,
|
|
@@ -539,6 +553,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|
|
539
553
|
pszDest ? pszDest : "",
|
|
540
554
|
conn_type,
|
|
541
555
|
/*inbound_onion=*/false,
|
|
556
|
+
network_id,
|
|
542
557
|
CNodeOptions{
|
|
543
558
|
.permission_flags = permission_flags,
|
|
544
559
|
.i2p_sam_session = std::move(i2p_transient_session),
|
|
@@ -586,6 +601,7 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optio
|
|
|
586
601
|
if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
|
|
587
602
|
NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
|
|
588
603
|
NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
|
|
604
|
+
NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
|
|
589
605
|
}
|
|
590
606
|
}
|
|
591
607
|
|
|
@@ -650,6 +666,7 @@ void CNode::CopyStats(CNodeStats& stats)
|
|
|
650
666
|
if (info.session_id) stats.m_session_id = HexStr(*info.session_id);
|
|
651
667
|
}
|
|
652
668
|
X(m_permission_flags);
|
|
669
|
+
X(m_forced_inbound);
|
|
653
670
|
|
|
654
671
|
X(m_last_ping_time);
|
|
655
672
|
X(m_min_ping_time);
|
|
@@ -659,6 +676,8 @@ void CNode::CopyStats(CNodeStats& stats)
|
|
|
659
676
|
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
|
|
660
677
|
|
|
661
678
|
X(m_conn_type);
|
|
679
|
+
|
|
680
|
+
X(m_cpu_time);
|
|
662
681
|
}
|
|
663
682
|
#undef X
|
|
664
683
|
|
|
@@ -1684,7 +1703,7 @@ std::pair<size_t, bool> CConnman::SocketSendData(CNode& node) const
|
|
|
1684
1703
|
* to forge. In order to partition a node the attacker must be
|
|
1685
1704
|
* simultaneously better at all of them than honest peers.
|
|
1686
1705
|
*/
|
|
1687
|
-
bool CConnman::AttemptToEvictConnection()
|
|
1706
|
+
bool CConnman::AttemptToEvictConnection(bool force)
|
|
1688
1707
|
{
|
|
1689
1708
|
std::vector<NodeEvictionCandidate> vEvictionCandidates;
|
|
1690
1709
|
{
|
|
@@ -1712,7 +1731,7 @@ bool CConnman::AttemptToEvictConnection()
|
|
|
1712
1731
|
vEvictionCandidates.push_back(candidate);
|
|
1713
1732
|
}
|
|
1714
1733
|
}
|
|
1715
|
-
const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
|
|
1734
|
+
const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates), force);
|
|
1716
1735
|
if (!node_id_to_evict) {
|
|
1717
1736
|
return false;
|
|
1718
1737
|
}
|
|
@@ -1768,7 +1787,26 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
|
1768
1787
|
{
|
|
1769
1788
|
int nInbound = 0;
|
|
1770
1789
|
|
|
1771
|
-
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
|
|
1790
|
+
const bool inbound_onion = [this, &addr, &addr_bind]{
|
|
1791
|
+
if (m_onion_binds.empty()) {
|
|
1792
|
+
if (!m_listenonion) {
|
|
1793
|
+
// If -listenonion=0, assume we do not have inbound Tor connections on non-onion listeners
|
|
1794
|
+
return false;
|
|
1795
|
+
}
|
|
1796
|
+
// Tor connections are coming in on the first -bind
|
|
1797
|
+
if ((!m_normal_binds.empty()) && addr_bind == m_normal_binds.front()) {
|
|
1798
|
+
if (addr_bind.IsBindAny()) {
|
|
1799
|
+
// Tor connections should have a source IP that is local
|
|
1800
|
+
return addr.IsLocal();
|
|
1801
|
+
}
|
|
1802
|
+
// Otherwise, the source IP is unpredictable, so assume anything could be onion
|
|
1803
|
+
return true;
|
|
1804
|
+
}
|
|
1805
|
+
return false;
|
|
1806
|
+
} else {
|
|
1807
|
+
return std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
|
|
1808
|
+
}
|
|
1809
|
+
}();
|
|
1772
1810
|
|
|
1773
1811
|
// Tor inbound connections do not reveal the peer's actual network address.
|
|
1774
1812
|
// Therefore do not apply address-based whitelist permissions to them.
|
|
@@ -1815,13 +1853,19 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
|
1815
1853
|
return;
|
|
1816
1854
|
}
|
|
1817
1855
|
|
|
1856
|
+
bool forced{false};
|
|
1818
1857
|
if (nInbound >= m_max_inbound)
|
|
1819
1858
|
{
|
|
1820
|
-
if (!AttemptToEvictConnection()) {
|
|
1859
|
+
// If the inbound connection attempt is granted ForceInbound permission, try a little harder
|
|
1860
|
+
// to make room by evicting a peer we may not have otherwise evicted.
|
|
1861
|
+
if (!AttemptToEvictConnection(NetPermissions::HasFlag(permission_flags, NetPermissionFlags::ForceInbound))) {
|
|
1821
1862
|
// No connection to evict, disconnect the new connection
|
|
1822
1863
|
LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
|
|
1823
1864
|
return;
|
|
1824
1865
|
}
|
|
1866
|
+
|
|
1867
|
+
// We kicked someone out
|
|
1868
|
+
forced = true;
|
|
1825
1869
|
}
|
|
1826
1870
|
|
|
1827
1871
|
NodeId id = GetNewNodeId();
|
|
@@ -1832,6 +1876,11 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
|
1832
1876
|
ServiceFlags local_services = GetLocalServices();
|
|
1833
1877
|
const bool use_v2transport(local_services & NODE_P2P_V2);
|
|
1834
1878
|
|
|
1879
|
+
uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)
|
|
1880
|
+
.Write(inbound_onion ? NET_ONION : addr.GetNetClass())
|
|
1881
|
+
.Write(addr_bind.GetAddrBytes())
|
|
1882
|
+
.Write(addr_bind.GetPort()) // inbound connections use bind port
|
|
1883
|
+
.Finalize();
|
|
1835
1884
|
CNode* pnode = new CNode(id,
|
|
1836
1885
|
std::move(sock),
|
|
1837
1886
|
CAddress{addr, NODE_NONE},
|
|
@@ -1841,9 +1890,11 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
|
1841
1890
|
/*addrNameIn=*/"",
|
|
1842
1891
|
ConnectionType::INBOUND,
|
|
1843
1892
|
inbound_onion,
|
|
1893
|
+
network_id,
|
|
1844
1894
|
CNodeOptions{
|
|
1845
1895
|
.permission_flags = permission_flags,
|
|
1846
1896
|
.prefer_evict = discouraged,
|
|
1897
|
+
.forced_inbound = forced,
|
|
1847
1898
|
.recv_flood_size = nReceiveFloodSize,
|
|
1848
1899
|
.use_v2transport = use_v2transport,
|
|
1849
1900
|
});
|
|
@@ -1937,7 +1988,7 @@ void CConnman::DisconnectNodes()
|
|
|
1937
1988
|
// Add to reconnection list if appropriate. We don't reconnect right here, because
|
|
1938
1989
|
// the creation of a connection is a blocking operation (up to several seconds),
|
|
1939
1990
|
// and we don't want to hold up the socket handler thread for that long.
|
|
1940
|
-
if (network_active && pnode->m_transport->ShouldReconnectV1()) {
|
|
1991
|
+
if (network_active && pnode->m_transport->ShouldReconnectV1() && !DisableV1OnClearnet(pnode->addr.GetNetClass())) {
|
|
1941
1992
|
reconnections_to_add.push_back({
|
|
1942
1993
|
.addr_connect = pnode->addr,
|
|
1943
1994
|
.grant = std::move(pnode->grantOutbound),
|
|
@@ -1996,16 +2047,15 @@ void CConnman::NotifyNumConnectionsChanged()
|
|
|
1996
2047
|
}
|
|
1997
2048
|
}
|
|
1998
2049
|
|
|
1999
|
-
bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const
|
|
2050
|
+
bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::microseconds now) const
|
|
2000
2051
|
{
|
|
2001
2052
|
return node.m_connected + m_peer_connect_timeout < now;
|
|
2002
2053
|
}
|
|
2003
2054
|
|
|
2004
|
-
bool CConnman::InactivityCheck(const CNode& node) const
|
|
2055
|
+
bool CConnman::InactivityCheck(const CNode& node, std::chrono::microseconds now) const
|
|
2005
2056
|
{
|
|
2006
2057
|
// Tests that see disconnects after using mocktime can start nodes with a
|
|
2007
2058
|
// large timeout. For example, -peertimeout=999999999.
|
|
2008
|
-
const auto now{GetTime<std::chrono::seconds>()};
|
|
2009
2059
|
const auto last_send{node.m_last_send.load()};
|
|
2010
2060
|
const auto last_recv{node.m_last_recv.load()};
|
|
2011
2061
|
|
|
@@ -2029,7 +2079,7 @@ bool CConnman::InactivityCheck(const CNode& node) const
|
|
|
2029
2079
|
|
|
2030
2080
|
if (now > last_send + TIMEOUT_INTERVAL) {
|
|
2031
2081
|
LogDebug(BCLog::NET,
|
|
2032
|
-
"socket sending timeout: %is, %s\n", count_seconds(now - last_send),
|
|
2082
|
+
"socket sending timeout: %is, %s\n", Ticks<std::chrono::seconds>(now - last_send),
|
|
2033
2083
|
node.DisconnectMsg(fLogIPs)
|
|
2034
2084
|
);
|
|
2035
2085
|
return true;
|
|
@@ -2037,7 +2087,7 @@ bool CConnman::InactivityCheck(const CNode& node) const
|
|
|
2037
2087
|
|
|
2038
2088
|
if (now > last_recv + TIMEOUT_INTERVAL) {
|
|
2039
2089
|
LogDebug(BCLog::NET,
|
|
2040
|
-
"socket receive timeout: %is, %s\n", count_seconds(now - last_recv),
|
|
2090
|
+
"socket receive timeout: %is, %s\n", Ticks<std::chrono::seconds>(now - last_recv),
|
|
2041
2091
|
node.DisconnectMsg(fLogIPs)
|
|
2042
2092
|
);
|
|
2043
2093
|
return true;
|
|
@@ -2119,6 +2169,8 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
|
|
|
2119
2169
|
{
|
|
2120
2170
|
AssertLockNotHeld(m_total_bytes_sent_mutex);
|
|
2121
2171
|
|
|
2172
|
+
auto now = GetTime<std::chrono::microseconds>();
|
|
2173
|
+
|
|
2122
2174
|
for (CNode* pnode : nodes) {
|
|
2123
2175
|
if (interruptNet)
|
|
2124
2176
|
return;
|
|
@@ -2209,7 +2261,7 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
|
|
|
2209
2261
|
}
|
|
2210
2262
|
}
|
|
2211
2263
|
|
|
2212
|
-
if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
|
|
2264
|
+
if (InactivityCheck(*pnode, now)) pnode->fDisconnect = true;
|
|
2213
2265
|
}
|
|
2214
2266
|
}
|
|
2215
2267
|
|
|
@@ -2500,6 +2552,11 @@ bool CConnman::MultipleManualOrFullOutboundConns(Network net) const
|
|
|
2500
2552
|
return m_network_conn_counts[net] > 1;
|
|
2501
2553
|
}
|
|
2502
2554
|
|
|
2555
|
+
bool CConnman::DisableV1OnClearnet(Network net) const
|
|
2556
|
+
{
|
|
2557
|
+
return disable_v1conn_clearnet && (net == NET_IPV4 || net == NET_IPV6);
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2503
2560
|
bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
|
|
2504
2561
|
{
|
|
2505
2562
|
std::array<Network, 5> nets{NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS};
|
|
@@ -3052,6 +3109,8 @@ void CConnman::ThreadMessageHandler()
|
|
|
3052
3109
|
if (pnode->fDisconnect)
|
|
3053
3110
|
continue;
|
|
3054
3111
|
|
|
3112
|
+
CpuTimer timer{[&pnode](std::chrono::nanoseconds elapsed) { pnode->m_cpu_time += elapsed; }};
|
|
3113
|
+
|
|
3055
3114
|
// Receive messages
|
|
3056
3115
|
bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
|
|
3057
3116
|
fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
|
|
@@ -3289,7 +3348,29 @@ bool CConnman::InitBinds(const Options& options)
|
|
|
3289
3348
|
inaddr_any.s_addr = htonl(INADDR_ANY);
|
|
3290
3349
|
const CService ipv4_any{inaddr_any, GetListenPort()}; // 0.0.0.0
|
|
3291
3350
|
if (!Bind(ipv4_any, BF_REPORT_ERROR, NetPermissionFlags::None)) {
|
|
3292
|
-
return false;
|
|
3351
|
+
int defaultPort = Params().GetDefaultPort();
|
|
3352
|
+
// If listening failed and another port than the standard port was specified,
|
|
3353
|
+
// ask if the user wants to connect via the standard port for the network instead
|
|
3354
|
+
if (GetListenPort() != defaultPort) {
|
|
3355
|
+
bool fRet = uiInterface.ThreadSafeQuestion(
|
|
3356
|
+
strprintf(_("Do you want to use the standard network port for %s (port %s) instead?"), CLIENT_NAME, defaultPort),
|
|
3357
|
+
strprintf(_("Listen on port %s failed."), GetListenPort()).translated,
|
|
3358
|
+
"", CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL | CClientUIInterface::BTN_OK | CClientUIInterface::BTN_ABORT);
|
|
3359
|
+
|
|
3360
|
+
if (fRet) {
|
|
3361
|
+
// FIXME: Unbind IPv6 on the other port
|
|
3362
|
+
|
|
3363
|
+
gArgs.ForceSetArg("-port", defaultPort);
|
|
3364
|
+
// Attempt to use standard port
|
|
3365
|
+
struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
|
|
3366
|
+
Bind(CService(inaddr6_any, defaultPort), BF_NONE, NetPermissionFlags::None);
|
|
3367
|
+
struct in_addr inaddr_any;
|
|
3368
|
+
inaddr_any.s_addr = INADDR_ANY;
|
|
3369
|
+
if (!Bind(CService(inaddr_any, defaultPort), BF_REPORT_ERROR, NetPermissionFlags::None)) {
|
|
3370
|
+
return false;
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3293
3374
|
}
|
|
3294
3375
|
}
|
|
3295
3376
|
return true;
|
|
@@ -3460,6 +3541,8 @@ void CConnman::StopThreads()
|
|
|
3460
3541
|
|
|
3461
3542
|
void CConnman::StopNodes()
|
|
3462
3543
|
{
|
|
3544
|
+
AssertLockNotHeld(m_reconnections_mutex);
|
|
3545
|
+
|
|
3463
3546
|
if (fAddressesInitialized) {
|
|
3464
3547
|
DumpAddresses();
|
|
3465
3548
|
fAddressesInitialized = false;
|
|
@@ -3487,6 +3570,7 @@ void CConnman::StopNodes()
|
|
|
3487
3570
|
DeleteNode(pnode);
|
|
3488
3571
|
}
|
|
3489
3572
|
m_nodes_disconnected.clear();
|
|
3573
|
+
WITH_LOCK(m_reconnections_mutex, m_reconnections.clear());
|
|
3490
3574
|
vhListenSocket.clear();
|
|
3491
3575
|
semOutbound.reset();
|
|
3492
3576
|
semAddnode.reset();
|
|
@@ -3519,15 +3603,9 @@ std::vector<CAddress> CConnman::GetAddressesUnsafe(size_t max_addresses, size_t
|
|
|
3519
3603
|
std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct)
|
|
3520
3604
|
{
|
|
3521
3605
|
auto local_socket_bytes = requestor.addrBind.GetAddrBytes();
|
|
3522
|
-
uint64_t cache_id = GetDeterministicRandomizer(RANDOMIZER_ID_ADDRCACHE)
|
|
3523
|
-
.Write(requestor.ConnectedThroughNetwork())
|
|
3524
|
-
.Write(local_socket_bytes)
|
|
3525
|
-
// For outbound connections, the port of the bound address is randomly
|
|
3526
|
-
// assigned by the OS and would therefore not be useful for seeding.
|
|
3527
|
-
.Write(requestor.IsInboundConn() ? requestor.addrBind.GetPort() : 0)
|
|
3528
|
-
.Finalize();
|
|
3606
|
+
uint64_t network_id = requestor.m_network_key;
|
|
3529
3607
|
const auto current_time = GetTime<std::chrono::microseconds>();
|
|
3530
|
-
auto r = m_addr_response_caches.emplace(cache_id, CachedAddrResponse{});
|
|
3608
|
+
auto r = m_addr_response_caches.emplace(network_id, CachedAddrResponse{});
|
|
3531
3609
|
CachedAddrResponse& cache_entry = r.first->second;
|
|
3532
3610
|
if (cache_entry.m_cache_entry_expiration < current_time) { // If emplace() added new one it has expiration 0.
|
|
3533
3611
|
cache_entry.m_addrs_response_cache = GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt);
|
|
@@ -3563,12 +3641,17 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres
|
|
|
3563
3641
|
|
|
3564
3642
|
bool CConnman::AddNode(const AddedNodeParams& add)
|
|
3565
3643
|
{
|
|
3566
|
-
const CService resolved(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)));
|
|
3567
|
-
const bool resolved_is_valid{resolved.IsValid()};
|
|
3644
|
+
const CService resolved{MaybeFlipIPv6toCJDNS(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)))};
|
|
3645
|
+
const bool resolved_invalid{!resolved.IsValid()};
|
|
3568
3646
|
|
|
3569
3647
|
LOCK(m_added_nodes_mutex);
|
|
3570
3648
|
for (const auto& it : m_added_node_params) {
|
|
3571
|
-
if (add.m_added_node == it.m_added_node || (resolved_is_valid && resolved == LookupNumeric(it.m_added_node, GetDefaultPort(it.m_added_node)))) return false;
|
|
3649
|
+
if (add.m_added_node == it.m_added_node) return false;
|
|
3650
|
+
if (resolved_invalid) continue;
|
|
3651
|
+
const CService service{MaybeFlipIPv6toCJDNS(LookupNumeric(it.m_added_node, GetDefaultPort(it.m_added_node)))};
|
|
3652
|
+
if (resolved == service) return false;
|
|
3653
|
+
// Check if CJDNS address matches regardless of port to detect already-connected inbound peers.
|
|
3654
|
+
if (resolved.IsCJDNS() && static_cast<CNetAddr>(resolved) == static_cast<CNetAddr>(service)) return false;
|
|
3572
3655
|
}
|
|
3573
3656
|
|
|
3574
3657
|
m_added_node_params.push_back(add);
|
|
@@ -3804,6 +3887,7 @@ CNode::CNode(NodeId idIn,
|
|
|
3804
3887
|
const std::string& addrNameIn,
|
|
3805
3888
|
ConnectionType conn_type_in,
|
|
3806
3889
|
bool inbound_onion,
|
|
3890
|
+
uint64_t network_key,
|
|
3807
3891
|
CNodeOptions&& node_opts)
|
|
3808
3892
|
: m_transport{MakeTransport(idIn, node_opts.use_v2transport, conn_type_in == ConnectionType::INBOUND)},
|
|
3809
3893
|
m_permission_flags{node_opts.permission_flags},
|
|
@@ -3815,7 +3899,9 @@ CNode::CNode(NodeId idIn,
|
|
|
3815
3899
|
m_dest(addrNameIn),
|
|
3816
3900
|
m_inbound_onion{inbound_onion},
|
|
3817
3901
|
m_prefer_evict{node_opts.prefer_evict},
|
|
3902
|
+
m_forced_inbound{node_opts.forced_inbound},
|
|
3818
3903
|
nKeyedNetGroup{nKeyedNetGroupIn},
|
|
3904
|
+
m_network_key{network_key},
|
|
3819
3905
|
m_conn_type{conn_type_in},
|
|
3820
3906
|
id{idIn},
|
|
3821
3907
|
nLocalHostNonce{nLocalHostNonceIn},
|
|
@@ -3877,7 +3963,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
|
|
|
3877
3963
|
AssertLockNotHeld(m_total_bytes_sent_mutex);
|
|
3878
3964
|
size_t nMessageSize = msg.data.size();
|
|
3879
3965
|
LogDebug(BCLog::NET, "sending %s (%d bytes) peer=%d\n", msg.m_type, nMessageSize, pnode->GetId());
|
|
3880
|
-
if (gArgs.GetBoolArg("-capturemessages", false)) {
|
|
3966
|
+
if (m_capture_messages) {
|
|
3881
3967
|
CaptureMessage(pnode->addr, msg.m_type, msg.data, /*is_incoming=*/false);
|
|
3882
3968
|
}
|
|
3883
3969
|
|