Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-present The Bitcoin Core developers
3 : : // Distributed under the MIT software license, see the accompanying
4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 : :
6 : : #include <bitcoin-build-config.h> // IWYU pragma: keep
7 : :
8 : : #include <net.h>
9 : :
10 : : #include <addrdb.h>
11 : : #include <addrman.h>
12 : : #include <banman.h>
13 : : #include <clientversion.h>
14 : : #include <common/args.h>
15 : : #include <common/netif.h>
16 : : #include <compat/compat.h>
17 : : #include <consensus/consensus.h>
18 : : #include <crypto/sha256.h>
19 : : #include <i2p.h>
20 : : #include <key.h>
21 : : #include <logging.h>
22 : : #include <memusage.h>
23 : : #include <net_permissions.h>
24 : : #include <netaddress.h>
25 : : #include <netbase.h>
26 : : #include <node/eviction.h>
27 : : #include <node/interface_ui.h>
28 : : #include <protocol.h>
29 : : #include <random.h>
30 : : #include <scheduler.h>
31 : : #include <util/fs.h>
32 : : #include <util/sock.h>
33 : : #include <util/strencodings.h>
34 : : #include <util/thread.h>
35 : : #include <util/threadinterrupt.h>
36 : : #include <util/trace.h>
37 : : #include <util/translation.h>
38 : : #include <util/vector.h>
39 : :
40 : : #include <algorithm>
41 : : #include <array>
42 : : #include <cmath>
43 : : #include <cstdint>
44 : : #include <cstring>
45 : : #include <functional>
46 : : #include <optional>
47 : : #include <string_view>
48 : : #include <unordered_map>
49 : :
50 : : TRACEPOINT_SEMAPHORE(net, closed_connection);
51 : : TRACEPOINT_SEMAPHORE(net, evicted_inbound_connection);
52 : : TRACEPOINT_SEMAPHORE(net, inbound_connection);
53 : : TRACEPOINT_SEMAPHORE(net, outbound_connection);
54 : : TRACEPOINT_SEMAPHORE(net, outbound_message);
55 : :
56 : : /** Maximum number of block-relay-only anchor connections */
57 : : static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS = 2;
58 : : static_assert (MAX_BLOCK_RELAY_ONLY_ANCHORS <= static_cast<size_t>(MAX_BLOCK_RELAY_ONLY_CONNECTIONS), "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
59 : : /** Anchor IP address database file name */
60 : : const char* const ANCHORS_DATABASE_FILENAME = "anchors.dat";
61 : :
62 : : // How often to dump addresses to peers.dat
63 : : static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15};
64 : :
65 : : /** Number of DNS seeds to query when the number of connections is low. */
66 : : static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
67 : :
68 : : /** Minimum number of outbound connections under which we will keep fetching our address seeds. */
69 : : static constexpr int SEED_OUTBOUND_CONNECTION_THRESHOLD = 2;
70 : :
71 : : /** How long to delay before querying DNS seeds
72 : : *
73 : : * If we have more than THRESHOLD entries in addrman, then it's likely
74 : : * that we got those addresses from having previously connected to the P2P
75 : : * network, and that we'll be able to successfully reconnect to the P2P
76 : : * network via contacting one of them. So if that's the case, spend a
77 : : * little longer trying to connect to known peers before querying the
78 : : * DNS seeds.
79 : : */
80 : : static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11};
81 : : static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS{5};
82 : : static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers
83 : :
84 : : /** The default timeframe for -maxuploadtarget. 1 day. */
85 : : static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME{60 * 60 * 24};
86 : :
87 : : // A random time period (0 to 1 seconds) is added to feeler connections to prevent synchronization.
88 : : static constexpr auto FEELER_SLEEP_WINDOW{1s};
89 : :
90 : : /** Frequency to attempt extra connections to reachable networks we're not connected to yet **/
91 : : static constexpr auto EXTRA_NETWORK_PEER_INTERVAL{5min};
92 : :
93 : : /** Used to pass flags to the Bind() function */
94 : : enum BindFlags {
95 : : BF_NONE = 0,
96 : : BF_REPORT_ERROR = (1U << 0),
97 : : /**
98 : : * Do not call AddLocal() for our special addresses, e.g., for incoming
99 : : * Tor connections, to prevent gossiping them over the network.
100 : : */
101 : : BF_DONT_ADVERTISE = (1U << 1),
102 : : };
103 : :
104 : : // The set of sockets cannot be modified while waiting
105 : : // The sleep time needs to be small to avoid new sockets stalling
106 : : static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
107 : :
108 : : const std::string NET_MESSAGE_TYPE_OTHER = "*other*";
109 : :
110 : : static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
111 : : static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
112 : : static const uint64_t RANDOMIZER_ID_NETWORKKEY = 0x0e8a2b136c592a7dULL; // SHA256("networkkey")[0:8]
113 : : //
114 : : // Global state variables
115 : : //
116 : : bool fDiscover = true;
117 : : bool fListen = true;
118 : : GlobalMutex g_maplocalhost_mutex;
119 : : std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(g_maplocalhost_mutex);
120 : : std::string strSubVersion;
121 : :
122 : 612673 : size_t CSerializedNetMsg::GetMemoryUsage() const noexcept
123 : : {
124 [ - + ]: 612673 : return sizeof(*this) + memusage::DynamicUsage(m_type) + memusage::DynamicUsage(data);
125 : : }
126 : :
127 : 195782 : size_t CNetMessage::GetMemoryUsage() const noexcept
128 : : {
129 : 195782 : return sizeof(*this) + memusage::DynamicUsage(m_type) + m_recv.GetMemoryUsage();
130 : : }
131 : :
132 : 0 : void CConnman::AddAddrFetch(const std::string& strDest)
133 : : {
134 : 0 : LOCK(m_addr_fetches_mutex);
135 [ # # ]: 0 : m_addr_fetches.push_back(strDest);
136 : 0 : }
137 : :
138 : 94194 : uint16_t GetListenPort()
139 : : {
140 : : // If -bind= is provided with ":port" part, use that (first one if multiple are provided).
141 [ + - - + ]: 94194 : for (const std::string& bind_arg : gArgs.GetArgs("-bind")) {
142 : 0 : constexpr uint16_t dummy_port = 0;
143 : :
144 [ # # # # ]: 0 : const std::optional<CService> bind_addr{Lookup(bind_arg, dummy_port, /*fAllowLookup=*/false)};
145 [ # # # # : 0 : if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port) return bind_addr->GetPort();
# # # # ]
146 : 94194 : }
147 : :
148 : : // Otherwise, if -whitebind= without NetPermissionFlags::NoBan is provided, use that
149 : : // (-whitebind= is required to have ":port").
150 [ + - - + ]: 94194 : for (const std::string& whitebind_arg : gArgs.GetArgs("-whitebind")) {
151 [ # # ]: 0 : NetWhitebindPermissions whitebind;
152 [ # # ]: 0 : bilingual_str error;
153 [ # # # # ]: 0 : if (NetWhitebindPermissions::TryParse(whitebind_arg, whitebind, error)) {
154 [ # # ]: 0 : if (!NetPermissions::HasFlag(whitebind.m_flags, NetPermissionFlags::NoBan)) {
155 [ # # ]: 0 : return whitebind.m_service.GetPort();
156 : : }
157 : : }
158 : 0 : }
159 : :
160 : : // Otherwise, if -port= is provided, use that. Otherwise use the default port.
161 : 188388 : return static_cast<uint16_t>(gArgs.GetIntArg("-port", Params().GetDefaultPort()));
162 : : }
163 : :
164 : : // Determine the "best" local address for a particular peer.
165 : 92892 : [[nodiscard]] static std::optional<CService> GetLocal(const CNode& peer)
166 : : {
167 [ - + ]: 92892 : if (!fListen) return std::nullopt;
168 : :
169 : 92892 : std::optional<CService> addr;
170 : 92892 : int nBestScore = -1;
171 : 92892 : int nBestReachability = -1;
172 : 92892 : {
173 [ + - ]: 92892 : LOCK(g_maplocalhost_mutex);
174 [ + - + + ]: 11942492 : for (const auto& [local_addr, local_service_info] : mapLocalHost) {
175 : : // For privacy reasons, don't advertise our privacy-network address
176 : : // to other networks and don't advertise our other-network address
177 : : // to privacy networks.
178 [ + - + - ]: 11849600 : if (local_addr.GetNetwork() != peer.ConnectedThroughNetwork()
179 [ + + + - : 20487023 : && (local_addr.IsPrivacyNet() || peer.IsConnectedThroughPrivacyNet())) {
+ + ]
180 : 2837833 : continue;
181 : : }
182 : 9011767 : const int nScore{local_service_info.nScore};
183 [ + - ]: 9011767 : const int nReachability{local_addr.GetReachabilityFrom(peer.addr)};
184 [ + + + + ]: 9011767 : if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) {
185 [ + - ]: 206725 : addr.emplace(CService{local_addr, local_service_info.nPort});
186 : 206725 : nBestReachability = nReachability;
187 : 206725 : nBestScore = nScore;
188 : : }
189 : : }
190 : 0 : }
191 [ + + ]: 162141 : return addr;
192 : 92892 : }
193 : :
194 : : //! Convert the serialized seeds into usable address objects.
195 : 0 : static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
196 : : {
197 : : // It'll only connect to one or two seed nodes because once it connects,
198 : : // it'll get a pile of addresses with newer timestamps.
199 : : // Seed nodes are given a random 'last seen time' of between one and two
200 : : // weeks ago.
201 : 0 : const auto one_week{7 * 24h};
202 : 0 : std::vector<CAddress> vSeedsOut;
203 : 0 : FastRandomContext rng;
204 [ # # ]: 0 : ParamsStream s{SpanReader{vSeedsIn}, CAddress::V2_NETWORK};
205 [ # # ]: 0 : while (!s.empty()) {
206 [ # # ]: 0 : CService endpoint;
207 [ # # ]: 0 : s >> endpoint;
208 : 0 : CAddress addr{endpoint, SeedsServiceFlags()};
209 : 0 : addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - one_week, -one_week);
210 [ # # # # : 0 : LogDebug(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToStringAddrPort());
# # # # ]
211 [ # # ]: 0 : vSeedsOut.push_back(addr);
212 : 0 : }
213 : 0 : return vSeedsOut;
214 : 0 : }
215 : :
216 : : // Determine the "best" local address for a particular peer.
217 : : // If none, return the unroutable 0.0.0.0 but filled in with
218 : : // the normal parameters, since the IP may be changed to a useful
219 : : // one by discovery.
220 : 92892 : CService GetLocalAddress(const CNode& peer)
221 : : {
222 [ + - + - : 92892 : return GetLocal(peer).value_or(CService{CNetAddr(), GetListenPort()});
+ - ]
223 : : }
224 : :
225 : 0 : static int GetnScore(const CService& addr)
226 : : {
227 : 0 : LOCK(g_maplocalhost_mutex);
228 [ # # ]: 0 : const auto it = mapLocalHost.find(addr);
229 [ # # ]: 0 : return (it != mapLocalHost.end()) ? it->second.nScore : 0;
230 : 0 : }
231 : :
232 : : // Is our peer's addrLocal potentially useful as an external IP source?
233 : 0 : [[nodiscard]] static bool IsPeerAddrLocalGood(CNode *pnode)
234 : : {
235 : 0 : CService addrLocal = pnode->GetAddrLocal();
236 [ # # # # : 0 : return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
# # # # #
# # # ]
237 [ # # ]: 0 : g_reachable_nets.Contains(addrLocal);
238 : 0 : }
239 : :
240 : 0 : std::optional<CService> GetLocalAddrForPeer(CNode& node)
241 : : {
242 : 0 : CService addrLocal{GetLocalAddress(node)};
243 : : // If discovery is enabled, sometimes give our peer the address it
244 : : // tells us that it sees us as in case it has a better idea of our
245 : : // address than we do.
246 : 0 : FastRandomContext rng;
247 [ # # # # : 0 : if (IsPeerAddrLocalGood(&node) && (!addrLocal.IsRoutable() ||
# # # # #
# ]
248 [ # # # # ]: 0 : rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0))
249 : : {
250 [ # # ]: 0 : if (node.IsInboundConn()) {
251 : : // For inbound connections, assume both the address and the port
252 : : // as seen from the peer.
253 [ # # ]: 0 : addrLocal = CService{node.GetAddrLocal()};
254 : : } else {
255 : : // For outbound connections, assume just the address as seen from
256 : : // the peer and leave the port in `addrLocal` as returned by
257 : : // `GetLocalAddress()` above. The peer has no way to observe our
258 : : // listening port when we have initiated the connection.
259 [ # # # # ]: 0 : addrLocal.SetIP(node.GetAddrLocal());
260 : : }
261 : : }
262 [ # # # # ]: 0 : if (addrLocal.IsRoutable()) {
263 [ # # # # : 0 : LogDebug(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToStringAddrPort(), node.GetId());
# # # # ]
264 : 0 : return addrLocal;
265 : : }
266 : : // Address is unroutable. Don't advertise.
267 : 0 : return std::nullopt;
268 : 0 : }
269 : :
270 : 1236 : void ClearLocal()
271 : : {
272 : 1236 : LOCK(g_maplocalhost_mutex);
273 [ + - ]: 1236 : return mapLocalHost.clear();
274 : 1236 : }
275 : :
276 : : // learn a new local address
277 : 185078 : bool AddLocal(const CService& addr_, int nScore)
278 : : {
279 : 185078 : CService addr{MaybeFlipIPv6toCJDNS(addr_)};
280 : :
281 [ + - + + ]: 185078 : if (!addr.IsRoutable())
282 : : return false;
283 : :
284 [ - + - - ]: 139007 : if (!fDiscover && nScore < LOCAL_MANUAL)
285 : : return false;
286 : :
287 [ + - + - ]: 139007 : if (!g_reachable_nets.Contains(addr))
288 : : return false;
289 : :
290 [ - + ]: 139007 : if (fLogIPs) {
291 [ # # # # ]: 0 : LogInfo("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
292 : : }
293 : :
294 : 139007 : {
295 [ + - ]: 139007 : LOCK(g_maplocalhost_mutex);
296 [ + - + + ]: 139007 : const auto [it, is_newly_added] = mapLocalHost.emplace(addr, LocalServiceInfo());
297 [ + + ]: 139007 : LocalServiceInfo &info = it->second;
298 [ + + + + ]: 139007 : if (is_newly_added || nScore >= info.nScore) {
299 [ + + ]: 59691 : info.nScore = nScore + (is_newly_added ? 0 : 1);
300 [ + - ]: 59691 : info.nPort = addr.GetPort();
301 : : }
302 : 0 : }
303 : :
304 : 139007 : return true;
305 : 185078 : }
306 : :
307 : 0 : bool AddLocal(const CNetAddr &addr, int nScore)
308 : : {
309 [ # # ]: 0 : return AddLocal(CService(addr, GetListenPort()), nScore);
310 : : }
311 : :
312 : 49164 : void RemoveLocal(const CService& addr)
313 : : {
314 : 49164 : LOCK(g_maplocalhost_mutex);
315 [ - + ]: 49164 : if (fLogIPs) {
316 [ # # # # ]: 0 : LogInfo("RemoveLocal(%s)\n", addr.ToStringAddrPort());
317 : : }
318 : :
319 [ + - + - ]: 49164 : mapLocalHost.erase(addr);
320 : 49164 : }
321 : :
322 : : /** vote for a local address */
323 : 180326 : bool SeenLocal(const CService& addr)
324 : : {
325 : 180326 : LOCK(g_maplocalhost_mutex);
326 [ + - ]: 180326 : const auto it = mapLocalHost.find(addr);
327 [ + + ]: 180326 : if (it == mapLocalHost.end()) return false;
328 : 161863 : ++it->second.nScore;
329 : 161863 : return true;
330 : 180326 : }
331 : :
332 : :
333 : : /** check whether a given address is potentially local */
334 : 147582 : bool IsLocal(const CService& addr)
335 : : {
336 : 147582 : LOCK(g_maplocalhost_mutex);
337 [ + - + - ]: 147582 : return mapLocalHost.contains(addr);
338 : 147582 : }
339 : :
340 : 16771 : bool CConnman::AlreadyConnectedToHost(std::string_view host) const
341 : : {
342 : 16771 : LOCK(m_nodes_mutex);
343 [ + - - + ]: 1995668 : return std::ranges::any_of(m_nodes, [&host](CNode* node) { return node->m_addr_name == host; });
344 : 16771 : }
345 : :
346 : 3247 : bool CConnman::AlreadyConnectedToAddressPort(const CService& addr_port) const
347 : : {
348 : 3247 : LOCK(m_nodes_mutex);
349 [ + - + - ]: 60822 : return std::ranges::any_of(m_nodes, [&addr_port](CNode* node) { return node->addr == addr_port; });
350 : 3247 : }
351 : :
352 : 1704 : bool CConnman::AlreadyConnectedToAddress(const CNetAddr& addr) const
353 : : {
354 : 1704 : LOCK(m_nodes_mutex);
355 [ + - + - ]: 51714 : return std::ranges::any_of(m_nodes, [&addr](CNode* node) { return node->addr == addr; });
356 : 1704 : }
357 : :
358 : 28846 : bool CConnman::CheckIncomingNonce(uint64_t nonce)
359 : : {
360 : 28846 : LOCK(m_nodes_mutex);
361 [ + + ]: 1715444 : for (const CNode* pnode : m_nodes) {
362 : : // Omit private broadcast connections from this check to prevent this privacy attack:
363 : : // - We connect to a peer in an attempt to privately broadcast a transaction. From our
364 : : // VERSION message the peer deducts that this is a short-lived connection for
365 : : // broadcasting a transaction, takes our nonce and delays their VERACK.
366 : : // - The peer starts connecting to (clearnet) nodes and sends them a VERSION message
367 : : // which contains our nonce. If the peer manages to connect to us we would disconnect.
368 : : // - Upon a disconnect, the peer knows our clearnet address. They go back to the short
369 : : // lived privacy broadcast connection and continue with VERACK.
370 [ + + + + : 1686740 : if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && !pnode->IsPrivateBroadcastConn() &&
+ + ]
371 [ + + ]: 101504 : pnode->GetLocalNonce() == nonce)
372 : : return false;
373 : : }
374 : : return true;
375 : 28846 : }
376 : :
377 : 17952 : CNode* CConnman::ConnectNode(CAddress addrConnect,
378 : : const char* pszDest,
379 : : bool fCountFailure,
380 : : ConnectionType conn_type,
381 : : bool use_v2transport,
382 : : const std::optional<Proxy>& proxy_override)
383 : : {
384 : 17952 : AssertLockNotHeld(m_nodes_mutex);
385 : 17952 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
386 [ - + ]: 17952 : assert(conn_type != ConnectionType::INBOUND);
387 : :
388 [ + + ]: 17952 : if (pszDest == nullptr) {
389 [ + - ]: 1317 : if (IsLocal(addrConnect))
390 : : return nullptr;
391 : :
392 : : // Look for an existing connection
393 [ - + ]: 1317 : if (AlreadyConnectedToAddressPort(addrConnect)) {
394 [ # # ]: 0 : LogInfo("Failed to open new connection to %s, already connected", addrConnect.ToStringAddrPort());
395 : 0 : return nullptr;
396 : : }
397 : : }
398 : :
399 [ - + - - : 17952 : LogDebug(BCLog::NET, "trying %s connection (%s) to %s, lastseen=%.1fhrs\n",
- - - - -
- - - ]
400 : : use_v2transport ? "v2" : "v1",
401 : : ConnectionTypeAsString(conn_type),
402 : : pszDest ? pszDest : addrConnect.ToStringAddrPort(),
403 : : Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.nTime));
404 : :
405 : : // Resolve
406 [ + + + - ]: 34587 : const uint16_t default_port{pszDest != nullptr ? GetDefaultPort(pszDest) :
407 : 1317 : m_params.GetDefaultPort()};
408 : :
409 : : // Collection of addresses to try to connect to: either all dns resolved addresses if a domain name (pszDest) is provided, or addrConnect otherwise.
410 : 17952 : std::vector<CAddress> connect_to{};
411 [ + + ]: 17952 : if (pszDest) {
412 [ + - + - : 33270 : std::vector<CService> resolved{Lookup(pszDest, default_port, fNameLookup && !HaveNameProxy(), 256)};
+ - - + +
- + - ]
413 [ + + ]: 16635 : if (!resolved.empty()) {
414 : 1954 : std::shuffle(resolved.begin(), resolved.end(), FastRandomContext());
415 : : // If the connection is made by name, it can be the case that the name resolves to more than one address.
416 : : // We don't want to connect any more of them if we are already connected to one
417 [ + + ]: 3758 : for (const auto& r : resolved) {
418 [ + - ]: 3908 : addrConnect = CAddress{MaybeFlipIPv6toCJDNS(r), NODE_NONE};
419 [ + - + + ]: 1954 : if (!addrConnect.IsValid()) {
420 [ + - - + : 24 : LogDebug(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToStringAddrPort(), pszDest);
- - - - ]
421 : 24 : return nullptr;
422 : : }
423 : : // It is possible that we already have a connection to the IP/port pszDest resolved to.
424 : : // In that case, drop the connection that was just created.
425 [ + - + + ]: 1930 : if (AlreadyConnectedToAddressPort(addrConnect)) {
426 [ + - + - ]: 126 : LogInfo("Not opening a connection to %s, already connected to %s\n", pszDest, addrConnect.ToStringAddrPort());
427 : 126 : return nullptr;
428 : : }
429 : : // Add the address to the resolved addresses vector so we can try to connect to it later on
430 [ + - ]: 1804 : connect_to.push_back(addrConnect);
431 : : }
432 : : } else {
433 : : // For resolution via proxy
434 [ + - ]: 14681 : connect_to.push_back(addrConnect);
435 : : }
436 : 16635 : } else {
437 : : // Connect via addrConnect directly
438 [ + - ]: 1317 : connect_to.push_back(addrConnect);
439 : : }
440 : :
441 : : // Connect
442 : 17802 : std::unique_ptr<Sock> sock;
443 [ + - ]: 17802 : CService addr_bind;
444 [ + - - + ]: 17802 : assert(!addr_bind.IsValid());
445 : 17802 : std::unique_ptr<i2p::sam::Session> i2p_transient_session;
446 : :
447 [ + + ]: 21393 : for (auto& target_addr : connect_to) {
448 [ + - + + ]: 17802 : if (target_addr.IsValid()) {
449 [ - + ]: 16835 : const std::optional<Proxy> use_proxy{
450 [ - + ]: 16835 : proxy_override.has_value() ? proxy_override : GetProxy(target_addr.GetNetwork()),
451 [ + - + - ]: 16835 : };
452 : 16835 : bool proxyConnectionFailed = false;
453 : :
454 [ + + + - ]: 16835 : if (target_addr.IsI2P() && use_proxy) {
455 [ # # ]: 0 : i2p::Connection conn;
456 : 0 : bool connected{false};
457 : :
458 : : // If an I2P SAM session already exists, normally we would re-use it. But in the case of
459 : : // private broadcast we force a new transient session. A Connect() using m_i2p_sam_session
460 : : // would use our permanent I2P address as a source address.
461 [ # # # # ]: 0 : if (m_i2p_sam_session && conn_type != ConnectionType::PRIVATE_BROADCAST) {
462 [ # # ]: 0 : connected = m_i2p_sam_session->Connect(target_addr, conn, proxyConnectionFailed);
463 : : } else {
464 : 0 : {
465 [ # # ]: 0 : LOCK(m_unused_i2p_sessions_mutex);
466 [ # # ]: 0 : if (m_unused_i2p_sessions.empty()) {
467 : 0 : i2p_transient_session =
468 [ # # ]: 0 : std::make_unique<i2p::sam::Session>(*use_proxy, m_interrupt_net);
469 : : } else {
470 : 0 : i2p_transient_session.swap(m_unused_i2p_sessions.front());
471 : 0 : m_unused_i2p_sessions.pop();
472 : : }
473 : 0 : }
474 [ # # ]: 0 : connected = i2p_transient_session->Connect(target_addr, conn, proxyConnectionFailed);
475 [ # # ]: 0 : if (!connected) {
476 [ # # ]: 0 : LOCK(m_unused_i2p_sessions_mutex);
477 [ # # # # ]: 0 : if (m_unused_i2p_sessions.size() < MAX_UNUSED_I2P_SESSIONS_SIZE) {
478 [ # # # # ]: 0 : m_unused_i2p_sessions.emplace(i2p_transient_session.release());
479 : : }
480 : 0 : }
481 : : }
482 : :
483 [ # # ]: 0 : if (connected) {
484 : 0 : sock = std::move(conn.sock);
485 : 0 : addr_bind = conn.me;
486 : : }
487 [ - + ]: 16835 : } else if (use_proxy) {
488 [ # # # # : 0 : LogDebug(BCLog::PROXY, "Using proxy: %s to connect to %s\n", use_proxy->ToString(), target_addr.ToStringAddrPort());
# # # # #
# ]
489 [ # # # # : 0 : sock = ConnectThroughProxy(*use_proxy, target_addr.ToStringAddr(), target_addr.GetPort(), proxyConnectionFailed);
# # ]
490 : : } else {
491 : : // no proxy needed (none set for target network)
492 [ + - ]: 33670 : sock = ConnectDirectly(target_addr, conn_type == ConnectionType::MANUAL);
493 : : }
494 [ + - ]: 16835 : if (!proxyConnectionFailed) {
495 : : // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
496 : : // the proxy, mark this as an attempt.
497 [ + - ]: 16835 : addrman.get().Attempt(target_addr, fCountFailure);
498 : : }
499 [ + + ]: 17802 : } else if (pszDest) {
500 [ + - - + ]: 135 : if (const auto name_proxy = GetNameProxy()) {
501 [ # # ]: 0 : std::string host;
502 : 0 : uint16_t port{default_port};
503 [ # # ]: 0 : SplitHostPort(pszDest, port, host);
504 : 0 : bool proxyConnectionFailed;
505 [ # # ]: 0 : sock = ConnectThroughProxy(*name_proxy, host, port, proxyConnectionFailed);
506 : 135 : }
507 : : }
508 : : // Check any other resolved address (if any) if we fail to connect
509 [ + + ]: 17802 : if (!sock) {
510 : 3591 : continue;
511 : : }
512 : :
513 : 14211 : NetPermissionFlags permission_flags = NetPermissionFlags::None;
514 [ + + + - ]: 14211 : std::vector<NetWhitelistPermissions> whitelist_permissions = conn_type == ConnectionType::MANUAL ? vWhitelistedRangeOutgoing : std::vector<NetWhitelistPermissions>{};
515 [ + - ]: 14211 : AddWhitelistPermissionFlags(permission_flags, target_addr, whitelist_permissions);
516 : :
517 : : // Add node
518 [ + - ]: 14211 : NodeId id = GetNewNodeId();
519 [ + - + - : 14211 : uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
+ - ]
520 [ + - + - ]: 14211 : if (!addr_bind.IsValid()) {
521 [ + - ]: 28422 : addr_bind = GetBindAddress(*sock);
522 : : }
523 [ + - ]: 14211 : uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)
524 [ + - + - ]: 14211 : .Write(target_addr.GetNetClass())
525 [ + - + - ]: 28422 : .Write(addr_bind.GetAddrBytes())
526 : : // For outbound connections, the port of the bound address is randomly
527 : : // assigned by the OS and would therefore not be useful for seeding.
528 [ + - ]: 14211 : .Write(0)
529 [ + - ]: 14211 : .Finalize();
530 : 14211 : CNode* pnode = new CNode(id,
531 : 14211 : std::move(sock),
532 : : target_addr,
533 : : CalculateKeyedNetGroup(target_addr),
534 : : nonce,
535 : : addr_bind,
536 [ + - ]: 28422 : pszDest ? pszDest : "",
537 : : conn_type,
538 : : /*inbound_onion=*/false,
539 : : network_id,
540 [ + + ]: 14211 : CNodeOptions{
541 : : .permission_flags = permission_flags,
542 : : .i2p_sam_session = std::move(i2p_transient_session),
543 [ + + ]: 14211 : .recv_flood_size = nReceiveFloodSize,
544 : : .use_v2transport = use_v2transport,
545 [ + - + - : 28422 : });
+ - + - +
- ]
546 : 14211 : pnode->AddRef();
547 : :
548 : : // We're making a new connection, harvest entropy from the time (and our peer count)
549 : 14211 : RandAddEvent((uint32_t)id);
550 : :
551 : 14211 : return pnode;
552 : 14211 : }
553 : :
554 : : return nullptr;
555 : 17952 : }
556 : :
557 : 38936 : void CNode::CloseSocketDisconnect()
558 : : {
559 : 38936 : fDisconnect = true;
560 : 38936 : LOCK(m_sock_mutex);
561 [ + + ]: 38936 : if (m_sock) {
562 [ + - - + : 18082 : LogDebug(BCLog::NET, "Resetting socket for %s", LogPeer());
- - - - ]
563 : 18082 : m_sock.reset();
564 : :
565 : : TRACEPOINT(net, closed_connection,
566 : : GetId(),
567 : : m_addr_name.c_str(),
568 : : ConnectionTypeAsString().c_str(),
569 : : ConnectedThroughNetwork(),
570 : 18082 : TicksSinceEpoch<std::chrono::seconds>(m_connected));
571 : : }
572 [ - + + - ]: 38936 : m_i2p_sam_session.reset();
573 : 38936 : }
574 : :
575 : 53747 : void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optional<CNetAddr> addr, const std::vector<NetWhitelistPermissions>& ranges) const {
576 [ + + ]: 115919 : for (const auto& subnet : ranges) {
577 [ + - + + ]: 62172 : if (addr.has_value() && subnet.m_subnet.Match(addr.value())) {
578 : 619 : NetPermissions::AddFlag(flags, subnet.m_flags);
579 : : }
580 : : }
581 [ + + ]: 53747 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Implicit)) {
582 [ - + ]: 325 : NetPermissions::ClearFlag(flags, NetPermissionFlags::Implicit);
583 [ - + ]: 325 : if (whitelist_forcerelay) NetPermissions::AddFlag(flags, NetPermissionFlags::ForceRelay);
584 [ + - ]: 325 : if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
585 : 325 : NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
586 : 325 : NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
587 : : }
588 : 53747 : }
589 : :
590 : 201063 : CService CNode::GetAddrLocal() const
591 : : {
592 : 201063 : AssertLockNotHeld(m_addr_local_mutex);
593 : 201063 : LOCK(m_addr_local_mutex);
594 [ + - ]: 201063 : return m_addr_local;
595 : 201063 : }
596 : :
597 : 10897 : void CNode::SetAddrLocal(const CService& addrLocalIn) {
598 : 10897 : AssertLockNotHeld(m_addr_local_mutex);
599 : 10897 : LOCK(m_addr_local_mutex);
600 [ + - + - : 21794 : if (Assume(!m_addr_local.IsValid())) { // Addr local can only be set once during version msg processing
+ - ]
601 : 10897 : m_addr_local = addrLocalIn;
602 : : }
603 : 10897 : }
604 : :
605 : 15078994 : Network CNode::ConnectedThroughNetwork() const
606 : : {
607 [ + + ]: 15078994 : return m_inbound_onion ? NET_ONION : addr.GetNetClass();
608 : : }
609 : :
610 : 8637423 : bool CNode::IsConnectedThroughPrivacyNet() const
611 : : {
612 [ + + + + ]: 8637423 : return m_inbound_onion || addr.IsPrivacyNet();
613 : : }
614 : :
615 : : #undef X
616 : : #define X(name) stats.name = name
617 : 199821 : void CNode::CopyStats(CNodeStats& stats)
618 : : {
619 : 199821 : stats.nodeid = this->GetId();
620 : 199821 : X(addr);
621 : 199821 : X(addrBind);
622 : 199821 : stats.m_network = ConnectedThroughNetwork();
623 : 199821 : X(m_last_send);
624 : 199821 : X(m_last_recv);
625 : 199821 : X(m_last_tx_time);
626 : 199821 : X(m_last_block_time);
627 : 199821 : X(m_connected);
628 : 199821 : X(m_addr_name);
629 : 199821 : X(nVersion);
630 : 199821 : {
631 : 199821 : LOCK(m_subver_mutex);
632 [ + - + - ]: 399642 : X(cleanSubVer);
633 : 0 : }
634 : 199821 : stats.fInbound = IsInboundConn();
635 : 199821 : X(m_bip152_highbandwidth_to);
636 : 199821 : X(m_bip152_highbandwidth_from);
637 : 199821 : {
638 : 199821 : LOCK(cs_vSend);
639 [ + - ]: 199821 : X(mapSendBytesPerMsgType);
640 [ + - ]: 199821 : X(nSendBytes);
641 : 0 : }
642 : 199821 : {
643 : 199821 : LOCK(cs_vRecv);
644 [ + - ]: 199821 : X(mapRecvBytesPerMsgType);
645 : 199821 : X(nRecvBytes);
646 : 199821 : Transport::Info info = m_transport->GetInfo();
647 : 199821 : stats.m_transport_type = info.transport_type;
648 [ - + - - ]: 199821 : if (info.session_id) stats.m_session_id = HexStr(*info.session_id);
649 : 0 : }
650 : 199821 : X(m_permission_flags);
651 : :
652 : 199821 : X(m_last_ping_time);
653 : 199821 : X(m_min_ping_time);
654 : :
655 : : // Leave string empty if addrLocal invalid (not filled in yet)
656 : 199821 : CService addrLocalUnlocked = GetAddrLocal();
657 [ + - + + : 199821 : stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
+ - + - ]
658 : :
659 : 199821 : X(m_conn_type);
660 : 199821 : }
661 : : #undef X
662 : :
663 : 287193 : bool CNode::ReceiveMsgBytes(std::span<const uint8_t> msg_bytes, bool& complete)
664 : : {
665 : 287193 : complete = false;
666 : 287193 : const auto time{NodeClock::now()};
667 : 287193 : LOCK(cs_vRecv);
668 : 287193 : m_last_recv = time;
669 : 287193 : nRecvBytes += msg_bytes.size();
670 [ + + ]: 877501 : while (msg_bytes.size() > 0) {
671 : : // absorb network data
672 [ + - + + ]: 349795 : if (!m_transport->ReceivedBytes(msg_bytes)) {
673 : : // Serious transport problem, disconnect from the peer.
674 : : return false;
675 : : }
676 : :
677 [ + - + + ]: 303115 : if (m_transport->ReceivedMessageComplete()) {
678 : : // decompose a transport agnostic CNetMessage from the deserializer
679 : 174956 : bool reject_message{false};
680 [ + - ]: 174956 : CNetMessage msg = m_transport->GetReceivedMessage(time, reject_message);
681 [ + + ]: 174956 : if (reject_message) {
682 : : // Message deserialization failed. Drop the message but don't disconnect the peer.
683 : : // store the size of the corrupt message
684 [ + - ]: 51120 : mapRecvBytesPerMsgType.at(NET_MESSAGE_TYPE_OTHER) += msg.m_raw_message_size;
685 : 51120 : continue;
686 : : }
687 : :
688 : : // Store received bytes per message type.
689 : : // To prevent a memory DOS, only allow known message types.
690 : 123836 : auto i = mapRecvBytesPerMsgType.find(msg.m_type);
691 [ + + ]: 123836 : if (i == mapRecvBytesPerMsgType.end()) {
692 : 22279 : i = mapRecvBytesPerMsgType.find(NET_MESSAGE_TYPE_OTHER);
693 : : }
694 [ - + ]: 123836 : assert(i != mapRecvBytesPerMsgType.end());
695 [ + - ]: 123836 : i->second += msg.m_raw_message_size;
696 : :
697 : : // push the message to the process queue,
698 [ + - ]: 123836 : vRecvMsg.push_back(std::move(msg));
699 : :
700 : 123836 : complete = true;
701 : 174956 : }
702 : : }
703 : :
704 : : return true;
705 : 287193 : }
706 : :
707 : 5422 : std::string CNode::LogPeer() const
708 : : {
709 : 5422 : auto peer_info{strprintf("peer=%d", GetId())};
710 [ - + ]: 5422 : if (fLogIPs) {
711 [ # # # # ]: 0 : return strprintf("%s, peeraddr=%s", peer_info, addr.ToStringAddrPort());
712 : : } else {
713 : 5422 : return peer_info;
714 : : }
715 : 5422 : }
716 : :
717 : 65 : std::string CNode::DisconnectMsg() const
718 : : {
719 [ + - ]: 130 : return strprintf("disconnecting %s", LogPeer());
720 : : }
721 : :
722 : 99388 : V1Transport::V1Transport(const NodeId node_id) noexcept
723 : 99388 : : m_magic_bytes{Params().MessageStart()}, m_node_id{node_id}
724 : : {
725 : 99388 : LOCK(m_recv_mutex);
726 [ + - ]: 99388 : Reset();
727 : 99388 : }
728 : :
729 : 193022 : Transport::Info V1Transport::GetInfo() const noexcept
730 : : {
731 : 193022 : return {.transport_type = TransportProtocolType::V1, .session_id = {}};
732 : : }
733 : :
734 : 364639 : int V1Transport::readHeader(std::span<const uint8_t> msg_bytes)
735 : : {
736 : 364639 : AssertLockHeld(m_recv_mutex);
737 : : // copy data to temporary parsing buffer
738 : 364639 : unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos;
739 [ + + ]: 364639 : unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
740 : :
741 [ + + ]: 364639 : memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy);
742 : 364639 : nHdrPos += nCopy;
743 : :
744 : : // if header incomplete, exit
745 [ + + ]: 364639 : if (nHdrPos < CMessageHeader::HEADER_SIZE)
746 : 31129 : return nCopy;
747 : :
748 : : // deserialize to CMessageHeader
749 : 333510 : try {
750 [ + - ]: 333510 : hdrbuf >> hdr;
751 : : }
752 [ - - ]: 0 : catch (const std::exception&) {
753 [ - - - - : 0 : LogDebug(BCLog::NET, "Header error: Unable to deserialize, peer=%d\n", m_node_id);
- - ]
754 : 0 : return -1;
755 : 0 : }
756 : :
757 : : // Check start string, network magic
758 [ + + ]: 333510 : if (hdr.pchMessageStart != m_magic_bytes) {
759 [ - + - - ]: 35601 : LogDebug(BCLog::NET, "Header error: Wrong MessageStart %s received, peer=%d\n", HexStr(hdr.pchMessageStart), m_node_id);
760 : 35601 : return -1;
761 : : }
762 : :
763 : : // reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH
764 : : // NOTE: failing to perform this check previously allowed a malicious peer to make us allocate 32MiB of memory per
765 : : // connection. See https://bitcoincore.org/en/2024/07/03/disclose_receive_buffer_oom.
766 [ + + ]: 297909 : if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
767 [ - + - - : 10403 : LogDebug(BCLog::NET, "Header error: Size too large (%s, %u bytes), peer=%d\n", SanitizeString(hdr.GetMessageType()), hdr.nMessageSize, m_node_id);
- - - - ]
768 : 10403 : return -1;
769 : : }
770 : :
771 : : // switch state to reading message data
772 : 287506 : in_data = true;
773 : :
774 : 287506 : return nCopy;
775 : : }
776 : :
777 : 156351 : int V1Transport::readData(std::span<const uint8_t> msg_bytes)
778 : : {
779 : 156351 : AssertLockHeld(m_recv_mutex);
780 : 156351 : unsigned int nRemaining = hdr.nMessageSize - nDataPos;
781 [ + + ]: 156351 : unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
782 : :
783 [ - + + + ]: 156351 : if (vRecv.size() < nDataPos + nCopy) {
784 : : // Allocate up to 256 KiB ahead, but never more than the total message size.
785 [ + + ]: 261975 : vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
786 : : }
787 : :
788 : 156351 : hasher.Write(msg_bytes.first(nCopy));
789 : 156351 : memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy);
790 : 156351 : nDataPos += nCopy;
791 : :
792 : 156351 : return nCopy;
793 : : }
794 : :
795 : 287366 : const uint256& V1Transport::GetMessageHash() const
796 : : {
797 : 287366 : AssertLockHeld(m_recv_mutex);
798 [ + - - + ]: 287366 : assert(CompleteInternal());
799 [ + - ]: 574732 : if (data_hash.IsNull())
800 : 287366 : hasher.Finalize(data_hash);
801 : 287366 : return data_hash;
802 : : }
803 : :
804 : 287366 : CNetMessage V1Transport::GetReceivedMessage(NodeClock::time_point time, bool& reject_message)
805 : : {
806 : 287366 : AssertLockNotHeld(m_recv_mutex);
807 : : // Initialize out parameter
808 : 287366 : reject_message = false;
809 : : // decompose a single CNetMessage from the TransportDeserializer
810 : 287366 : LOCK(m_recv_mutex);
811 [ + - ]: 287366 : CNetMessage msg(std::move(vRecv));
812 : :
813 : : // store message type string, time, and sizes
814 [ + - ]: 287366 : msg.m_type = hdr.GetMessageType();
815 : 287366 : msg.m_time = time;
816 : 287366 : msg.m_message_size = hdr.nMessageSize;
817 : 287366 : msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
818 : :
819 [ + - ]: 287366 : uint256 hash = GetMessageHash();
820 : :
821 : : // We just received a message off the wire, harvest entropy from the time (and the message checksum)
822 : 287366 : RandAddEvent(ReadLE32(hash.begin()));
823 : :
824 : : // Check checksum and header message type string
825 [ + + ]: 287366 : if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) {
826 [ + - - + : 23333 : LogDebug(BCLog::NET, "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
- - - - -
- - - -
- ]
827 : : SanitizeString(msg.m_type), msg.m_message_size,
828 : : HexStr(std::span{hash}.first(CMessageHeader::CHECKSUM_SIZE)),
829 : : HexStr(hdr.pchChecksum),
830 : : m_node_id);
831 : 23333 : reject_message = true;
832 [ + - + + ]: 264033 : } else if (!hdr.IsMessageTypeValid()) {
833 [ + - - + : 89016 : LogDebug(BCLog::NET, "Header error: Invalid message type (%s, %u bytes), peer=%d\n",
- - - - -
- ]
834 : : SanitizeString(hdr.GetMessageType()), msg.m_message_size, m_node_id);
835 : 89016 : reject_message = true;
836 : : }
837 : :
838 : : // Always reset the network deserializer (prepare for the next message)
839 [ + - ]: 287366 : Reset();
840 [ + - ]: 287366 : return msg;
841 : 287366 : }
842 : :
843 : 448489 : bool V1Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
844 : : {
845 : 448489 : AssertLockNotHeld(m_send_mutex);
846 : : // Determine whether a new message can be set.
847 : 448489 : LOCK(m_send_mutex);
848 [ + + - + : 448489 : if (m_sending_header || m_bytes_sent < m_message_to_send.data.size()) return false;
+ + ]
849 : :
850 : : // create dbl-sha256 checksum
851 : 344350 : uint256 hash = Hash(msg.data);
852 : :
853 : : // create header
854 [ - + ]: 344350 : CMessageHeader hdr(m_magic_bytes, msg.m_type.c_str(), msg.data.size());
855 [ + + ]: 344350 : memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
856 : :
857 : : // serialize header
858 [ + + ]: 344350 : m_header_to_send.clear();
859 : 344350 : VectorWriter{m_header_to_send, 0, hdr};
860 : :
861 : : // update state
862 : 344350 : m_message_to_send = std::move(msg);
863 : 344350 : m_sending_header = true;
864 : 344350 : m_bytes_sent = 0;
865 : 344350 : return true;
866 : 448489 : }
867 : :
868 : 2802209 : Transport::BytesToSend V1Transport::GetBytesToSend(bool have_next_message) const noexcept
869 : : {
870 : 2802209 : AssertLockNotHeld(m_send_mutex);
871 : 2802209 : LOCK(m_send_mutex);
872 [ + + ]: 2802209 : if (m_sending_header) {
873 [ - + + + ]: 806913 : return {std::span{m_header_to_send}.subspan(m_bytes_sent),
874 : : // We have more to send after the header if the message has payload, or if there
875 : : // is a next message after that.
876 [ + + + + ]: 806913 : have_next_message || !m_message_to_send.data.empty(),
877 : 806913 : m_message_to_send.m_type
878 : 806913 : };
879 : : } else {
880 [ - + ]: 1995296 : return {std::span{m_message_to_send.data}.subspan(m_bytes_sent),
881 : : // We only have more to send after this message's payload if there is another
882 : : // message.
883 : : have_next_message,
884 : 1995296 : m_message_to_send.m_type
885 : 1995296 : };
886 : : }
887 : 2802209 : }
888 : :
889 : 642232 : void V1Transport::MarkBytesSent(size_t bytes_sent) noexcept
890 : : {
891 : 642232 : AssertLockNotHeld(m_send_mutex);
892 : 642232 : LOCK(m_send_mutex);
893 : 642232 : m_bytes_sent += bytes_sent;
894 [ + + - + : 642232 : if (m_sending_header && m_bytes_sent == m_header_to_send.size()) {
+ + ]
895 : : // We're done sending a message's header. Switch to sending its data bytes.
896 : 342487 : m_sending_header = false;
897 : 342487 : m_bytes_sent = 0;
898 [ + + - + : 299745 : } else if (!m_sending_header && m_bytes_sent == m_message_to_send.data.size()) {
+ + ]
899 : : // We're done sending a message's data. Wipe the data vector to reduce memory consumption.
900 : 221028 : ClearShrink(m_message_to_send.data);
901 : 221028 : m_bytes_sent = 0;
902 : : }
903 : 642232 : }
904 : :
905 : 306338 : size_t V1Transport::GetSendMemoryUsage() const noexcept
906 : : {
907 : 306338 : AssertLockNotHeld(m_send_mutex);
908 : 306338 : LOCK(m_send_mutex);
909 : : // Don't count sending-side fields besides m_message_to_send, as they're all small and bounded.
910 [ + - ]: 306338 : return m_message_to_send.GetMemoryUsage();
911 : 306338 : }
912 : :
913 : : namespace {
914 : :
915 : : /** List of short messages as defined in BIP324, in order.
916 : : *
917 : : * Only message types that are actually implemented in this codebase need to be listed, as other
918 : : * messages get ignored anyway - whether we know how to decode them or not.
919 : : */
920 : : const std::array<std::string, 33> V2_MESSAGE_IDS = {
921 : : "", // 12 bytes follow encoding the message type like in V1
922 : : NetMsgType::ADDR,
923 : : NetMsgType::BLOCK,
924 : : NetMsgType::BLOCKTXN,
925 : : NetMsgType::CMPCTBLOCK,
926 : : NetMsgType::FEEFILTER,
927 : : NetMsgType::FILTERADD,
928 : : NetMsgType::FILTERCLEAR,
929 : : NetMsgType::FILTERLOAD,
930 : : NetMsgType::GETBLOCKS,
931 : : NetMsgType::GETBLOCKTXN,
932 : : NetMsgType::GETDATA,
933 : : NetMsgType::GETHEADERS,
934 : : NetMsgType::HEADERS,
935 : : NetMsgType::INV,
936 : : NetMsgType::MEMPOOL,
937 : : NetMsgType::MERKLEBLOCK,
938 : : NetMsgType::NOTFOUND,
939 : : NetMsgType::PING,
940 : : NetMsgType::PONG,
941 : : NetMsgType::SENDCMPCT,
942 : : NetMsgType::TX,
943 : : NetMsgType::GETCFILTERS,
944 : : NetMsgType::CFILTER,
945 : : NetMsgType::GETCFHEADERS,
946 : : NetMsgType::CFHEADERS,
947 : : NetMsgType::GETCFCHECKPT,
948 : : NetMsgType::CFCHECKPT,
949 : : NetMsgType::ADDRV2,
950 : : // Unimplemented message types that are assigned in BIP324:
951 : : "",
952 : : "",
953 : : "",
954 : : ""
955 : : };
956 : :
957 : : class V2MessageMap
958 : : {
959 : : std::unordered_map<std::string, uint8_t> m_map;
960 : :
961 : : public:
962 : 230 : V2MessageMap() noexcept
963 : 230 : {
964 [ + + ]: 7590 : for (size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
965 : 7360 : m_map.emplace(V2_MESSAGE_IDS[i], i);
966 : : }
967 : 230 : }
968 : :
969 : 37697 : std::optional<uint8_t> operator()(const std::string& message_name) const noexcept
970 : : {
971 : 37697 : auto it = m_map.find(message_name);
972 [ + + ]: 37697 : if (it == m_map.end()) return std::nullopt;
973 : 29374 : return it->second;
974 : : }
975 : : };
976 : :
977 : : const V2MessageMap V2_MESSAGE_MAP;
978 : :
979 : 12740 : std::vector<uint8_t> GenerateRandomGarbage() noexcept
980 : : {
981 : 12740 : std::vector<uint8_t> ret;
982 : 12740 : FastRandomContext rng;
983 : 12740 : ret.resize(rng.randrange(V2Transport::MAX_GARBAGE_LEN + 1));
984 : 12740 : rng.fillrand(MakeWritableByteSpan(ret));
985 : 12740 : return ret;
986 : 12740 : }
987 : :
988 : : } // namespace
989 : :
990 : 15502 : void V2Transport::StartSendingHandshake() noexcept
991 : : {
992 : 15502 : AssertLockHeld(m_send_mutex);
993 [ - + ]: 15502 : Assume(m_send_state == SendState::AWAITING_KEY);
994 [ - + ]: 15502 : Assume(m_send_buffer.empty());
995 : : // Initialize the send buffer with ellswift pubkey + provided garbage.
996 [ - + ]: 15502 : m_send_buffer.resize(EllSwiftPubKey::size() + m_send_garbage.size());
997 : 15502 : std::copy(std::begin(m_cipher.GetOurPubKey()), std::end(m_cipher.GetOurPubKey()), MakeWritableByteSpan(m_send_buffer).begin());
998 : 15502 : std::copy(m_send_garbage.begin(), m_send_garbage.end(), m_send_buffer.begin() + EllSwiftPubKey::size());
999 : : // We cannot wipe m_send_garbage as it will still be used as AAD later in the handshake.
1000 : 15502 : }
1001 : :
1002 : 16333 : V2Transport::V2Transport(NodeId nodeid, bool initiating, const CKey& key, std::span<const std::byte> ent32, std::vector<uint8_t> garbage) noexcept
1003 : 16333 : : m_cipher{key, ent32},
1004 : 16333 : m_initiating{initiating},
1005 : 16333 : m_nodeid{nodeid},
1006 : 16333 : m_v1_fallback{nodeid},
1007 [ + + ]: 16333 : m_recv_state{initiating ? RecvState::KEY : RecvState::KEY_MAYBE_V1},
1008 [ - + ]: 16333 : m_send_garbage{std::move(garbage)},
1009 [ + + - + ]: 34768 : m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
1010 : : {
1011 [ - + - + ]: 16333 : Assume(m_send_garbage.size() <= MAX_GARBAGE_LEN);
1012 : : // Start sending immediately if we're the initiator of the connection.
1013 [ + + ]: 16333 : if (initiating) {
1014 : 14231 : LOCK(m_send_mutex);
1015 [ + - ]: 14231 : StartSendingHandshake();
1016 : 14231 : }
1017 : 16333 : }
1018 : :
1019 : 12740 : V2Transport::V2Transport(NodeId nodeid, bool initiating) noexcept
1020 : 25480 : : V2Transport{nodeid, initiating, GenerateRandomKey(),
1021 : 25480 : MakeByteSpan(GetRandHash()), GenerateRandomGarbage()} {}
1022 : :
1023 : 85687 : void V2Transport::SetReceiveState(RecvState recv_state) noexcept
1024 : : {
1025 : 85687 : AssertLockHeld(m_recv_mutex);
1026 : : // Enforce allowed state transitions.
1027 [ + + + + : 85687 : switch (m_recv_state) {
+ + - - ]
1028 : 1862 : case RecvState::KEY_MAYBE_V1:
1029 [ - + ]: 1862 : Assume(recv_state == RecvState::KEY || recv_state == RecvState::V1);
1030 : : break;
1031 : 3347 : case RecvState::KEY:
1032 [ - + ]: 3347 : Assume(recv_state == RecvState::GARB_GARBTERM);
1033 : : break;
1034 : 2542 : case RecvState::GARB_GARBTERM:
1035 [ - + ]: 2542 : Assume(recv_state == RecvState::VERSION);
1036 : : break;
1037 : 2542 : case RecvState::VERSION:
1038 [ - + ]: 2542 : Assume(recv_state == RecvState::APP);
1039 : : break;
1040 : 37697 : case RecvState::APP:
1041 [ - + ]: 37697 : Assume(recv_state == RecvState::APP_READY);
1042 : : break;
1043 : 37697 : case RecvState::APP_READY:
1044 [ - + ]: 37697 : Assume(recv_state == RecvState::APP);
1045 : : break;
1046 : 0 : case RecvState::V1:
1047 : 0 : Assume(false); // V1 state cannot be left
1048 : 0 : break;
1049 : : }
1050 : : // Change state.
1051 : 85687 : m_recv_state = recv_state;
1052 : 85687 : }
1053 : :
1054 : 5209 : void V2Transport::SetSendState(SendState send_state) noexcept
1055 : : {
1056 : 5209 : AssertLockHeld(m_send_mutex);
1057 : : // Enforce allowed state transitions.
1058 [ + + - - ]: 5209 : switch (m_send_state) {
1059 : 1862 : case SendState::MAYBE_V1:
1060 [ - + ]: 1862 : Assume(send_state == SendState::V1 || send_state == SendState::AWAITING_KEY);
1061 : : break;
1062 : 3347 : case SendState::AWAITING_KEY:
1063 [ - + ]: 3347 : Assume(send_state == SendState::READY);
1064 : : break;
1065 : 0 : case SendState::READY:
1066 : 0 : case SendState::V1:
1067 : 0 : Assume(false); // Final states
1068 : 0 : break;
1069 : : }
1070 : : // Change state.
1071 : 5209 : m_send_state = send_state;
1072 : 5209 : }
1073 : :
1074 : 110829 : bool V2Transport::ReceivedMessageComplete() const noexcept
1075 : : {
1076 : 110829 : AssertLockNotHeld(m_recv_mutex);
1077 : 110829 : LOCK(m_recv_mutex);
1078 [ + + ]: 110829 : if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedMessageComplete();
1079 : :
1080 : 81029 : return m_recv_state == RecvState::APP_READY;
1081 : 110829 : }
1082 : :
1083 : 2195 : void V2Transport::ProcessReceivedMaybeV1Bytes() noexcept
1084 : : {
1085 : 2195 : AssertLockHeld(m_recv_mutex);
1086 : 2195 : AssertLockNotHeld(m_send_mutex);
1087 [ - + ]: 2195 : Assume(m_recv_state == RecvState::KEY_MAYBE_V1);
1088 : : // We still have to determine if this is a v1 or v2 connection. The bytes being received could
1089 : : // be the beginning of either a v1 packet (network magic + "version\x00\x00\x00\x00\x00"), or
1090 : : // of a v2 public key. BIP324 specifies that a mismatch with this 16-byte string should trigger
1091 : : // sending of the key.
1092 : 2195 : 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};
1093 : 2195 : std::copy(std::begin(Params().MessageStart()), std::end(Params().MessageStart()), v1_prefix.begin());
1094 [ - + - + ]: 2195 : Assume(m_recv_buffer.size() <= v1_prefix.size());
1095 [ + + ]: 2195 : if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), v1_prefix.begin())) {
1096 : : // Mismatch with v1 prefix, so we can assume a v2 connection.
1097 : 1271 : SetReceiveState(RecvState::KEY); // Convert to KEY state, leaving received bytes around.
1098 : : // Transition the sender to AWAITING_KEY state and start sending.
1099 : 1271 : LOCK(m_send_mutex);
1100 : 1271 : SetSendState(SendState::AWAITING_KEY);
1101 [ + - ]: 1271 : StartSendingHandshake();
1102 [ - + + + ]: 2195 : } else if (m_recv_buffer.size() == v1_prefix.size()) {
1103 : : // Full match with the v1 prefix, so fall back to v1 behavior.
1104 : 591 : LOCK(m_send_mutex);
1105 [ - + ]: 591 : std::span<const uint8_t> feedback{m_recv_buffer};
1106 : : // Feed already received bytes to v1 transport. It should always accept these, because it's
1107 : : // less than the size of a v1 header, and these are the first bytes fed to m_v1_fallback.
1108 : 591 : bool ret = m_v1_fallback.ReceivedBytes(feedback);
1109 [ - + ]: 591 : Assume(feedback.empty());
1110 [ - + ]: 591 : Assume(ret);
1111 : 591 : SetReceiveState(RecvState::V1);
1112 : 591 : SetSendState(SendState::V1);
1113 : : // Reset v2 transport buffers to save memory.
1114 : 591 : ClearShrink(m_recv_buffer);
1115 [ + - ]: 591 : ClearShrink(m_send_buffer);
1116 : 591 : } else {
1117 : : // We have not received enough to distinguish v1 from v2 yet. Wait until more bytes come.
1118 : : }
1119 : 2195 : }
1120 : :
1121 : 4753 : bool V2Transport::ProcessReceivedKeyBytes() noexcept
1122 : : {
1123 : 4753 : AssertLockHeld(m_recv_mutex);
1124 : 4753 : AssertLockNotHeld(m_send_mutex);
1125 [ - + ]: 4753 : Assume(m_recv_state == RecvState::KEY);
1126 [ - + - + ]: 4753 : Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());
1127 : :
1128 : : // As a special exception, if bytes 4-16 of the key on a responder connection match the
1129 : : // corresponding bytes of a V1 version message, but bytes 0-4 don't match the network magic
1130 : : // (if they did, we'd have switched to V1 state already), assume this is a peer from
1131 : : // another network, and disconnect them. They will almost certainly disconnect us too when
1132 : : // they receive our uniformly random key and garbage, but detecting this case specially
1133 : : // means we can log it.
1134 : 4753 : static constexpr std::array<uint8_t, 12> MATCH = {'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 0, 0, 0, 0};
1135 : 4753 : static constexpr size_t OFFSET = std::tuple_size_v<MessageStartChars>;
1136 [ + + - + : 4753 : if (!m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
+ + ]
1137 [ - + ]: 1876 : if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
1138 [ # # # # ]: 0 : LogDebug(BCLog::NET, "V2 transport error: V1 peer with wrong MessageStart %s\n",
1139 : : HexStr(std::span(m_recv_buffer).first(OFFSET)));
1140 : 0 : return false;
1141 : : }
1142 : : }
1143 : :
1144 [ - + + + ]: 4753 : if (m_recv_buffer.size() == EllSwiftPubKey::size()) {
1145 : : // Other side's key has been fully received, and can now be Diffie-Hellman combined with
1146 : : // our key to initialize the encryption ciphers.
1147 : :
1148 : : // Initialize the ciphers.
1149 : 3347 : EllSwiftPubKey ellswift(MakeByteSpan(m_recv_buffer));
1150 : 3347 : LOCK(m_send_mutex);
1151 : 3347 : m_cipher.Initialize(ellswift, m_initiating);
1152 : :
1153 : : // Switch receiver state to GARB_GARBTERM.
1154 : 3347 : SetReceiveState(RecvState::GARB_GARBTERM);
1155 [ + - ]: 3347 : m_recv_buffer.clear();
1156 : :
1157 : : // Switch sender state to READY.
1158 : 3347 : SetSendState(SendState::READY);
1159 : :
1160 : : // Append the garbage terminator to the send buffer.
1161 [ - + ]: 3347 : m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1162 : 3347 : std::copy(m_cipher.GetSendGarbageTerminator().begin(),
1163 : 3347 : m_cipher.GetSendGarbageTerminator().end(),
1164 : 3347 : MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN).begin());
1165 : :
1166 : : // Construct version packet in the send buffer, with the sent garbage data as AAD.
1167 [ - + ]: 3347 : m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::EXPANSION + VERSION_CONTENTS.size());
1168 : 3347 : m_cipher.Encrypt(
1169 : : /*contents=*/VERSION_CONTENTS,
1170 : 3347 : /*aad=*/MakeByteSpan(m_send_garbage),
1171 : : /*ignore=*/false,
1172 : 3347 : /*output=*/MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::EXPANSION + VERSION_CONTENTS.size()));
1173 : : // We no longer need the garbage.
1174 [ + - ]: 3347 : ClearShrink(m_send_garbage);
1175 : 3347 : } else {
1176 : : // We still have to receive more key bytes.
1177 : : }
1178 : : return true;
1179 : : }
1180 : :
1181 : 7533078 : bool V2Transport::ProcessReceivedGarbageBytes() noexcept
1182 : : {
1183 : 7533078 : AssertLockHeld(m_recv_mutex);
1184 [ - + ]: 7533078 : Assume(m_recv_state == RecvState::GARB_GARBTERM);
1185 [ - + - + ]: 7533078 : Assume(m_recv_buffer.size() <= MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1186 [ - + + + ]: 7533078 : if (m_recv_buffer.size() >= BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
1187 [ + + ]: 7483053 : if (std::ranges::equal(MakeByteSpan(m_recv_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN), m_cipher.GetReceiveGarbageTerminator())) {
1188 : : // Garbage terminator received. Store garbage to authenticate it as AAD later.
1189 : 2542 : m_recv_aad = std::move(m_recv_buffer);
1190 [ - + ]: 2542 : m_recv_aad.resize(m_recv_aad.size() - BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1191 [ - + ]: 2542 : m_recv_buffer.clear();
1192 : 2542 : SetReceiveState(RecvState::VERSION);
1193 [ + + ]: 7480511 : } else if (m_recv_buffer.size() == MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
1194 : : // We've reached the maximum length for garbage + garbage terminator, and the
1195 : : // terminator still does not match. Abort.
1196 [ - + ]: 766 : LogDebug(BCLog::NET, "V2 transport error: missing garbage terminator, peer=%d\n", m_nodeid);
1197 : 766 : return false;
1198 : : } else {
1199 : : // We still need to receive more garbage and/or garbage terminator bytes.
1200 : : }
1201 : : } else {
1202 : : // We have less than GARBAGE_TERMINATOR_LEN (16) bytes, so we certainly need to receive
1203 : : // more first.
1204 : : }
1205 : : return true;
1206 : : }
1207 : :
1208 : 111662 : bool V2Transport::ProcessReceivedPacketBytes() noexcept
1209 : : {
1210 : 111662 : AssertLockHeld(m_recv_mutex);
1211 [ - + ]: 111662 : Assume(m_recv_state == RecvState::VERSION || m_recv_state == RecvState::APP);
1212 : :
1213 : : // The maximum permitted contents length for a packet, consisting of:
1214 : : // - 0x00 byte: indicating long message type encoding
1215 : : // - 12 bytes of message type
1216 : : // - payload
1217 : 111662 : static constexpr size_t MAX_CONTENTS_LEN =
1218 : : 1 + CMessageHeader::MESSAGE_TYPE_SIZE +
1219 : : std::min<size_t>(MAX_SIZE, MAX_PROTOCOL_MESSAGE_LENGTH);
1220 : :
1221 [ - + + + ]: 111662 : if (m_recv_buffer.size() == BIP324Cipher::LENGTH_LEN) {
1222 : : // Length descriptor received.
1223 : 40239 : m_recv_len = m_cipher.DecryptLength(MakeByteSpan(m_recv_buffer));
1224 [ - + ]: 40239 : if (m_recv_len > MAX_CONTENTS_LEN) {
1225 [ # # ]: 0 : LogDebug(BCLog::NET, "V2 transport error: packet too large (%u bytes), peer=%d\n", m_recv_len, m_nodeid);
1226 : 0 : return false;
1227 : : }
1228 [ + + + + ]: 71423 : } else if (m_recv_buffer.size() > BIP324Cipher::LENGTH_LEN && m_recv_buffer.size() == m_recv_len + BIP324Cipher::EXPANSION) {
1229 : : // Ciphertext received, decrypt it into m_recv_decode_buffer.
1230 : : // Note that it is impossible to reach this branch without hitting the branch above first,
1231 : : // as GetMaxBytesToProcess only allows up to LENGTH_LEN into the buffer before that point.
1232 : 40239 : m_recv_decode_buffer.resize(m_recv_len);
1233 : 40239 : bool ignore{false};
1234 : 80478 : bool ret = m_cipher.Decrypt(
1235 : 40239 : /*input=*/MakeByteSpan(m_recv_buffer).subspan(BIP324Cipher::LENGTH_LEN),
1236 : 40239 : /*aad=*/MakeByteSpan(m_recv_aad),
1237 : : /*ignore=*/ignore,
1238 : : /*contents=*/MakeWritableByteSpan(m_recv_decode_buffer));
1239 [ - + ]: 40239 : if (!ret) {
1240 [ # # ]: 0 : LogDebug(BCLog::NET, "V2 transport error: packet decryption failure (%u bytes), peer=%d\n", m_recv_len, m_nodeid);
1241 : 0 : return false;
1242 : : }
1243 : : // We have decrypted a valid packet with the AAD we expected, so clear the expected AAD.
1244 : 40239 : ClearShrink(m_recv_aad);
1245 : : // Feed the last 4 bytes of the Poly1305 authentication tag (and its timing) into our RNG.
1246 [ - + ]: 40239 : RandAddEvent(ReadLE32(m_recv_buffer.data() + m_recv_buffer.size() - 4));
1247 : :
1248 : : // At this point we have a valid packet decrypted into m_recv_decode_buffer. If it's not a
1249 : : // decoy, which we simply ignore, use the current state to decide what to do with it.
1250 [ + - ]: 40239 : if (!ignore) {
1251 [ + + - ]: 40239 : switch (m_recv_state) {
1252 : 2542 : case RecvState::VERSION:
1253 : : // Version message received; transition to application phase. The contents is
1254 : : // ignored, but can be used for future extensions.
1255 : 2542 : SetReceiveState(RecvState::APP);
1256 : 2542 : break;
1257 : 37697 : case RecvState::APP:
1258 : : // Application message decrypted correctly. It can be extracted using GetMessage().
1259 : 37697 : SetReceiveState(RecvState::APP_READY);
1260 : 37697 : break;
1261 : 0 : default:
1262 : : // Any other state is invalid (this function should not have been called).
1263 : 0 : Assume(false);
1264 : : }
1265 : : }
1266 : : // Wipe the receive buffer where the next packet will be received into.
1267 : 40239 : ClearShrink(m_recv_buffer);
1268 : : // In all but APP_READY state, we can wipe the decoded contents.
1269 [ + + ]: 40239 : if (m_recv_state != RecvState::APP_READY) ClearShrink(m_recv_decode_buffer);
1270 : : } else {
1271 : : // We either have less than 3 bytes, so we don't know the packet's length yet, or more
1272 : : // than 3 bytes but less than the packet's full ciphertext. Wait until those arrive.
1273 : : }
1274 : : return true;
1275 : : }
1276 : :
1277 : 7687733 : size_t V2Transport::GetMaxBytesToProcess() noexcept
1278 : : {
1279 : 7687733 : AssertLockHeld(m_recv_mutex);
1280 [ + + + + : 7687733 : switch (m_recv_state) {
- - + ]
1281 : 2195 : case RecvState::KEY_MAYBE_V1:
1282 : : // During the KEY_MAYBE_V1 state we do not allow more than the length of v1 prefix into the
1283 : : // receive buffer.
1284 [ - + - + ]: 2195 : Assume(m_recv_buffer.size() <= V1_PREFIX_LEN);
1285 : : // As long as we're not sure if this is a v1 or v2 connection, don't receive more than what
1286 : : // is strictly necessary to distinguish the two (16 bytes). If we permitted more than
1287 : : // the v1 header size (24 bytes), we may not be able to feed the already-received bytes
1288 : : // back into the m_v1_fallback V1 transport.
1289 [ - + ]: 2195 : return V1_PREFIX_LEN - m_recv_buffer.size();
1290 : 4753 : case RecvState::KEY:
1291 : : // During the KEY state, we only allow the 64-byte key into the receive buffer.
1292 [ - + - + ]: 4753 : Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());
1293 : : // As long as we have not received the other side's public key, don't receive more than
1294 : : // that (64 bytes), as garbage follows, and locating the garbage terminator requires the
1295 : : // key exchange first.
1296 [ - + ]: 4753 : return EllSwiftPubKey::size() - m_recv_buffer.size();
1297 : : case RecvState::GARB_GARBTERM:
1298 : : // Process garbage bytes one by one (because terminator may appear anywhere).
1299 : : return 1;
1300 : 111662 : case RecvState::VERSION:
1301 : 111662 : case RecvState::APP:
1302 : : // These three states all involve decoding a packet. Process the length descriptor first,
1303 : : // so that we know where the current packet ends (and we don't process bytes from the next
1304 : : // packet or decoy yet). Then, process the ciphertext bytes of the current packet.
1305 [ - + + + ]: 111662 : if (m_recv_buffer.size() < BIP324Cipher::LENGTH_LEN) {
1306 : 41410 : return BIP324Cipher::LENGTH_LEN - m_recv_buffer.size();
1307 : : } else {
1308 : : // Note that BIP324Cipher::EXPANSION is the total difference between contents size
1309 : : // and encoded packet size, which includes the 3 bytes due to the packet length.
1310 : : // When transitioning from receiving the packet length to receiving its ciphertext,
1311 : : // the encrypted packet length is left in the receive buffer.
1312 : 70252 : return BIP324Cipher::EXPANSION + m_recv_len - m_recv_buffer.size();
1313 : : }
1314 : 36045 : case RecvState::APP_READY:
1315 : : // No bytes can be processed until GetMessage() is called.
1316 : 36045 : return 0;
1317 : 0 : case RecvState::V1:
1318 : : // Not allowed (must be dealt with by the caller).
1319 : 0 : Assume(false);
1320 : 0 : return 0;
1321 : : }
1322 : 0 : Assume(false); // unreachable
1323 : 0 : return 0;
1324 : : }
1325 : :
1326 : 111595 : bool V2Transport::ReceivedBytes(std::span<const uint8_t>& msg_bytes) noexcept
1327 : : {
1328 : 111595 : AssertLockNotHeld(m_recv_mutex);
1329 : : /** How many bytes to allocate in the receive buffer at most above what is received so far. */
1330 : 111595 : static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024;
1331 : :
1332 : 111595 : LOCK(m_recv_mutex);
1333 [ + + ]: 111595 : if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes(msg_bytes);
1334 : :
1335 : : // Process the provided bytes in msg_bytes in a loop. In each iteration a nonzero number of
1336 : : // bytes (decided by GetMaxBytesToProcess) are taken from the beginning om msg_bytes, and
1337 : : // appended to m_recv_buffer. Then, depending on the receiver state, one of the
1338 : : // ProcessReceived*Bytes functions is called to process the bytes in that buffer.
1339 : 7732717 : while (!msg_bytes.empty()) {
1340 : : // Decide how many bytes to copy from msg_bytes to m_recv_buffer.
1341 : 7687733 : size_t max_read = GetMaxBytesToProcess();
1342 : :
1343 : : // Reserve space in the buffer if there is not enough.
1344 [ - + + + : 7732750 : if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
- + + + ]
1345 [ + + - - : 84568 : switch (m_recv_state) {
- ]
1346 : 4090 : case RecvState::KEY_MAYBE_V1:
1347 : 4090 : case RecvState::KEY:
1348 : 4090 : case RecvState::GARB_GARBTERM:
1349 : : // During the initial states (key/garbage), allocate once to fit the maximum (4111
1350 : : // bytes).
1351 : 4090 : m_recv_buffer.reserve(MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1352 : 4090 : break;
1353 : 80478 : case RecvState::VERSION:
1354 : 80478 : case RecvState::APP: {
1355 : : // During states where a packet is being received, as much as is expected but never
1356 : : // more than MAX_RESERVE_AHEAD bytes in addition to what is received so far.
1357 : : // This means attackers that want to cause us to waste allocated memory are limited
1358 : : // to MAX_RESERVE_AHEAD above the largest allowed message contents size, and to
1359 : : // MAX_RESERVE_AHEAD more than they've actually sent us.
1360 [ + - ]: 80478 : size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
1361 : 80478 : m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
1362 : 80478 : break;
1363 : : }
1364 : 0 : case RecvState::APP_READY:
1365 : : // The buffer is empty in this state.
1366 [ # # ]: 0 : Assume(m_recv_buffer.empty());
1367 : : break;
1368 : 0 : case RecvState::V1:
1369 : : // Should have bailed out above.
1370 : 0 : Assume(false);
1371 : 0 : break;
1372 : : }
1373 : : }
1374 : :
1375 : : // Can't read more than provided input.
1376 [ + + ]: 7687733 : max_read = std::min(msg_bytes.size(), max_read);
1377 : : // Copy data to buffer.
1378 : 7687733 : m_recv_buffer.insert(m_recv_buffer.end(), UCharCast(msg_bytes.data()), UCharCast(msg_bytes.data() + max_read));
1379 [ + + + + : 7687733 : msg_bytes = msg_bytes.subspan(max_read);
- - + ]
1380 : :
1381 : : // Process data in the buffer.
1382 [ + + + + : 7687733 : switch (m_recv_state) {
- - + ]
1383 : 2195 : case RecvState::KEY_MAYBE_V1:
1384 : 2195 : ProcessReceivedMaybeV1Bytes();
1385 [ + + ]: 2195 : if (m_recv_state == RecvState::V1) return true;
1386 : : break;
1387 : :
1388 : 4753 : case RecvState::KEY:
1389 [ + - ]: 4753 : if (!ProcessReceivedKeyBytes()) return false;
1390 : : break;
1391 : :
1392 : 7533078 : case RecvState::GARB_GARBTERM:
1393 [ + + ]: 7533078 : if (!ProcessReceivedGarbageBytes()) return false;
1394 : : break;
1395 : :
1396 : 111662 : case RecvState::VERSION:
1397 : 111662 : case RecvState::APP:
1398 [ + - ]: 111662 : if (!ProcessReceivedPacketBytes()) return false;
1399 : : break;
1400 : :
1401 : : case RecvState::APP_READY:
1402 : : return true;
1403 : :
1404 : 0 : case RecvState::V1:
1405 : : // We should have bailed out before.
1406 : 0 : Assume(false);
1407 : 0 : break;
1408 : : }
1409 : : // Make sure we have made progress before continuing.
1410 [ - + + + ]: 7732717 : Assume(max_read > 0);
1411 : : }
1412 : :
1413 : : return true;
1414 : 111595 : }
1415 : :
1416 : 37697 : std::optional<std::string> V2Transport::GetMessageType(std::span<const uint8_t>& contents) noexcept
1417 : : {
1418 [ - + ]: 37697 : if (contents.size() == 0) return std::nullopt; // Empty contents
1419 [ + + ]: 37697 : uint8_t first_byte = contents[0];
1420 [ + + ]: 37697 : contents = contents.subspan(1); // Strip first byte.
1421 : :
1422 [ + + ]: 37697 : if (first_byte != 0) {
1423 : : // Short (1 byte) encoding.
1424 [ + - ]: 29374 : if (first_byte < std::size(V2_MESSAGE_IDS)) {
1425 : : // Valid short message id.
1426 [ - + ]: 58748 : return V2_MESSAGE_IDS[first_byte];
1427 : : } else {
1428 : : // Unknown short message id.
1429 : 0 : return std::nullopt;
1430 : : }
1431 : : }
1432 : :
1433 [ - + ]: 8323 : if (contents.size() < CMessageHeader::MESSAGE_TYPE_SIZE) {
1434 : 0 : return std::nullopt; // Long encoding needs 12 message type bytes.
1435 : : }
1436 : :
1437 : : size_t msg_type_len{0};
1438 [ + + + + ]: 62095 : while (msg_type_len < CMessageHeader::MESSAGE_TYPE_SIZE && contents[msg_type_len] != 0) {
1439 : : // Verify that message type bytes before the first 0x00 are in range.
1440 [ - + + - ]: 53772 : if (contents[msg_type_len] < ' ' || contents[msg_type_len] > 0x7F) {
1441 : 0 : return {};
1442 : : }
1443 : 53772 : ++msg_type_len;
1444 : : }
1445 : 8323 : std::string ret{reinterpret_cast<const char*>(contents.data()), msg_type_len};
1446 [ + + ]: 54427 : while (msg_type_len < CMessageHeader::MESSAGE_TYPE_SIZE) {
1447 : : // Verify that message type bytes after the first 0x00 are also 0x00.
1448 [ - + ]: 46104 : if (contents[msg_type_len] != 0) return {};
1449 : 46104 : ++msg_type_len;
1450 : : }
1451 : : // Strip message type bytes of contents.
1452 : 8323 : contents = contents.subspan(CMessageHeader::MESSAGE_TYPE_SIZE);
1453 : 8323 : return ret;
1454 : 8323 : }
1455 : :
1456 : 52325 : CNetMessage V2Transport::GetReceivedMessage(NodeClock::time_point time, bool& reject_message) noexcept
1457 : : {
1458 : 52325 : AssertLockNotHeld(m_recv_mutex);
1459 : 52325 : LOCK(m_recv_mutex);
1460 [ + + ]: 52325 : if (m_recv_state == RecvState::V1) return m_v1_fallback.GetReceivedMessage(time, reject_message);
1461 : :
1462 [ - + ]: 37697 : Assume(m_recv_state == RecvState::APP_READY);
1463 [ - + ]: 37697 : std::span<const uint8_t> contents{m_recv_decode_buffer};
1464 : 37697 : auto msg_type = GetMessageType(contents);
1465 : 37697 : CNetMessage msg{DataStream{}};
1466 : : // Note that BIP324Cipher::EXPANSION also includes the length descriptor size.
1467 [ - + ]: 37697 : msg.m_raw_message_size = m_recv_decode_buffer.size() + BIP324Cipher::EXPANSION;
1468 [ + - ]: 37697 : if (msg_type) {
1469 : 37697 : reject_message = false;
1470 : 37697 : msg.m_type = std::move(*msg_type);
1471 : 37697 : msg.m_time = time;
1472 : 37697 : msg.m_message_size = contents.size();
1473 : 37697 : msg.m_recv.resize(contents.size());
1474 : 37697 : std::copy(contents.begin(), contents.end(), UCharCast(msg.m_recv.data()));
1475 : : } else {
1476 [ # # # # ]: 0 : LogDebug(BCLog::NET, "V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(), m_nodeid);
1477 : 0 : reject_message = true;
1478 : : }
1479 : 37697 : ClearShrink(m_recv_decode_buffer);
1480 : 37697 : SetReceiveState(RecvState::APP);
1481 : :
1482 : 37697 : return msg;
1483 : 37697 : }
1484 : :
1485 : 179716 : bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
1486 : : {
1487 : 179716 : AssertLockNotHeld(m_send_mutex);
1488 : 179716 : LOCK(m_send_mutex);
1489 [ + + ]: 179716 : if (m_send_state == SendState::V1) return m_v1_fallback.SetMessageToSend(msg);
1490 : : // We only allow adding a new message to be sent when in the READY state (so the packet cipher
1491 : : // is available) and the send buffer is empty. This limits the number of messages in the send
1492 : : // buffer to just one, and leaves the responsibility for queueing them up to the caller.
1493 [ + + + + ]: 169744 : if (!(m_send_state == SendState::READY && m_send_buffer.empty())) return false;
1494 : : // Construct contents (encoding message type + payload).
1495 : 37697 : std::vector<uint8_t> contents;
1496 : 37697 : auto short_message_id = V2_MESSAGE_MAP(msg.m_type);
1497 [ + + ]: 37697 : if (short_message_id) {
1498 [ - + ]: 29374 : contents.resize(1 + msg.data.size());
1499 : 29374 : contents[0] = *short_message_id;
1500 : 29374 : std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1);
1501 : : } else {
1502 : : // Initialize with zeroes, and then write the message type string starting at offset 1.
1503 : : // This means contents[0] and the unused positions in contents[1..13] remain 0x00.
1504 [ - + ]: 8323 : contents.resize(1 + CMessageHeader::MESSAGE_TYPE_SIZE + msg.data.size(), 0);
1505 [ - + ]: 8323 : std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
1506 : 8323 : std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1 + CMessageHeader::MESSAGE_TYPE_SIZE);
1507 : : }
1508 : : // Construct ciphertext in send buffer.
1509 [ - + ]: 37697 : m_send_buffer.resize(contents.size() + BIP324Cipher::EXPANSION);
1510 : 37697 : m_cipher.Encrypt(MakeByteSpan(contents), {}, false, MakeWritableByteSpan(m_send_buffer));
1511 : 37697 : m_send_type = msg.m_type;
1512 : : // Release memory
1513 : 37697 : ClearShrink(msg.data);
1514 : 37697 : return true;
1515 : 37697 : }
1516 : :
1517 : 1688298 : Transport::BytesToSend V2Transport::GetBytesToSend(bool have_next_message) const noexcept
1518 : : {
1519 : 1688298 : AssertLockNotHeld(m_send_mutex);
1520 : 1688298 : LOCK(m_send_mutex);
1521 [ + + ]: 1688298 : if (m_send_state == SendState::V1) return m_v1_fallback.GetBytesToSend(have_next_message);
1522 : :
1523 [ + + - + ]: 1507214 : if (m_send_state == SendState::MAYBE_V1) Assume(m_send_buffer.empty());
1524 [ - + - + ]: 1507214 : Assume(m_send_pos <= m_send_buffer.size());
1525 : 1507214 : return {
1526 [ - + + + ]: 1507214 : std::span{m_send_buffer}.subspan(m_send_pos),
1527 : : // We only have more to send after the current m_send_buffer if there is a (next)
1528 : : // message to be sent, and we're capable of sending packets. */
1529 [ + + + + ]: 1507214 : have_next_message && m_send_state == SendState::READY,
1530 : 1507214 : m_send_type
1531 : 1507214 : };
1532 : 1688298 : }
1533 : :
1534 : 161706 : void V2Transport::MarkBytesSent(size_t bytes_sent) noexcept
1535 : : {
1536 : 161706 : AssertLockNotHeld(m_send_mutex);
1537 : 161706 : LOCK(m_send_mutex);
1538 [ + + + - ]: 161706 : if (m_send_state == SendState::V1) return m_v1_fallback.MarkBytesSent(bytes_sent);
1539 : :
1540 [ + + + + : 143386 : if (m_send_state == SendState::AWAITING_KEY && m_send_pos == 0 && bytes_sent > 0) {
+ - ]
1541 [ - + ]: 2622 : LogDebug(BCLog::NET, "start sending v2 handshake to peer=%d\n", m_nodeid);
1542 : : }
1543 : :
1544 : 143386 : m_send_pos += bytes_sent;
1545 [ - + - + ]: 143386 : Assume(m_send_pos <= m_send_buffer.size());
1546 [ + + ]: 143386 : if (m_send_pos >= CMessageHeader::HEADER_SIZE) {
1547 : 96587 : m_sent_v1_header_worth = true;
1548 : : }
1549 : : // Wipe the buffer when everything is sent.
1550 [ - + + + ]: 143386 : if (m_send_pos == m_send_buffer.size()) {
1551 : 41207 : m_send_pos = 0;
1552 : 41207 : ClearShrink(m_send_buffer);
1553 : : }
1554 : 161706 : }
1555 : :
1556 : 0 : bool V2Transport::ShouldReconnectV1() const noexcept
1557 : : {
1558 : 0 : AssertLockNotHeld(m_send_mutex);
1559 : 0 : AssertLockNotHeld(m_recv_mutex);
1560 : : // Only outgoing connections need reconnection.
1561 [ # # ]: 0 : if (!m_initiating) return false;
1562 : :
1563 : 0 : LOCK(m_recv_mutex);
1564 : : // We only reconnect in the very first state and when the receive buffer is empty. Together
1565 : : // these conditions imply nothing has been received so far.
1566 [ # # ]: 0 : if (m_recv_state != RecvState::KEY) return false;
1567 [ # # ]: 0 : if (!m_recv_buffer.empty()) return false;
1568 : : // Check if we've sent enough for the other side to disconnect us (if it was V1).
1569 : 0 : LOCK(m_send_mutex);
1570 [ # # ]: 0 : return m_sent_v1_header_worth;
1571 : 0 : }
1572 : :
1573 : 2995 : size_t V2Transport::GetSendMemoryUsage() const noexcept
1574 : : {
1575 : 2995 : AssertLockNotHeld(m_send_mutex);
1576 : 2995 : LOCK(m_send_mutex);
1577 [ - + ]: 2995 : if (m_send_state == SendState::V1) return m_v1_fallback.GetSendMemoryUsage();
1578 : :
1579 [ - + ]: 5990 : return sizeof(m_send_buffer) + memusage::DynamicUsage(m_send_buffer);
1580 : 2995 : }
1581 : :
1582 : 16107 : Transport::Info V2Transport::GetInfo() const noexcept
1583 : : {
1584 : 16107 : AssertLockNotHeld(m_recv_mutex);
1585 : 16107 : LOCK(m_recv_mutex);
1586 [ + + ]: 16107 : if (m_recv_state == RecvState::V1) return m_v1_fallback.GetInfo();
1587 : :
1588 [ + + ]: 15516 : Transport::Info info;
1589 : :
1590 : : // Do not report v2 and session ID until the version packet has been received
1591 : : // and verified (confirming that the other side very likely has the same keys as us).
1592 [ + + ]: 15516 : if (m_recv_state != RecvState::KEY_MAYBE_V1 && m_recv_state != RecvState::KEY &&
1593 : : m_recv_state != RecvState::GARB_GARBTERM && m_recv_state != RecvState::VERSION) {
1594 : 2542 : info.transport_type = TransportProtocolType::V2;
1595 : 2542 : info.session_id = uint256(MakeUCharSpan(m_cipher.GetSessionID()));
1596 : : } else {
1597 : 12974 : info.transport_type = TransportProtocolType::DETECTING;
1598 : : }
1599 : :
1600 : 15516 : return info;
1601 : 16107 : }
1602 : :
1603 : 128137 : std::pair<size_t, bool> CConnman::SocketSendData(CNode& node) const
1604 : : {
1605 : 128137 : auto it = node.vSendMsg.begin();
1606 : 128137 : size_t nSentSize = 0;
1607 : 128137 : bool data_left{false}; //!< second return value (whether unsent data remains)
1608 : 128137 : std::optional<bool> expected_more;
1609 : :
1610 : 315108 : while (true) {
1611 [ + + ]: 315108 : if (it != node.vSendMsg.end()) {
1612 : : // If possible, move one message from the send queue to the transport. This fails when
1613 : : // there is an existing message still being sent, or (for v2 transports) when the
1614 : : // handshake has not yet completed.
1615 : 125139 : size_t memusage = it->GetMemoryUsage();
1616 [ + - ]: 125139 : if (node.m_transport->SetMessageToSend(*it)) {
1617 : : // Update memory usage of send buffer (as *it will be deleted).
1618 : 125139 : node.m_send_memusage -= memusage;
1619 : 125139 : ++it;
1620 : : }
1621 : : }
1622 [ + + ]: 315108 : const auto& [data, more, msg_type] = node.m_transport->GetBytesToSend(it != node.vSendMsg.end());
1623 : : // We rely on the 'more' value returned by GetBytesToSend to correctly predict whether more
1624 : : // bytes are still to be sent, to correctly set the MSG_MORE flag. As a sanity check,
1625 : : // verify that the previously returned 'more' was correct.
1626 [ + + - + ]: 315108 : if (expected_more.has_value()) Assume(!data.empty() == *expected_more);
1627 [ + + ]: 315108 : expected_more = more;
1628 [ + + ]: 315108 : data_left = !data.empty(); // will be overwritten on next loop if all of data gets sent
1629 : 315108 : int nBytes = 0;
1630 [ + + ]: 315108 : if (!data.empty()) {
1631 : 209826 : LOCK(node.m_sock_mutex);
1632 : : // There is no socket in case we've already disconnected, or in test cases without
1633 : : // real connections. In these cases, we bail out immediately and just leave things
1634 : : // in the send queue and transport.
1635 [ + + ]: 209826 : if (!node.m_sock) {
1636 : : break;
1637 : : }
1638 : 200248 : int flags = MSG_NOSIGNAL | MSG_DONTWAIT;
1639 : : #ifdef MSG_MORE
1640 [ + + ]: 200248 : if (more) {
1641 : 87657 : flags |= MSG_MORE;
1642 : : }
1643 : : #endif
1644 [ + - + - ]: 200248 : nBytes = node.m_sock->Send(data.data(), data.size(), flags);
1645 : 9578 : }
1646 [ + + ]: 200248 : if (nBytes > 0) {
1647 : 196518 : node.m_last_send = NodeClock::now();
1648 : 196518 : node.nSendBytes += nBytes;
1649 : : // Notify transport that bytes have been processed.
1650 : 196518 : node.m_transport->MarkBytesSent(nBytes);
1651 : : // Update statistics per message type.
1652 [ + + ]: 196518 : if (!msg_type.empty()) { // don't report v2 handshake bytes for now
1653 : 182490 : node.AccountForSentBytes(msg_type, nBytes);
1654 : : }
1655 : 196518 : nSentSize += nBytes;
1656 [ + + ]: 196518 : if ((size_t)nBytes != data.size()) {
1657 : : // could not send full message; stop sending more
1658 : : break;
1659 : : }
1660 : : } else {
1661 [ + + ]: 109012 : if (nBytes < 0) {
1662 : : // error
1663 : 3142 : int nErr = WSAGetLastError();
1664 [ + + + + ]: 3142 : if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) {
1665 [ - + - - : 2568 : LogDebug(BCLog::NET, "socket send error, %s: %s", node.DisconnectMsg(), NetworkErrorString(nErr));
- - ]
1666 : 2568 : node.CloseSocketDisconnect();
1667 : : }
1668 : : }
1669 : : break;
1670 : : }
1671 : : }
1672 : :
1673 [ + - ]: 128137 : node.fPauseSend = node.m_send_memusage + node.m_transport->GetSendMemoryUsage() > nSendBufferMaxSize;
1674 : :
1675 [ + - ]: 128137 : if (it == node.vSendMsg.end()) {
1676 [ - + ]: 128137 : assert(node.m_send_memusage == 0);
1677 : : }
1678 : 128137 : node.vSendMsg.erase(node.vSendMsg.begin(), it);
1679 : 128137 : return {nSentSize, data_left};
1680 : : }
1681 : :
1682 : : /** Try to find a connection to evict when the node is full.
1683 : : * Extreme care must be taken to avoid opening the node to attacker
1684 : : * triggered network partitioning.
1685 : : * The strategy used here is to protect a small number of peers
1686 : : * for each of several distinct characteristics which are difficult
1687 : : * to forge. In order to partition a node the attacker must be
1688 : : * simultaneously better at all of them than honest peers.
1689 : : */
1690 : 36313 : bool CConnman::AttemptToEvictConnection()
1691 : : {
1692 : 36313 : AssertLockNotHeld(m_nodes_mutex);
1693 : :
1694 : 36313 : std::vector<NodeEvictionCandidate> vEvictionCandidates;
1695 : 36313 : {
1696 : :
1697 [ + - ]: 36313 : LOCK(m_nodes_mutex);
1698 [ + + ]: 4739227 : for (const CNode* node : m_nodes) {
1699 [ + + ]: 4702914 : if (node->fDisconnect)
1700 : 1674583 : continue;
1701 : 3028331 : NodeEvictionCandidate candidate{
1702 : 3028331 : .id = node->GetId(),
1703 : : .m_connected = node->m_connected,
1704 : 3028331 : .m_min_ping_time = node->m_min_ping_time,
1705 : 3028331 : .m_last_block_time = node->m_last_block_time,
1706 : 3028331 : .m_last_tx_time = node->m_last_tx_time,
1707 [ + - ]: 3028331 : .fRelevantServices = node->m_has_all_wanted_services,
1708 : 3028331 : .m_relay_txs = node->m_relays_txs.load(),
1709 : 3028331 : .fBloomFilter = node->m_bloom_filter_loaded.load(),
1710 : 3028331 : .nKeyedNetGroup = node->nKeyedNetGroup,
1711 : 3028331 : .prefer_evict = node->m_prefer_evict,
1712 [ + - ]: 3028331 : .m_is_local = node->addr.IsLocal(),
1713 : 3028331 : .m_network = node->ConnectedThroughNetwork(),
1714 : 3028331 : .m_noban = node->HasPermission(NetPermissionFlags::NoBan),
1715 : 3028331 : .m_conn_type = node->m_conn_type,
1716 [ + - + - : 6056662 : };
+ - ]
1717 [ + - ]: 3028331 : vEvictionCandidates.push_back(candidate);
1718 : : }
1719 : 0 : }
1720 [ + - ]: 36313 : const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
1721 [ + + ]: 36313 : if (!node_id_to_evict) {
1722 : : return false;
1723 : : }
1724 [ + - ]: 15788 : LOCK(m_nodes_mutex);
1725 [ + - ]: 2337481 : for (CNode* pnode : m_nodes) {
1726 [ + + ]: 2337481 : if (pnode->GetId() == *node_id_to_evict) {
1727 [ + - - + : 15788 : LogDebug(BCLog::NET, "selected %s connection for eviction, %s", pnode->ConnectionTypeAsString(), pnode->DisconnectMsg());
- - - - ]
1728 : : TRACEPOINT(net, evicted_inbound_connection,
1729 : : pnode->GetId(),
1730 : : pnode->m_addr_name.c_str(),
1731 : : pnode->ConnectionTypeAsString().c_str(),
1732 : : pnode->ConnectedThroughNetwork(),
1733 : 15788 : TicksSinceEpoch<std::chrono::seconds>(pnode->m_connected));
1734 : 15788 : pnode->fDisconnect = true;
1735 : 15788 : return true;
1736 : : }
1737 : : }
1738 : : return false;
1739 : 52101 : }
1740 : :
1741 : 2361 : void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
1742 : 2361 : AssertLockNotHeld(m_nodes_mutex);
1743 : :
1744 : 2361 : struct sockaddr_storage sockaddr;
1745 : 2361 : socklen_t len = sizeof(sockaddr);
1746 : 4697 : auto sock = hListenSocket.sock->Accept((struct sockaddr*)&sockaddr, &len);
1747 : :
1748 [ + + ]: 2361 : if (!sock) {
1749 : 25 : const int nErr = WSAGetLastError();
1750 [ + - ]: 25 : if (nErr != WSAEWOULDBLOCK) {
1751 [ + - + - ]: 50 : LogInfo("socket error accept failed: %s\n", NetworkErrorString(nErr));
1752 : : }
1753 : 25 : return;
1754 : : }
1755 : :
1756 [ + - ]: 2336 : CService addr;
1757 [ + - - + ]: 2336 : if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) {
1758 [ # # ]: 0 : LogWarning("Unknown socket family\n");
1759 : : } else {
1760 [ + - ]: 4672 : addr = MaybeFlipIPv6toCJDNS(addr);
1761 : : }
1762 : :
1763 [ + - + - ]: 2336 : const CService addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock))};
1764 : :
1765 : 2336 : NetPermissionFlags permission_flags = NetPermissionFlags::None;
1766 [ + - ]: 2336 : hListenSocket.AddSocketPermissionFlags(permission_flags);
1767 : :
1768 [ + - ]: 2336 : CreateNodeFromAcceptedSocket(std::move(sock), permission_flags, addr_bind, addr);
1769 : 2361 : }
1770 : :
1771 : 39536 : void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
1772 : : NetPermissionFlags permission_flags,
1773 : : const CService& addr_bind,
1774 : : const CService& addr)
1775 : : {
1776 : 39536 : AssertLockNotHeld(m_nodes_mutex);
1777 : :
1778 : 39536 : int nInbound = 0;
1779 : :
1780 [ - + ]: 39536 : const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
1781 : :
1782 : : // Tor inbound connections do not reveal the peer's actual network address.
1783 : : // Therefore do not apply address-based whitelist permissions to them.
1784 [ - + + - ]: 79072 : AddWhitelistPermissionFlags(permission_flags, inbound_onion ? std::optional<CNetAddr>{} : addr, vWhitelistedRangeIncoming);
1785 : :
1786 : 39536 : {
1787 : 39536 : LOCK(m_nodes_mutex);
1788 [ + + ]: 4799599 : for (const CNode* pnode : m_nodes) {
1789 [ + + ]: 4760063 : if (pnode->IsInboundConn()) nInbound++;
1790 : : }
1791 : 39536 : }
1792 : :
1793 [ + + ]: 39536 : if (!fNetworkActive) {
1794 [ - + - - ]: 2095 : LogDebug(BCLog::NET, "connection from %s dropped: not accepting new connections\n", addr.ToStringAddrPort());
1795 : 2095 : return;
1796 : : }
1797 : :
1798 [ + + ]: 37441 : if (!sock->IsSelectable()) {
1799 [ + - ]: 1128 : LogInfo("connection from %s dropped: non-selectable socket\n", addr.ToStringAddrPort());
1800 : 1128 : return;
1801 : : }
1802 : :
1803 : : // According to the internet TCP_NODELAY is not carried into accepted sockets
1804 : : // on all platforms. Set it again here just to be sure.
1805 : 36313 : const int on{1};
1806 [ + + ]: 36313 : if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
1807 [ - + - - ]: 35942 : LogDebug(BCLog::NET, "connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
1808 : : addr.ToStringAddrPort());
1809 : : }
1810 : :
1811 : : // Don't accept connections from banned peers.
1812 [ - + - - ]: 36313 : bool banned = m_banman && m_banman->IsBanned(addr);
1813 [ + + - + ]: 36313 : if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && banned)
1814 : : {
1815 [ # # # # ]: 0 : LogDebug(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToStringAddrPort());
1816 : 0 : return;
1817 : : }
1818 : :
1819 : : // Only accept connections from discouraged peers if our inbound slots aren't (almost) full.
1820 [ - + - - ]: 36313 : bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
1821 [ + + + - : 36313 : if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= m_max_inbound && discouraged)
+ - ]
1822 : : {
1823 [ # # # # ]: 0 : LogDebug(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToStringAddrPort());
1824 : 0 : return;
1825 : : }
1826 : :
1827 [ + - ]: 36313 : if (nInbound >= m_max_inbound)
1828 : : {
1829 [ + + ]: 36313 : if (!AttemptToEvictConnection()) {
1830 : : // No connection to evict, disconnect the new connection
1831 [ - + ]: 20525 : LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
1832 : 20525 : return;
1833 : : }
1834 : : }
1835 : :
1836 : 15788 : NodeId id = GetNewNodeId();
1837 : 15788 : uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
1838 : :
1839 : : // The V2Transport transparently falls back to V1 behavior when an incoming V1 connection is
1840 : : // detected, so use it whenever we signal NODE_P2P_V2.
1841 : 15788 : ServiceFlags local_services = GetLocalServices();
1842 : 15788 : const bool use_v2transport(local_services & NODE_P2P_V2);
1843 : :
1844 : 15788 : uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)
1845 [ + - ]: 15788 : .Write(inbound_onion ? NET_ONION : addr.GetNetClass())
1846 [ - + + - ]: 15788 : .Write(addr_bind.GetAddrBytes())
1847 [ + - + - ]: 15788 : .Write(addr_bind.GetPort()) // inbound connections use bind port
1848 [ + - ]: 15788 : .Finalize();
1849 : 15788 : CNode* pnode = new CNode(id,
1850 : 15788 : std::move(sock),
1851 [ + - ]: 31576 : CAddress{addr, NODE_NONE},
1852 : : CalculateKeyedNetGroup(addr),
1853 : : nonce,
1854 : : addr_bind,
1855 : 15788 : /*addrNameIn=*/"",
1856 : : ConnectionType::INBOUND,
1857 : : inbound_onion,
1858 : : network_id,
1859 : 0 : CNodeOptions{
1860 : : .permission_flags = permission_flags,
1861 : : .prefer_evict = discouraged,
1862 : 15788 : .recv_flood_size = nReceiveFloodSize,
1863 : : .use_v2transport = use_v2transport,
1864 [ + - + - : 31576 : });
+ - + - ]
1865 : 15788 : pnode->AddRef();
1866 : 15788 : m_msgproc->InitializeNode(*pnode, local_services);
1867 : 15788 : {
1868 : 15788 : LOCK(m_nodes_mutex);
1869 [ + - ]: 15788 : m_nodes.push_back(pnode);
1870 : 0 : }
1871 [ - + - - ]: 15788 : LogDebug(BCLog::NET, "connection from %s accepted\n", addr.ToStringAddrPort());
1872 : : TRACEPOINT(net, inbound_connection,
1873 : : pnode->GetId(),
1874 : : pnode->m_addr_name.c_str(),
1875 : : pnode->ConnectionTypeAsString().c_str(),
1876 : : pnode->ConnectedThroughNetwork(),
1877 : 15788 : GetNodeCount(ConnectionDirection::In));
1878 : :
1879 : : // We received a new connection, harvest entropy from the time (and our peer count)
1880 : 15788 : RandAddEvent((uint32_t)id);
1881 : : }
1882 : :
1883 : 0 : bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type, bool use_v2transport = false)
1884 : : {
1885 : 0 : AssertLockNotHeld(m_nodes_mutex);
1886 : 0 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
1887 : 0 : std::optional<int> max_connections;
1888 [ # # # # ]: 0 : switch (conn_type) {
1889 : : case ConnectionType::INBOUND:
1890 : : case ConnectionType::MANUAL:
1891 : : case ConnectionType::PRIVATE_BROADCAST:
1892 : : return false;
1893 : 0 : case ConnectionType::OUTBOUND_FULL_RELAY:
1894 : 0 : max_connections = m_max_outbound_full_relay;
1895 : 0 : break;
1896 : 0 : case ConnectionType::BLOCK_RELAY:
1897 : 0 : max_connections = m_max_outbound_block_relay;
1898 : 0 : break;
1899 : : // no limit for ADDR_FETCH because -seednode has no limit either
1900 : : case ConnectionType::ADDR_FETCH:
1901 : : break;
1902 : : // no limit for FEELER connections since they're short-lived
1903 : : case ConnectionType::FEELER:
1904 : : break;
1905 : : } // no default case, so the compiler can warn about missing cases
1906 : :
1907 : : // Count existing connections
1908 [ # # # # ]: 0 : int existing_connections = WITH_LOCK(m_nodes_mutex,
1909 : : return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](CNode* node) { return node->m_conn_type == conn_type; }););
1910 : :
1911 : : // Max connections of specified type already exist
1912 [ # # ]: 0 : if (max_connections != std::nullopt && existing_connections >= max_connections) return false;
1913 : :
1914 : : // Max total outbound connections already exist
1915 : 0 : CountingSemaphoreGrant<> grant(*semOutbound, true);
1916 [ # # ]: 0 : if (!grant) return false;
1917 : :
1918 [ # # # # : 0 : OpenNetworkConnection(CAddress(), false, std::move(grant), address.c_str(), conn_type, /*use_v2transport=*/use_v2transport);
# # ]
1919 : 0 : return true;
1920 : : }
1921 : :
1922 : 0 : void CConnman::DisconnectNodes()
1923 : : {
1924 : 0 : AssertLockNotHeld(m_nodes_mutex);
1925 : 0 : AssertLockNotHeld(m_reconnections_mutex);
1926 : :
1927 : : // Use a temporary variable to accumulate desired reconnections, so we don't need
1928 : : // m_reconnections_mutex while holding m_nodes_mutex.
1929 [ # # ]: 0 : decltype(m_reconnections) reconnections_to_add;
1930 : :
1931 : 0 : {
1932 [ # # ]: 0 : LOCK(m_nodes_mutex);
1933 : :
1934 [ # # ]: 0 : const bool network_active{fNetworkActive};
1935 [ # # ]: 0 : if (!network_active) {
1936 : : // Disconnect any connected nodes
1937 [ # # ]: 0 : for (CNode* pnode : m_nodes) {
1938 [ # # ]: 0 : if (!pnode->fDisconnect) {
1939 [ # # # # : 0 : LogDebug(BCLog::NET, "Network not active, %s", pnode->DisconnectMsg());
# # # # ]
1940 : 0 : pnode->fDisconnect = true;
1941 : : }
1942 : : }
1943 : : }
1944 : :
1945 : : // Disconnect unused nodes
1946 [ # # ]: 0 : std::vector<CNode*> nodes_copy = m_nodes;
1947 [ # # ]: 0 : for (CNode* pnode : nodes_copy)
1948 : : {
1949 [ # # ]: 0 : if (pnode->fDisconnect)
1950 : : {
1951 : : // remove from m_nodes
1952 : 0 : m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());
1953 : :
1954 : : // Add to reconnection list if appropriate. We don't reconnect right here, because
1955 : : // the creation of a connection is a blocking operation (up to several seconds),
1956 : : // and we don't want to hold up the socket handler thread for that long.
1957 [ # # # # ]: 0 : if (network_active && pnode->m_transport->ShouldReconnectV1()) {
1958 : 0 : reconnections_to_add.push_back({
1959 : 0 : .addr_connect = pnode->addr,
1960 [ # # ]: 0 : .grant = std::move(pnode->grantOutbound),
1961 : 0 : .destination = pnode->m_dest,
1962 : 0 : .conn_type = pnode->m_conn_type,
1963 : : .use_v2transport = false});
1964 [ # # # # : 0 : LogDebug(BCLog::NET, "retrying with v1 transport protocol for peer=%d\n", pnode->GetId());
# # ]
1965 : : }
1966 : :
1967 : : // release outbound grant (if any)
1968 : 0 : pnode->grantOutbound.Release();
1969 : :
1970 : : // close socket and cleanup
1971 [ # # ]: 0 : pnode->CloseSocketDisconnect();
1972 : :
1973 : : // update connection count by network
1974 [ # # # # ]: 0 : if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];
1975 : :
1976 : : // hold in disconnected pool until all refs are released
1977 [ # # ]: 0 : pnode->Release();
1978 [ # # ]: 0 : m_nodes_disconnected.push_back(pnode);
1979 : : }
1980 : : }
1981 [ # # ]: 0 : }
1982 : 0 : {
1983 : : // Delete disconnected nodes
1984 [ # # ]: 0 : std::list<CNode*> nodes_disconnected_copy = m_nodes_disconnected;
1985 [ # # ]: 0 : for (CNode* pnode : nodes_disconnected_copy)
1986 : : {
1987 : : // Destroy the object only after other threads have stopped using it.
1988 [ # # ]: 0 : if (pnode->GetRefCount() <= 0) {
1989 : 0 : m_nodes_disconnected.remove(pnode);
1990 [ # # ]: 0 : DeleteNode(pnode);
1991 : : }
1992 : : }
1993 : 0 : }
1994 : 0 : {
1995 : : // Move entries from reconnections_to_add to m_reconnections.
1996 [ # # ]: 0 : LOCK(m_reconnections_mutex);
1997 [ # # ]: 0 : m_reconnections.splice(m_reconnections.end(), std::move(reconnections_to_add));
1998 : 0 : }
1999 [ # # # # : 0 : }
# # ]
2000 : :
2001 : 0 : void CConnman::NotifyNumConnectionsChanged()
2002 : : {
2003 : 0 : AssertLockNotHeld(m_nodes_mutex);
2004 : :
2005 : 0 : size_t nodes_size;
2006 : 0 : {
2007 : 0 : LOCK(m_nodes_mutex);
2008 [ # # # # ]: 0 : nodes_size = m_nodes.size();
2009 : 0 : }
2010 [ # # ]: 0 : if(nodes_size != nPrevNodeCount) {
2011 : 0 : nPrevNodeCount = nodes_size;
2012 [ # # ]: 0 : if (m_client_interface) {
2013 : 0 : m_client_interface->NotifyNumConnectionsChanged(nodes_size);
2014 : : }
2015 : : }
2016 : 0 : }
2017 : :
2018 : 1327822 : bool CConnman::ShouldRunInactivityChecks(const CNode& node, NodeClock::time_point now) const
2019 : : {
2020 : 1327822 : return node.m_connected + m_peer_connect_timeout < now;
2021 : : }
2022 : :
2023 : 8513 : bool CConnman::InactivityCheck(const CNode& node, NodeClock::time_point now) const
2024 : : {
2025 : : // Tests that see disconnects after using mocktime can start nodes with a
2026 : : // large timeout. For example, -peertimeout=999999999.
2027 : 8513 : const auto last_send{node.m_last_send.load()};
2028 : 8513 : const auto last_recv{node.m_last_recv.load()};
2029 : :
2030 [ - + ]: 8513 : if (!ShouldRunInactivityChecks(node, now)) return false;
2031 : :
2032 [ # # ]: 0 : bool has_received{last_recv > NodeClock::epoch};
2033 : 0 : bool has_sent{last_send > NodeClock::epoch};
2034 : :
2035 [ # # ]: 0 : if (!has_received || !has_sent) {
2036 [ # # ]: 0 : std::string has_never;
2037 [ # # # # ]: 0 : if (!has_received) has_never += ", never received from peer";
2038 [ # # # # ]: 0 : if (!has_sent) has_never += ", never sent to peer";
2039 [ # # # # : 0 : LogDebug(BCLog::NET,
# # # # ]
2040 : : "socket no message in first %i seconds%s, %s",
2041 : : count_seconds(m_peer_connect_timeout),
2042 : : has_never,
2043 : : node.DisconnectMsg()
2044 : : );
2045 : 0 : return true;
2046 : 0 : }
2047 : :
2048 [ # # ]: 0 : if (now > last_send + TIMEOUT_INTERVAL) {
2049 [ # # # # ]: 0 : LogDebug(BCLog::NET,
2050 : : "socket sending timeout: %is, %s", Ticks<std::chrono::seconds>(now - last_send),
2051 : : node.DisconnectMsg()
2052 : : );
2053 : 0 : return true;
2054 : : }
2055 : :
2056 [ # # ]: 0 : if (now > last_recv + TIMEOUT_INTERVAL) {
2057 [ # # # # ]: 0 : LogDebug(BCLog::NET,
2058 : : "socket receive timeout: %is, %s", Ticks<std::chrono::seconds>(now - last_recv),
2059 : : node.DisconnectMsg()
2060 : : );
2061 : 0 : return true;
2062 : : }
2063 : :
2064 [ # # ]: 0 : if (!node.fSuccessfullyConnected) {
2065 [ # # ]: 0 : if (node.m_transport->GetInfo().transport_type == TransportProtocolType::DETECTING) {
2066 [ # # # # ]: 0 : LogDebug(BCLog::NET, "V2 handshake timeout, %s", node.DisconnectMsg());
2067 : : } else {
2068 [ # # # # ]: 0 : LogDebug(BCLog::NET, "version handshake timeout, %s", node.DisconnectMsg());
2069 : : }
2070 : 0 : return true;
2071 : : }
2072 : :
2073 : : return false;
2074 : : }
2075 : :
2076 : 7342 : Sock::EventsPerSock CConnman::GenerateWaitSockets(std::span<CNode* const> nodes)
2077 : : {
2078 : 7342 : Sock::EventsPerSock events_per_sock;
2079 : :
2080 [ + + ]: 176374 : for (const ListenSocket& hListenSocket : vhListenSocket) {
2081 [ + - ]: 169032 : events_per_sock.emplace(hListenSocket.sock, Sock::Events{Sock::RECV});
2082 : : }
2083 : :
2084 [ + + ]: 920024 : for (CNode* pnode : nodes) {
2085 [ + - ]: 912682 : bool select_recv = !pnode->fPauseRecv;
2086 : 912682 : bool select_send;
2087 : 912682 : {
2088 [ + - ]: 912682 : LOCK(pnode->cs_vSend);
2089 : : // Sending is possible if either there are bytes to send right now, or if there will be
2090 : : // once a potential message from vSendMsg is handed to the transport. GetBytesToSend
2091 : : // determines both of these in a single call.
2092 [ + + ]: 912682 : const auto& [to_send, more, _msg_type] = pnode->m_transport->GetBytesToSend(!pnode->vSendMsg.empty());
2093 [ + + + - : 1545873 : select_send = !to_send.empty() || more;
+ - ]
2094 : 912682 : }
2095 [ - + ]: 912682 : if (!select_recv && !select_send) continue;
2096 : :
2097 [ + - ]: 912682 : LOCK(pnode->m_sock_mutex);
2098 [ + + ]: 912682 : if (pnode->m_sock) {
2099 [ + + - + ]: 1531985 : Sock::Event event = (select_send ? Sock::SEND : 0) | (select_recv ? Sock::RECV : 0);
2100 [ + - ]: 904762 : events_per_sock.emplace(pnode->m_sock, Sock::Events{event});
2101 : : }
2102 : 912682 : }
2103 : :
2104 : 7342 : return events_per_sock;
2105 : 0 : }
2106 : :
2107 : 7342 : void CConnman::SocketHandler()
2108 : : {
2109 : 7342 : AssertLockNotHeld(m_nodes_mutex);
2110 : 7342 : AssertLockNotHeld(m_total_bytes_sent_mutex);
2111 : :
2112 [ + - ]: 7342 : Sock::EventsPerSock events_per_sock;
2113 : :
2114 : 7342 : {
2115 [ + - ]: 7342 : const NodesSnapshot snap{*this, /*shuffle=*/false};
2116 : :
2117 : 7342 : const auto timeout = std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS);
2118 : :
2119 : : // Check for the readiness of the already connected sockets and the
2120 : : // listening sockets in one call ("readiness" as in poll(2) or
2121 : : // select(2)). If none are ready, wait for a short while and return
2122 : : // empty sets.
2123 [ - + + - ]: 14684 : events_per_sock = GenerateWaitSockets(snap.Nodes());
2124 [ + + + - : 7342 : if (events_per_sock.empty() || !events_per_sock.begin()->first->WaitMany(timeout, events_per_sock)) {
- + ]
2125 [ + - ]: 777 : m_interrupt_net->sleep_for(timeout);
2126 : : }
2127 : :
2128 : : // Service (send/receive) each of the already connected nodes.
2129 [ + - ]: 7342 : SocketHandlerConnected(snap.Nodes(), events_per_sock);
2130 : 7342 : }
2131 : :
2132 : : // Accept new connections from listening sockets.
2133 [ + - ]: 7342 : SocketHandlerListening(events_per_sock);
2134 : 7342 : }
2135 : :
2136 : 7342 : void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
2137 : : const Sock::EventsPerSock& events_per_sock)
2138 : : {
2139 : 7342 : AssertLockNotHeld(m_total_bytes_sent_mutex);
2140 : :
2141 : 7342 : const auto now{NodeClock::now()};
2142 : :
2143 [ + + ]: 18735 : for (CNode* pnode : nodes) {
2144 [ + + ]: 17432 : if (m_interrupt_net->interrupted()) {
2145 : : return;
2146 : : }
2147 : :
2148 : : //
2149 : : // Receive
2150 : : //
2151 : 11393 : bool recvSet = false;
2152 : 11393 : bool sendSet = false;
2153 : 11393 : bool errorSet = false;
2154 : 11393 : {
2155 : 11393 : LOCK(pnode->m_sock_mutex);
2156 [ + + ]: 11393 : if (!pnode->m_sock) {
2157 [ + - ]: 2102 : continue;
2158 : : }
2159 [ + - + - ]: 18582 : const auto it = events_per_sock.find(pnode->m_sock);
2160 [ + - + - ]: 18582 : if (it != events_per_sock.end()) {
2161 : 9291 : recvSet = it->second.occurred & Sock::RECV;
2162 : 9291 : sendSet = it->second.occurred & Sock::SEND;
2163 : 9291 : errorSet = it->second.occurred & Sock::ERR;
2164 : : }
2165 : 2102 : }
2166 : :
2167 [ + + ]: 9291 : if (sendSet) {
2168 : : // Send data
2169 [ + + + - ]: 8994 : auto [bytes_sent, data_left] = WITH_LOCK(pnode->cs_vSend, return SocketSendData(*pnode));
2170 [ + + ]: 2998 : if (bytes_sent) {
2171 : 2093 : RecordBytesSent(bytes_sent);
2172 : :
2173 : : // If both receiving and (non-optimistic) sending were possible, we first attempt
2174 : : // sending. If that succeeds, but does not fully drain the send queue, do not
2175 : : // attempt to receive. This avoids needlessly queueing data if the remote peer
2176 : : // is slow at receiving data, by means of TCP flow control. We only do this when
2177 : : // sending actually succeeded to make sure progress is always made; otherwise a
2178 : : // deadlock would be possible when both sides have data to send, but neither is
2179 : : // receiving.
2180 [ + + ]: 2093 : if (data_left) recvSet = false;
2181 : : }
2182 : : }
2183 : :
2184 [ + + ]: 9291 : if (recvSet || errorSet)
2185 : : {
2186 : : // typical socket buffer is 8K-64K
2187 : 7044 : uint8_t pchBuf[0x10000];
2188 : 7044 : int nBytes = 0;
2189 : 7044 : {
2190 : 7044 : LOCK(pnode->m_sock_mutex);
2191 [ + + ]: 7044 : if (!pnode->m_sock) {
2192 [ + - ]: 778 : continue;
2193 : : }
2194 [ + - + - ]: 6266 : nBytes = pnode->m_sock->Recv(pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
2195 : 778 : }
2196 [ + + ]: 6266 : if (nBytes > 0)
2197 : : {
2198 : 2680 : bool notify = false;
2199 [ + + ]: 2680 : if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
2200 [ - + - - ]: 2290 : LogDebug(BCLog::NET,
2201 : : "receiving message bytes failed, %s",
2202 : : pnode->DisconnectMsg()
2203 : : );
2204 : 2290 : pnode->CloseSocketDisconnect();
2205 : : }
2206 : 2680 : RecordBytesRecv(nBytes);
2207 [ - + ]: 2680 : if (notify) {
2208 : 0 : pnode->MarkReceivedMsgsForProcessing();
2209 : 0 : WakeMessageHandler();
2210 : : }
2211 : : }
2212 [ + + ]: 3586 : else if (nBytes == 0)
2213 : : {
2214 : : // socket closed gracefully
2215 [ + + ]: 3457 : if (!pnode->fDisconnect) {
2216 [ - + - - ]: 3002 : LogDebug(BCLog::NET, "socket closed, %s", pnode->DisconnectMsg());
2217 : : }
2218 : 3457 : pnode->CloseSocketDisconnect();
2219 : : }
2220 [ + - ]: 129 : else if (nBytes < 0)
2221 : : {
2222 : : // error
2223 : 129 : int nErr = WSAGetLastError();
2224 [ + + + + ]: 129 : if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
2225 : : {
2226 [ + + ]: 58 : if (!pnode->fDisconnect) {
2227 [ - + - - : 55 : LogDebug(BCLog::NET, "socket recv error, %s: %s", pnode->DisconnectMsg(), NetworkErrorString(nErr));
- - ]
2228 : : }
2229 : 58 : pnode->CloseSocketDisconnect();
2230 : : }
2231 : : }
2232 : : }
2233 : :
2234 [ - + ]: 8513 : if (InactivityCheck(*pnode, now)) pnode->fDisconnect = true;
2235 : : }
2236 : : }
2237 : :
2238 : 7342 : void CConnman::SocketHandlerListening(const Sock::EventsPerSock& events_per_sock)
2239 : : {
2240 : 7342 : AssertLockNotHeld(m_nodes_mutex);
2241 : :
2242 [ + + ]: 10033 : for (const ListenSocket& listen_socket : vhListenSocket) {
2243 [ + + ]: 4368 : if (m_interrupt_net->interrupted()) {
2244 : : return;
2245 : : }
2246 [ + - + - ]: 5382 : const auto it = events_per_sock.find(listen_socket.sock);
2247 [ + - + + ]: 5052 : if (it != events_per_sock.end() && it->second.occurred & Sock::RECV) {
2248 : 2361 : AcceptConnection(listen_socket);
2249 : : }
2250 : : }
2251 : : }
2252 : :
2253 : 0 : void CConnman::ThreadSocketHandler()
2254 : : {
2255 : 0 : AssertLockNotHeld(m_total_bytes_sent_mutex);
2256 : :
2257 [ # # ]: 0 : while (!m_interrupt_net->interrupted()) {
2258 : 0 : DisconnectNodes();
2259 : 0 : NotifyNumConnectionsChanged();
2260 : 0 : SocketHandler();
2261 : : }
2262 : 0 : }
2263 : :
2264 : 0 : void CConnman::WakeMessageHandler()
2265 : : {
2266 : 0 : {
2267 : 0 : LOCK(mutexMsgProc);
2268 [ # # ]: 0 : fMsgProcWake = true;
2269 : 0 : }
2270 : 0 : condMsgProc.notify_one();
2271 : 0 : }
2272 : :
2273 : 0 : void CConnman::ThreadDNSAddressSeed()
2274 : : {
2275 : 0 : int outbound_connection_count = 0;
2276 : :
2277 [ # # # # ]: 0 : if (!gArgs.GetArgs("-seednode").empty()) {
2278 : 0 : auto start = NodeClock::now();
2279 : 0 : constexpr std::chrono::seconds SEEDNODE_TIMEOUT = 30s;
2280 : 0 : LogInfo("-seednode enabled. Trying the provided seeds for %d seconds before defaulting to the dnsseeds.\n", SEEDNODE_TIMEOUT.count());
2281 [ # # ]: 0 : while (!m_interrupt_net->interrupted()) {
2282 [ # # ]: 0 : if (!m_interrupt_net->sleep_for(500ms)) {
2283 : : return;
2284 : : }
2285 : :
2286 : : // Abort if we have spent enough time without reaching our target.
2287 : : // Giving seed nodes 30 seconds so this does not become a race against fixedseeds (which triggers after 1 min)
2288 [ # # ]: 0 : if (NodeClock::now() > start + SEEDNODE_TIMEOUT) {
2289 : 0 : LogInfo("Couldn't connect to enough peers via seed nodes. Handing fetch logic to the DNS seeds.\n");
2290 : 0 : break;
2291 : : }
2292 : :
2293 : 0 : outbound_connection_count = GetFullOutboundConnCount();
2294 [ # # ]: 0 : if (outbound_connection_count >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
2295 : 0 : LogInfo("P2P peers available. Finished fetching data from seed nodes.\n");
2296 : 0 : break;
2297 : : }
2298 : : }
2299 : : }
2300 : :
2301 : 0 : FastRandomContext rng;
2302 [ # # ]: 0 : std::vector<std::string> seeds = m_params.DNSSeeds();
2303 : 0 : std::shuffle(seeds.begin(), seeds.end(), rng);
2304 : 0 : int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections
2305 : :
2306 [ # # # # : 0 : if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
# # ]
2307 : : // When -forcednsseed is provided, query all.
2308 [ # # ]: 0 : seeds_right_now = seeds.size();
2309 [ # # # # ]: 0 : } else if (addrman.get().Size() == 0) {
2310 : : // If we have no known peers, query all.
2311 : : // This will occur on the first run, or if peers.dat has been
2312 : : // deleted.
2313 [ # # ]: 0 : seeds_right_now = seeds.size();
2314 : : }
2315 : :
2316 : : // Proceed with dnsseeds if seednodes hasn't reached the target or if forcednsseed is set
2317 [ # # ]: 0 : if (outbound_connection_count < SEED_OUTBOUND_CONNECTION_THRESHOLD || seeds_right_now) {
2318 : : // goal: only query DNS seed if address need is acute
2319 : : // * If we have a reasonable number of peers in addrman, spend
2320 : : // some time trying them first. This improves user privacy by
2321 : : // creating fewer identifying DNS requests, reduces trust by
2322 : : // giving seeds less influence on the network topology, and
2323 : : // reduces traffic to the seeds.
2324 : : // * When querying DNS seeds query a few at once, this ensures
2325 : : // that we don't give DNS seeds the ability to eclipse nodes
2326 : : // that query them.
2327 : : // * If we continue having problems, eventually query all the
2328 : : // DNS seeds, and if that fails too, also try the fixed seeds.
2329 : : // (done in ThreadOpenConnections)
2330 : 0 : int found = 0;
2331 [ # # # # ]: 0 : const std::chrono::seconds seeds_wait_time = (addrman.get().Size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
2332 : :
2333 [ # # ]: 0 : for (const std::string& seed : seeds) {
2334 [ # # ]: 0 : if (seeds_right_now == 0) {
2335 : 0 : seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
2336 : :
2337 [ # # # # ]: 0 : if (addrman.get().Size() > 0) {
2338 [ # # ]: 0 : LogInfo("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
2339 : 0 : std::chrono::seconds to_wait = seeds_wait_time;
2340 [ # # ]: 0 : while (to_wait.count() > 0) {
2341 : : // if sleeping for the MANY_PEERS interval, wake up
2342 : : // early to see if we have enough peers and can stop
2343 : : // this thread entirely freeing up its resources
2344 : 0 : std::chrono::seconds w = std::min(DNSSEEDS_DELAY_FEW_PEERS, to_wait);
2345 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(w)) return;
2346 [ # # ]: 0 : to_wait -= w;
2347 : :
2348 [ # # # # ]: 0 : if (GetFullOutboundConnCount() >= SEED_OUTBOUND_CONNECTION_THRESHOLD) {
2349 [ # # ]: 0 : if (found > 0) {
2350 [ # # ]: 0 : LogInfo("%d addresses found from DNS seeds\n", found);
2351 [ # # ]: 0 : LogInfo("P2P peers available. Finished DNS seeding.\n");
2352 : : } else {
2353 [ # # ]: 0 : LogInfo("P2P peers available. Skipped DNS seeding.\n");
2354 : : }
2355 : 0 : return;
2356 : : }
2357 : : }
2358 : : }
2359 : : }
2360 : :
2361 [ # # # # ]: 0 : if (m_interrupt_net->interrupted()) return;
2362 : :
2363 : : // hold off on querying seeds if P2P network deactivated
2364 [ # # ]: 0 : if (!fNetworkActive) {
2365 [ # # ]: 0 : LogInfo("Waiting for network to be reactivated before querying DNS seeds.\n");
2366 : 0 : do {
2367 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(1s)) return;
2368 [ # # ]: 0 : } while (!fNetworkActive);
2369 : : }
2370 : :
2371 [ # # ]: 0 : LogInfo("Loading addresses from DNS seed %s\n", seed);
2372 : : // If -proxy is in use, we make an ADDR_FETCH connection to the DNS resolved peer address
2373 : : // for the base dns seed domain in chainparams
2374 [ # # # # ]: 0 : if (HaveNameProxy()) {
2375 [ # # ]: 0 : AddAddrFetch(seed);
2376 : : } else {
2377 : 0 : std::vector<CAddress> vAdd;
2378 : 0 : constexpr ServiceFlags requiredServiceBits{SeedsServiceFlags()};
2379 [ # # ]: 0 : std::string host = strprintf("x%x.%s", requiredServiceBits, seed);
2380 [ # # ]: 0 : CNetAddr resolveSource;
2381 [ # # # # ]: 0 : if (!resolveSource.SetInternal(host)) {
2382 : 0 : continue;
2383 : : }
2384 : : // Limit number of IPs learned from a single DNS seed. This limit exists to prevent the results from
2385 : : // one DNS seed from dominating AddrMan. Note that the number of results from a UDP DNS query is
2386 : : // bounded to 33 already, but it is possible for it to use TCP where a larger number of results can be
2387 : : // returned.
2388 : 0 : unsigned int nMaxIPs = 32;
2389 [ # # # # ]: 0 : const auto addresses{LookupHost(host, nMaxIPs, true)};
2390 [ # # ]: 0 : if (!addresses.empty()) {
2391 [ # # ]: 0 : for (const CNetAddr& ip : addresses) {
2392 [ # # ]: 0 : CAddress addr = CAddress(CService(ip, m_params.GetDefaultPort()), requiredServiceBits);
2393 : 0 : addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
2394 [ # # ]: 0 : vAdd.push_back(addr);
2395 : 0 : found++;
2396 : 0 : }
2397 [ # # ]: 0 : addrman.get().Add(vAdd, resolveSource);
2398 : : } else {
2399 : : // If the seed does not support a subdomain with our desired service bits,
2400 : : // we make an ADDR_FETCH connection to the DNS resolved peer address for the
2401 : : // base dns seed domain in chainparams
2402 [ # # ]: 0 : AddAddrFetch(seed);
2403 : : }
2404 : 0 : }
2405 : 0 : --seeds_right_now;
2406 : : }
2407 [ # # ]: 0 : LogInfo("%d addresses found from DNS seeds\n", found);
2408 : : } else {
2409 [ # # ]: 0 : LogInfo("Skipping DNS seeds. Enough peers have been found\n");
2410 : : }
2411 : 0 : }
2412 : :
2413 : 0 : void CConnman::DumpAddresses()
2414 : : {
2415 : 0 : const auto start{SteadyClock::now()};
2416 : :
2417 : 0 : DumpPeerAddresses(::gArgs, addrman);
2418 : :
2419 [ # # ]: 0 : LogDebug(BCLog::NET, "Flushed %d addresses to peers.dat %dms",
2420 : : addrman.get().Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
2421 : 0 : }
2422 : :
2423 : 0 : void CConnman::ProcessAddrFetch()
2424 : : {
2425 : 0 : AssertLockNotHeld(m_nodes_mutex);
2426 : 0 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
2427 [ # # ]: 0 : std::string strDest;
2428 : 0 : {
2429 [ # # ]: 0 : LOCK(m_addr_fetches_mutex);
2430 [ # # ]: 0 : if (m_addr_fetches.empty())
2431 [ # # ]: 0 : return;
2432 [ # # ]: 0 : strDest = m_addr_fetches.front();
2433 [ # # ]: 0 : m_addr_fetches.pop_front();
2434 : 0 : }
2435 : : // Attempt v2 connection if we support v2 - we'll reconnect with v1 if our
2436 : : // peer doesn't support it or immediately disconnects us for another reason.
2437 [ # # ]: 0 : const bool use_v2transport(GetLocalServices() & NODE_P2P_V2);
2438 [ # # ]: 0 : CAddress addr;
2439 : 0 : CountingSemaphoreGrant<> grant(*semOutbound, /*fTry=*/true);
2440 [ # # ]: 0 : if (grant) {
2441 [ # # ]: 0 : OpenNetworkConnection(addr, false, std::move(grant), strDest.c_str(), ConnectionType::ADDR_FETCH, use_v2transport);
2442 : : }
2443 : 0 : }
2444 : :
2445 : 3391 : bool CConnman::GetTryNewOutboundPeer() const
2446 : : {
2447 : 3391 : return m_try_another_outbound_peer;
2448 : : }
2449 : :
2450 : 4688 : void CConnman::SetTryNewOutboundPeer(bool flag)
2451 : : {
2452 : 4688 : m_try_another_outbound_peer = flag;
2453 [ - + - - ]: 4688 : LogDebug(BCLog::NET, "setting try another outbound peer=%s\n", flag ? "true" : "false");
2454 : 4688 : }
2455 : :
2456 : 0 : void CConnman::StartExtraBlockRelayPeers()
2457 : : {
2458 [ # # ]: 0 : LogDebug(BCLog::NET, "enabling extra block-relay-only peers\n");
2459 : 0 : m_start_extra_block_relay_peers = true;
2460 : 0 : }
2461 : :
2462 : : // Return the number of outbound connections that are full relay (not blocks only)
2463 : 0 : int CConnman::GetFullOutboundConnCount() const
2464 : : {
2465 : 0 : AssertLockNotHeld(m_nodes_mutex);
2466 : :
2467 : 0 : int nRelevant = 0;
2468 : 0 : {
2469 : 0 : LOCK(m_nodes_mutex);
2470 [ # # ]: 0 : for (const CNode* pnode : m_nodes) {
2471 [ # # # # ]: 0 : if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
2472 : : }
2473 : 0 : }
2474 : 0 : return nRelevant;
2475 : : }
2476 : :
2477 : : // Return the number of peers we have over our outbound connection limit
2478 : : // Exclude peers that are marked for disconnect, or are going to be
2479 : : // disconnected soon (eg ADDR_FETCH and FEELER)
2480 : : // Also exclude peers that haven't finished initial connection handshake yet
2481 : : // (so that we don't decide we're over our desired connection limit, and then
2482 : : // evict some peer that has finished the handshake)
2483 : 3391 : int CConnman::GetExtraFullOutboundCount() const
2484 : : {
2485 : 3391 : AssertLockNotHeld(m_nodes_mutex);
2486 : :
2487 : 3391 : int full_outbound_peers = 0;
2488 : 3391 : {
2489 : 3391 : LOCK(m_nodes_mutex);
2490 [ + + ]: 78348 : for (const CNode* pnode : m_nodes) {
2491 [ + + + + : 74957 : if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
+ + ]
2492 : 4078 : ++full_outbound_peers;
2493 : : }
2494 : : }
2495 : 3391 : }
2496 [ + - ]: 3391 : return std::max(full_outbound_peers - m_max_outbound_full_relay, 0);
2497 : : }
2498 : :
2499 : 0 : int CConnman::GetExtraBlockRelayCount() const
2500 : : {
2501 : 0 : AssertLockNotHeld(m_nodes_mutex);
2502 : :
2503 : 0 : int block_relay_peers = 0;
2504 : 0 : {
2505 : 0 : LOCK(m_nodes_mutex);
2506 [ # # ]: 0 : for (const CNode* pnode : m_nodes) {
2507 [ # # # # : 0 : if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
# # ]
2508 : 0 : ++block_relay_peers;
2509 : : }
2510 : : }
2511 : 0 : }
2512 [ # # ]: 0 : return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
2513 : : }
2514 : :
2515 : 0 : std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
2516 : : {
2517 : 0 : std::unordered_set<Network> networks{};
2518 [ # # ]: 0 : for (int n = 0; n < NET_MAX; n++) {
2519 : 0 : enum Network net = (enum Network)n;
2520 [ # # ]: 0 : if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
2521 [ # # # # : 0 : if (g_reachable_nets.Contains(net) && addrman.get().Size(net, std::nullopt) == 0) {
# # # # ]
2522 [ # # ]: 0 : networks.insert(net);
2523 : : }
2524 : : }
2525 : 0 : return networks;
2526 : 0 : }
2527 : :
2528 : 0 : bool CConnman::MultipleManualOrFullOutboundConns(Network net) const
2529 : : {
2530 : 0 : AssertLockHeld(m_nodes_mutex);
2531 : 0 : return m_network_conn_counts[net] > 1;
2532 : : }
2533 : :
2534 : 0 : bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
2535 : : {
2536 : 0 : AssertLockNotHeld(m_nodes_mutex);
2537 : :
2538 : 0 : std::array<Network, 5> nets{NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS};
2539 : 0 : std::shuffle(nets.begin(), nets.end(), FastRandomContext());
2540 : :
2541 : 0 : LOCK(m_nodes_mutex);
2542 [ # # ]: 0 : for (const auto net : nets) {
2543 [ # # # # : 0 : if (g_reachable_nets.Contains(net) && m_network_conn_counts[net] == 0 && addrman.get().Size(net) != 0) {
# # # # #
# ]
2544 : 0 : network = net;
2545 : 0 : return true;
2546 : : }
2547 : : }
2548 : :
2549 : : return false;
2550 : 0 : }
2551 : :
2552 : 0 : void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, std::span<const std::string> seed_nodes)
2553 : : {
2554 : 0 : AssertLockNotHeld(m_nodes_mutex);
2555 : 0 : AssertLockNotHeld(m_reconnections_mutex);
2556 : 0 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
2557 : :
2558 : 0 : FastRandomContext rng;
2559 : : // Connect to specific addresses
2560 [ # # ]: 0 : if (!connect.empty())
2561 : : {
2562 : : // Attempt v2 connection if we support v2 - we'll reconnect with v1 if our
2563 : : // peer doesn't support it or immediately disconnects us for another reason.
2564 [ # # ]: 0 : const bool use_v2transport(GetLocalServices() & NODE_P2P_V2);
2565 : 0 : for (int64_t nLoop = 0;; nLoop++)
2566 : : {
2567 [ # # ]: 0 : for (const std::string& strAddr : connect)
2568 : : {
2569 [ # # ]: 0 : CAddress addr(CService(), NODE_NONE);
2570 [ # # # # ]: 0 : OpenNetworkConnection(addr, false, {}, strAddr.c_str(), ConnectionType::MANUAL, /*use_v2transport=*/use_v2transport);
2571 [ # # # # ]: 0 : for (int i = 0; i < 10 && i < nLoop; i++)
2572 : : {
2573 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(500ms)) {
2574 : 0 : return;
2575 : : }
2576 : : }
2577 : 0 : }
2578 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(500ms)) {
2579 : : return;
2580 : : }
2581 [ # # ]: 0 : PerformReconnections();
2582 : 0 : }
2583 : : }
2584 : :
2585 : : // Initiate network connections
2586 : 0 : auto start = GetTime<std::chrono::microseconds>();
2587 : :
2588 : : // Minimum time before next feeler connection (in microseconds).
2589 : 0 : auto next_feeler = start + rng.rand_exp_duration(FEELER_INTERVAL);
2590 : 0 : auto next_extra_block_relay = start + rng.rand_exp_duration(EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
2591 [ # # ]: 0 : auto next_extra_network_peer{start + rng.rand_exp_duration(EXTRA_NETWORK_PEER_INTERVAL)};
2592 [ # # # # ]: 0 : const bool dnsseed = gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED);
2593 [ # # # # ]: 0 : bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
2594 [ # # # # ]: 0 : const bool use_seednodes{!gArgs.GetArgs("-seednode").empty()};
2595 : :
2596 : 0 : auto seed_node_timer = NodeClock::now();
2597 [ # # # # : 0 : bool add_addr_fetch{addrman.get().Size() == 0 && !seed_nodes.empty()};
# # ]
2598 : 0 : constexpr std::chrono::seconds ADD_NEXT_SEEDNODE = 10s;
2599 : :
2600 [ # # ]: 0 : if (!add_fixed_seeds) {
2601 [ # # ]: 0 : LogInfo("Fixed seeds are disabled\n");
2602 : : }
2603 : :
2604 [ # # # # ]: 0 : while (!m_interrupt_net->interrupted()) {
2605 [ # # ]: 0 : if (add_addr_fetch) {
2606 : 0 : add_addr_fetch = false;
2607 : 0 : const auto& seed{SpanPopBack(seed_nodes)};
2608 [ # # ]: 0 : AddAddrFetch(seed);
2609 : :
2610 [ # # # # ]: 0 : if (addrman.get().Size() == 0) {
2611 [ # # ]: 0 : LogInfo("Empty addrman, adding seednode (%s) to addrfetch\n", seed);
2612 : : } else {
2613 [ # # ]: 0 : LogInfo("Couldn't connect to peers from addrman after %d seconds. Adding seednode (%s) to addrfetch\n", ADD_NEXT_SEEDNODE.count(), seed);
2614 : : }
2615 : : }
2616 : :
2617 [ # # ]: 0 : ProcessAddrFetch();
2618 : :
2619 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(500ms)) {
2620 : : return;
2621 : : }
2622 : :
2623 [ # # ]: 0 : PerformReconnections();
2624 : :
2625 : 0 : CountingSemaphoreGrant<> grant(*semOutbound);
2626 [ # # # # ]: 0 : if (m_interrupt_net->interrupted()) {
2627 : : return;
2628 : : }
2629 : :
2630 [ # # ]: 0 : const std::unordered_set<Network> fixed_seed_networks{GetReachableEmptyNetworks()};
2631 [ # # # # ]: 0 : if (add_fixed_seeds && !fixed_seed_networks.empty()) {
2632 : : // When the node starts with an empty peers.dat, there are a few other sources of peers before
2633 : : // we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
2634 : : // If none of those are available, we fallback on to fixed seeds immediately, else we allow
2635 : : // 60 seconds for any of those sources to populate addrman.
2636 : 0 : bool add_fixed_seeds_now = false;
2637 : : // It is cheapest to check if enough time has passed first.
2638 [ # # ]: 0 : if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
2639 : 0 : add_fixed_seeds_now = true;
2640 [ # # ]: 0 : LogInfo("Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
2641 : : }
2642 : :
2643 : : // Perform cheap checks before locking a mutex.
2644 [ # # ]: 0 : else if (!dnsseed && !use_seednodes) {
2645 [ # # ]: 0 : LOCK(m_added_nodes_mutex);
2646 [ # # ]: 0 : if (m_added_node_params.empty()) {
2647 : 0 : add_fixed_seeds_now = true;
2648 [ # # ]: 0 : LogInfo("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
2649 : : }
2650 : 0 : }
2651 : :
2652 [ # # ]: 0 : if (add_fixed_seeds_now) {
2653 [ # # ]: 0 : std::vector<CAddress> seed_addrs{ConvertSeeds(m_params.FixedSeeds())};
2654 : : // We will not make outgoing connections to peers that are unreachable
2655 : : // (e.g. because of -onlynet configuration).
2656 : : // Therefore, we do not add them to addrman in the first place.
2657 : : // In case previously unreachable networks become reachable
2658 : : // (e.g. in case of -onlynet changes by the user), fixed seeds will
2659 : : // be loaded only for networks for which we have no addresses.
2660 [ # # ]: 0 : seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
2661 : 0 : [&fixed_seed_networks](const CAddress& addr) { return !fixed_seed_networks.contains(addr.GetNetwork()); }),
2662 [ # # ]: 0 : seed_addrs.end());
2663 [ # # ]: 0 : CNetAddr local;
2664 [ # # # # ]: 0 : local.SetInternal("fixedseeds");
2665 [ # # ]: 0 : addrman.get().Add(seed_addrs, local);
2666 : 0 : add_fixed_seeds = false;
2667 [ # # # # ]: 0 : LogInfo("Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
2668 : 0 : }
2669 : : }
2670 : :
2671 : : //
2672 : : // Choose an address to connect to based on most recently seen
2673 : : //
2674 [ # # ]: 0 : CAddress addrConnect;
2675 : :
2676 : : // Only connect out to one peer per ipv4/ipv6 network group (/16 for IPv4).
2677 : 0 : int nOutboundFullRelay = 0;
2678 : 0 : int nOutboundBlockRelay = 0;
2679 : 0 : int outbound_privacy_network_peers = 0;
2680 [ # # ]: 0 : std::set<std::vector<unsigned char>> outbound_ipv46_peer_netgroups;
2681 : :
2682 : 0 : {
2683 [ # # ]: 0 : LOCK(m_nodes_mutex);
2684 [ # # ]: 0 : for (const CNode* pnode : m_nodes) {
2685 [ # # ]: 0 : if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
2686 [ # # ]: 0 : if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
2687 : :
2688 : : // Make sure our persistent outbound slots to ipv4/ipv6 peers belong to different netgroups.
2689 [ # # ]: 0 : switch (pnode->m_conn_type) {
2690 : : // We currently don't take inbound connections into account. Since they are
2691 : : // free to make, an attacker could make them to prevent us from connecting to
2692 : : // certain peers.
2693 : : case ConnectionType::INBOUND:
2694 : : // Short-lived outbound connections should not affect how we select outbound
2695 : : // peers from addrman.
2696 : : case ConnectionType::ADDR_FETCH:
2697 : : case ConnectionType::FEELER:
2698 : : case ConnectionType::PRIVATE_BROADCAST:
2699 : : break;
2700 : 0 : case ConnectionType::MANUAL:
2701 : 0 : case ConnectionType::OUTBOUND_FULL_RELAY:
2702 : 0 : case ConnectionType::BLOCK_RELAY:
2703 : 0 : const CAddress address{pnode->addr};
2704 [ # # # # : 0 : if (address.IsTor() || address.IsI2P() || address.IsCJDNS()) {
# # ]
2705 : : // Since our addrman-groups for these networks are
2706 : : // random, without relation to the route we
2707 : : // take to connect to these peers or to the
2708 : : // difficulty in obtaining addresses with diverse
2709 : : // groups, we don't worry about diversity with
2710 : : // respect to our addrman groups when connecting to
2711 : : // these networks.
2712 : 0 : ++outbound_privacy_network_peers;
2713 : : } else {
2714 [ # # # # ]: 0 : outbound_ipv46_peer_netgroups.insert(m_netgroupman.GetGroup(address));
2715 : : }
2716 : : } // no default case, so the compiler can warn about missing cases
2717 : : }
2718 : 0 : }
2719 : :
2720 [ # # # # ]: 0 : if (!seed_nodes.empty() && nOutboundFullRelay < SEED_OUTBOUND_CONNECTION_THRESHOLD) {
2721 [ # # ]: 0 : if (NodeClock::now() > seed_node_timer + ADD_NEXT_SEEDNODE) {
2722 : 0 : seed_node_timer = NodeClock::now();
2723 : 0 : add_addr_fetch = true;
2724 : : }
2725 : : }
2726 : :
2727 : 0 : ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
2728 : 0 : auto now = GetTime<std::chrono::microseconds>();
2729 : 0 : bool anchor = false;
2730 : 0 : bool fFeeler = false;
2731 : 0 : std::optional<Network> preferred_net;
2732 : :
2733 : : // Determine what type of connection to open. Opening
2734 : : // BLOCK_RELAY connections to addresses from anchors.dat gets the highest
2735 : : // priority. Then we open OUTBOUND_FULL_RELAY priority until we
2736 : : // meet our full-relay capacity. Then we open BLOCK_RELAY connection
2737 : : // until we hit our block-relay-only peer limit.
2738 : : // GetTryNewOutboundPeer() gets set when a stale tip is detected, so we
2739 : : // try opening an additional OUTBOUND_FULL_RELAY connection. If none of
2740 : : // these conditions are met, check to see if it's time to try an extra
2741 : : // block-relay-only peer (to confirm our tip is current, see below) or the next_feeler
2742 : : // timer to decide if we should open a FEELER.
2743 : :
2744 [ # # # # ]: 0 : if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) {
2745 : : conn_type = ConnectionType::BLOCK_RELAY;
2746 : : anchor = true;
2747 [ # # ]: 0 : } else if (nOutboundFullRelay < m_max_outbound_full_relay) {
2748 : : // OUTBOUND_FULL_RELAY
2749 [ # # ]: 0 : } else if (nOutboundBlockRelay < m_max_outbound_block_relay) {
2750 : : conn_type = ConnectionType::BLOCK_RELAY;
2751 [ # # # # ]: 0 : } else if (GetTryNewOutboundPeer()) {
2752 : : // OUTBOUND_FULL_RELAY
2753 [ # # # # ]: 0 : } else if (now > next_extra_block_relay && m_start_extra_block_relay_peers) {
2754 : : // Periodically connect to a peer (using regular outbound selection
2755 : : // methodology from addrman) and stay connected long enough to sync
2756 : : // headers, but not much else.
2757 : : //
2758 : : // Then disconnect the peer, if we haven't learned anything new.
2759 : : //
2760 : : // The idea is to make eclipse attacks very difficult to pull off,
2761 : : // because every few minutes we're finding a new peer to learn headers
2762 : : // from.
2763 : : //
2764 : : // This is similar to the logic for trying extra outbound (full-relay)
2765 : : // peers, except:
2766 : : // - we do this all the time on an exponential timer, rather than just when
2767 : : // our tip is stale
2768 : : // - we potentially disconnect our next-youngest block-relay-only peer, if our
2769 : : // newest block-relay-only peer delivers a block more recently.
2770 : : // See the eviction logic in net_processing.cpp.
2771 : : //
2772 : : // Because we can promote these connections to block-relay-only
2773 : : // connections, they do not get their own ConnectionType enum
2774 : : // (similar to how we deal with extra outbound peers).
2775 : 0 : next_extra_block_relay = now + rng.rand_exp_duration(EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
2776 : 0 : conn_type = ConnectionType::BLOCK_RELAY;
2777 [ # # ]: 0 : } else if (now > next_feeler) {
2778 : 0 : next_feeler = now + rng.rand_exp_duration(FEELER_INTERVAL);
2779 : 0 : conn_type = ConnectionType::FEELER;
2780 : 0 : fFeeler = true;
2781 [ # # ]: 0 : } else if (nOutboundFullRelay == m_max_outbound_full_relay &&
2782 [ # # ]: 0 : m_max_outbound_full_relay == MAX_OUTBOUND_FULL_RELAY_CONNECTIONS &&
2783 [ # # # # : 0 : now > next_extra_network_peer &&
# # ]
2784 [ # # ]: 0 : MaybePickPreferredNetwork(preferred_net)) {
2785 : : // Full outbound connection management: Attempt to get at least one
2786 : : // outbound peer from each reachable network by making extra connections
2787 : : // and then protecting "only" peers from a network during outbound eviction.
2788 : : // This is not attempted if the user changed -maxconnections to a value
2789 : : // so low that less than MAX_OUTBOUND_FULL_RELAY_CONNECTIONS are made,
2790 : : // to prevent interactions with otherwise protected outbound peers.
2791 : 0 : next_extra_network_peer = now + rng.rand_exp_duration(EXTRA_NETWORK_PEER_INTERVAL);
2792 : : } else {
2793 : : // skip to next iteration of while loop
2794 : 0 : continue;
2795 : : }
2796 : :
2797 [ # # ]: 0 : addrman.get().ResolveCollisions();
2798 : :
2799 : 0 : const auto current_time{NodeClock::now()};
2800 : 0 : int nTries = 0;
2801 [ # # ]: 0 : const auto reachable_nets{g_reachable_nets.All()};
2802 : :
2803 [ # # # # ]: 0 : while (!m_interrupt_net->interrupted()) {
2804 [ # # # # ]: 0 : if (anchor && !m_anchors.empty()) {
2805 : 0 : const CAddress addr = m_anchors.back();
2806 : 0 : m_anchors.pop_back();
2807 [ # # # # : 0 : if (!addr.IsValid() || IsLocal(addr) || !g_reachable_nets.Contains(addr) ||
# # # # #
# # # #
# ]
2808 [ # # # # : 0 : !m_msgproc->HasAllDesirableServiceFlags(addr.nServices) ||
# # ]
2809 [ # # ]: 0 : outbound_ipv46_peer_netgroups.contains(m_netgroupman.GetGroup(addr))) continue;
2810 : 0 : addrConnect = addr;
2811 [ # # # # : 0 : LogDebug(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToStringAddrPort());
# # # # ]
2812 : 0 : break;
2813 : 0 : }
2814 : :
2815 : : // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
2816 : : // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
2817 : : // already-connected network ranges, ...) before trying new addrman addresses.
2818 : 0 : nTries++;
2819 [ # # ]: 0 : if (nTries > 100)
2820 : : break;
2821 : :
2822 [ # # ]: 0 : CAddress addr;
2823 : 0 : NodeSeconds addr_last_try{0s};
2824 : :
2825 [ # # ]: 0 : if (fFeeler) {
2826 : : // First, try to get a tried table collision address. This returns
2827 : : // an empty (invalid) address if there are no collisions to try.
2828 [ # # ]: 0 : std::tie(addr, addr_last_try) = addrman.get().SelectTriedCollision();
2829 : :
2830 [ # # # # ]: 0 : if (!addr.IsValid()) {
2831 : : // No tried table collisions. Select a new table address
2832 : : // for our feeler.
2833 [ # # ]: 0 : std::tie(addr, addr_last_try) = addrman.get().Select(true, reachable_nets);
2834 [ # # # # ]: 0 : } else if (AlreadyConnectedToAddress(addr)) {
2835 : : // If test-before-evict logic would have us connect to a
2836 : : // peer that we're already connected to, just mark that
2837 : : // address as Good(). We won't be able to initiate the
2838 : : // connection anyway, so this avoids inadvertently evicting
2839 : : // a currently-connected peer.
2840 [ # # ]: 0 : addrman.get().Good(addr);
2841 : : // Select a new table address for our feeler instead.
2842 [ # # ]: 0 : std::tie(addr, addr_last_try) = addrman.get().Select(true, reachable_nets);
2843 : : }
2844 : : } else {
2845 : : // Not a feeler
2846 : : // If preferred_net has a value set, pick an extra outbound
2847 : : // peer from that network. The eviction logic in net_processing
2848 : : // ensures that a peer from another network will be evicted.
2849 [ # # ]: 0 : std::tie(addr, addr_last_try) = preferred_net.has_value()
2850 [ # # # # : 0 : ? addrman.get().Select(false, {*preferred_net})
# # # # #
# # # ]
2851 [ # # ]: 0 : : addrman.get().Select(false, reachable_nets);
2852 : : }
2853 : :
2854 : : // Require outbound IPv4/IPv6 connections, other than feelers, to be to distinct network groups
2855 [ # # # # : 0 : if (!fFeeler && outbound_ipv46_peer_netgroups.contains(m_netgroupman.GetGroup(addr))) {
# # # # ]
2856 : 0 : continue;
2857 : : }
2858 : :
2859 : : // if we selected an invalid or local address, restart
2860 [ # # # # : 0 : if (!addr.IsValid() || IsLocal(addr)) {
# # # # ]
2861 : : break;
2862 : : }
2863 : :
2864 [ # # # # ]: 0 : if (!g_reachable_nets.Contains(addr)) {
2865 : 0 : continue;
2866 : : }
2867 : :
2868 : : // only consider very recently tried nodes after 30 failed attempts
2869 [ # # # # ]: 0 : if (current_time - addr_last_try < 10min && nTries < 30) {
2870 : 0 : continue;
2871 : : }
2872 : :
2873 : : // for non-feelers, require all the services we'll want,
2874 : : // for feelers, only require they be a full node (only because most
2875 : : // SPV clients don't have a good address DB available)
2876 [ # # # # : 0 : if (!fFeeler && !m_msgproc->HasAllDesirableServiceFlags(addr.nServices)) {
# # ]
2877 : 0 : continue;
2878 [ # # # # ]: 0 : } else if (fFeeler && !MayHaveUsefulAddressDB(addr.nServices)) {
2879 : 0 : continue;
2880 : : }
2881 : :
2882 : : // Do not connect to bad ports, unless 50 invalid addresses have been selected already.
2883 [ # # # # : 0 : if (nTries < 50 && (addr.IsIPv4() || addr.IsIPv6()) && IsBadPort(addr.GetPort())) {
# # # # #
# # # ]
2884 : 0 : continue;
2885 : : }
2886 : :
2887 : : // Do not make automatic outbound connections to addnode peers, to
2888 : : // not use our limited outbound slots for them and to ensure
2889 : : // addnode connections benefit from their intended protections.
2890 [ # # # # ]: 0 : if (AddedNodesContain(addr)) {
2891 [ # # # # : 0 : LogDebug(BCLog::NET, "Not making automatic %s%s connection to %s peer selected for manual (addnode) connection%s\n",
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
2892 : : preferred_net.has_value() ? "network-specific " : "",
2893 : : ConnectionTypeAsString(conn_type), GetNetworkName(addr.GetNetwork()),
2894 : : fLogIPs ? strprintf(": %s", addr.ToStringAddrPort()) : "");
2895 : 0 : continue;
2896 : 0 : }
2897 : :
2898 : 0 : addrConnect = addr;
2899 : : break;
2900 : 0 : }
2901 : :
2902 [ # # # # ]: 0 : if (addrConnect.IsValid()) {
2903 [ # # ]: 0 : if (fFeeler) {
2904 : : // Add small amount of random noise before connection to avoid synchronization.
2905 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(rng.rand_uniform_duration<CThreadInterrupt::Clock>(FEELER_SLEEP_WINDOW))) {
2906 : 0 : return;
2907 : : }
2908 [ # # # # : 0 : LogDebug(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToStringAddrPort());
# # # # ]
2909 : : }
2910 : :
2911 [ # # # # : 0 : if (preferred_net != std::nullopt) LogDebug(BCLog::NET, "Making network specific connection to %s on %s.\n", addrConnect.ToStringAddrPort(), GetNetworkName(preferred_net.value()));
# # # # #
# # # #
# ]
2912 : :
2913 : : // Record addrman failure attempts when node has at least 2 persistent outbound connections to peers with
2914 : : // different netgroups in ipv4/ipv6 networks + all peers in Tor/I2P/CJDNS networks.
2915 : : // Don't record addrman failure attempts when node is offline. This can be identified since all local
2916 : : // network connections (if any) belong in the same netgroup, and the size of `outbound_ipv46_peer_netgroups` would only be 1.
2917 [ # # ]: 0 : const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(m_max_automatic_connections - 1, 2)};
2918 : : // Use BIP324 transport when both us and them have NODE_V2_P2P set.
2919 [ # # ]: 0 : const bool use_v2transport(addrConnect.nServices & GetLocalServices() & NODE_P2P_V2);
2920 [ # # ]: 0 : OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*pszDest=*/nullptr, conn_type, use_v2transport);
2921 : : }
2922 : 0 : }
2923 : 0 : }
2924 : :
2925 : 0 : std::vector<CAddress> CConnman::GetCurrentBlockRelayOnlyConns() const
2926 : : {
2927 : 0 : AssertLockNotHeld(m_nodes_mutex);
2928 : 0 : std::vector<CAddress> ret;
2929 [ # # ]: 0 : LOCK(m_nodes_mutex);
2930 [ # # ]: 0 : for (const CNode* pnode : m_nodes) {
2931 [ # # ]: 0 : if (pnode->IsBlockOnlyConn()) {
2932 [ # # ]: 0 : ret.push_back(pnode->addr);
2933 : : }
2934 : : }
2935 : :
2936 [ # # ]: 0 : return ret;
2937 : 0 : }
2938 : :
2939 : 3399 : std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo(bool include_connected) const
2940 : : {
2941 : 3399 : AssertLockNotHeld(m_nodes_mutex);
2942 : :
2943 : 3399 : std::vector<AddedNodeInfo> ret;
2944 : :
2945 [ + - ]: 3399 : std::list<AddedNodeParams> lAddresses(0);
2946 : 3399 : {
2947 [ + - ]: 3399 : LOCK(m_added_nodes_mutex);
2948 [ - + + - ]: 3399 : ret.reserve(m_added_node_params.size());
2949 [ + - ]: 3399 : std::copy(m_added_node_params.cbegin(), m_added_node_params.cend(), std::back_inserter(lAddresses));
2950 : 0 : }
2951 : :
2952 : :
2953 : : // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
2954 [ + - ]: 3399 : std::map<CService, bool> mapConnected;
2955 : 3399 : std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
2956 : 3399 : {
2957 [ + - ]: 3399 : LOCK(m_nodes_mutex);
2958 [ + + ]: 78356 : for (const CNode* pnode : m_nodes) {
2959 [ + - + + ]: 74957 : if (pnode->addr.IsValid()) {
2960 [ + - ]: 65090 : mapConnected[pnode->addr] = pnode->IsInboundConn();
2961 : : }
2962 [ - + ]: 74957 : std::string addrName{pnode->m_addr_name};
2963 [ + - ]: 74957 : if (!addrName.empty()) {
2964 [ + - ]: 74957 : mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(), static_cast<const CService&>(pnode->addr));
2965 : : }
2966 : 74957 : }
2967 : 0 : }
2968 : :
2969 [ + + ]: 4606 : for (const auto& addr : lAddresses) {
2970 [ + - + - : 2414 : CService service{MaybeFlipIPv6toCJDNS(LookupNumeric(addr.m_added_node, GetDefaultPort(addr.m_added_node)))};
+ - + - ]
2971 [ + - + - ]: 1207 : AddedNodeInfo addedNode{addr, CService(), false, false};
2972 [ + - + + ]: 1207 : if (service.IsValid()) {
2973 : : // strAddNode is an IP:port
2974 [ + - ]: 289 : auto it = mapConnected.find(service);
2975 [ + + ]: 289 : if (it != mapConnected.end()) {
2976 [ + + ]: 34 : if (!include_connected) {
2977 : 19 : continue;
2978 : : }
2979 : 15 : addedNode.resolvedAddress = service;
2980 : 15 : addedNode.fConnected = true;
2981 : 15 : addedNode.fInbound = it->second;
2982 : : }
2983 : : } else {
2984 : : // strAddNode is a name
2985 : 918 : auto it = mapConnectedByName.find(addr.m_added_node);
2986 [ + + ]: 918 : if (it != mapConnectedByName.end()) {
2987 [ + + ]: 88 : if (!include_connected) {
2988 : 72 : continue;
2989 : : }
2990 : 16 : addedNode.resolvedAddress = it->second.second;
2991 : 16 : addedNode.fConnected = true;
2992 : 16 : addedNode.fInbound = it->second.first;
2993 : : }
2994 : : }
2995 [ + - ]: 1116 : ret.emplace_back(std::move(addedNode));
2996 : 1207 : }
2997 : :
2998 : 3399 : return ret;
2999 : 3399 : }
3000 : :
3001 : 0 : void CConnman::ThreadOpenAddedConnections()
3002 : : {
3003 : 0 : AssertLockNotHeld(m_nodes_mutex);
3004 : 0 : AssertLockNotHeld(m_reconnections_mutex);
3005 : 0 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
3006 : :
3007 : 0 : while (true)
3008 : : {
3009 : 0 : CountingSemaphoreGrant<> grant(*semAddnode);
3010 [ # # ]: 0 : std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo(/*include_connected=*/false);
3011 : 0 : bool tried = false;
3012 [ # # ]: 0 : for (const AddedNodeInfo& info : vInfo) {
3013 [ # # ]: 0 : if (!grant) {
3014 : : // If we've used up our semaphore and need a new one, let's not wait here since while we are waiting
3015 : : // the addednodeinfo state might change.
3016 : : break;
3017 : : }
3018 : 0 : tried = true;
3019 [ # # ]: 0 : CAddress addr(CService(), NODE_NONE);
3020 [ # # ]: 0 : OpenNetworkConnection(addr, false, std::move(grant), info.m_params.m_added_node.c_str(), ConnectionType::MANUAL, info.m_params.m_use_v2transport);
3021 [ # # # # ]: 0 : if (!m_interrupt_net->sleep_for(500ms)) return;
3022 : 0 : grant = CountingSemaphoreGrant<>(*semAddnode, /*fTry=*/true);
3023 : 0 : }
3024 : : // See if any reconnections are desired.
3025 [ # # ]: 0 : PerformReconnections();
3026 : : // Retry every 60 seconds if a connection was attempted, otherwise two seconds
3027 [ # # # # : 0 : if (!m_interrupt_net->sleep_for(tried ? 60s : 2s)) {
# # ]
3028 : : return;
3029 : : }
3030 : 0 : }
3031 : : }
3032 : :
3033 : : // if successful, this moves the passed grant to the constructed node
3034 : 93697 : bool CConnman::OpenNetworkConnection(const CAddress& addrConnect,
3035 : : bool fCountFailure,
3036 : : CountingSemaphoreGrant<>&& grant_outbound,
3037 : : const char* pszDest,
3038 : : ConnectionType conn_type,
3039 : : bool use_v2transport,
3040 : : const std::optional<Proxy>& proxy_override)
3041 : : {
3042 : 93697 : AssertLockNotHeld(m_nodes_mutex);
3043 : 93697 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
3044 [ - + ]: 93697 : assert(conn_type != ConnectionType::INBOUND);
3045 : :
3046 : : //
3047 : : // Initiate outbound network connection
3048 : : //
3049 [ + + ]: 93697 : if (m_interrupt_net->interrupted()) {
3050 : : return false;
3051 : : }
3052 [ + + ]: 18907 : if (!fNetworkActive) {
3053 : : return false;
3054 : : }
3055 [ + + ]: 18702 : if (!pszDest) {
3056 [ - + - - : 1931 : bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect));
- - ]
3057 [ + + + - : 1931 : if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) {
+ + ]
3058 : 614 : return false;
3059 : : }
3060 [ + + ]: 16771 : } else if (AlreadyConnectedToHost(pszDest)) {
3061 : : return false;
3062 : : }
3063 : :
3064 [ + - ]: 17952 : CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type, use_v2transport, proxy_override);
3065 : :
3066 [ + + ]: 17952 : if (!pnode)
3067 : : return false;
3068 : 14211 : pnode->grantOutbound = std::move(grant_outbound);
3069 : :
3070 : 14211 : m_msgproc->InitializeNode(*pnode, m_local_services);
3071 : 14211 : {
3072 : 14211 : LOCK(m_nodes_mutex);
3073 [ + - ]: 14211 : m_nodes.push_back(pnode);
3074 : :
3075 : : // update connection count by network
3076 [ + + + - ]: 14211 : if (pnode->IsManualOrFullOutboundConn()) ++m_network_conn_counts[pnode->addr.GetNetwork()];
3077 : 14211 : }
3078 : :
3079 : : TRACEPOINT(net, outbound_connection,
3080 : : pnode->GetId(),
3081 : : pnode->m_addr_name.c_str(),
3082 : : pnode->ConnectionTypeAsString().c_str(),
3083 : : pnode->ConnectedThroughNetwork(),
3084 : 14211 : GetNodeCount(ConnectionDirection::Out));
3085 : :
3086 : 14211 : return true;
3087 : : }
3088 : :
3089 : 0 : std::optional<Network> CConnman::PrivateBroadcast::PickNetwork(std::optional<Proxy>& proxy) const
3090 : : {
3091 : 0 : prevector<4, Network> nets;
3092 : 0 : std::optional<Proxy> clearnet_proxy;
3093 [ # # ]: 0 : proxy.reset();
3094 [ # # # # ]: 0 : if (g_reachable_nets.Contains(NET_ONION)) {
3095 : 0 : nets.push_back(NET_ONION);
3096 : :
3097 [ # # # # ]: 0 : clearnet_proxy = ProxyForIPv4or6();
3098 [ # # ]: 0 : if (clearnet_proxy.has_value()) {
3099 [ # # # # ]: 0 : if (g_reachable_nets.Contains(NET_IPV4)) {
3100 : 0 : nets.push_back(NET_IPV4);
3101 : : }
3102 [ # # # # ]: 0 : if (g_reachable_nets.Contains(NET_IPV6)) {
3103 : 0 : nets.push_back(NET_IPV6);
3104 : : }
3105 : : }
3106 : : }
3107 [ # # # # ]: 0 : if (g_reachable_nets.Contains(NET_I2P)) {
3108 : 0 : nets.push_back(NET_I2P);
3109 : : }
3110 : :
3111 [ # # # # ]: 0 : if (nets.empty()) {
3112 : 0 : return std::nullopt;
3113 : : }
3114 : :
3115 [ # # # # ]: 0 : const Network net{nets[FastRandomContext{}.randrange(nets.size())]};
3116 [ # # ]: 0 : if (net == NET_IPV4 || net == NET_IPV6) {
3117 [ # # ]: 0 : proxy = clearnet_proxy;
3118 : : }
3119 : 0 : return net;
3120 : 0 : }
3121 : :
3122 : 0 : size_t CConnman::PrivateBroadcast::NumToOpen() const
3123 : : {
3124 : 0 : return m_num_to_open;
3125 : : }
3126 : :
3127 : 3416 : void CConnman::PrivateBroadcast::NumToOpenAdd(size_t n)
3128 : : {
3129 : 3416 : m_num_to_open += n;
3130 : 3416 : m_num_to_open.notify_all();
3131 : 3416 : }
3132 : :
3133 : 2 : size_t CConnman::PrivateBroadcast::NumToOpenSub(size_t n)
3134 : : {
3135 : 2 : size_t current_value{m_num_to_open.load()};
3136 : 2 : size_t new_value;
3137 : 2 : do {
3138 [ - + ]: 2 : new_value = current_value > n ? current_value - n : 0;
3139 [ - + ]: 2 : } while (!m_num_to_open.compare_exchange_strong(current_value, new_value));
3140 : 2 : return new_value;
3141 : : }
3142 : :
3143 : 0 : void CConnman::PrivateBroadcast::NumToOpenWait() const
3144 : : {
3145 : 0 : m_num_to_open.wait(0);
3146 : 0 : }
3147 : :
3148 : 0 : std::optional<Proxy> CConnman::PrivateBroadcast::ProxyForIPv4or6() const
3149 : : {
3150 [ # # ]: 0 : if (m_outbound_tor_ok_at_least_once.load()) {
3151 [ # # ]: 0 : if (const auto tor_proxy = GetProxy(NET_ONION)) {
3152 : : return tor_proxy;
3153 : 0 : }
3154 : : }
3155 : 0 : return std::nullopt;
3156 : : }
3157 : :
3158 : : Mutex NetEventsInterface::g_msgproc_mutex;
3159 : :
3160 : 0 : void CConnman::ThreadMessageHandler()
3161 : : {
3162 : 0 : AssertLockNotHeld(m_nodes_mutex);
3163 : :
3164 : 0 : LOCK(NetEventsInterface::g_msgproc_mutex);
3165 : :
3166 [ # # ]: 0 : while (!flagInterruptMsgProc)
3167 : : {
3168 : 0 : bool fMoreWork = false;
3169 : :
3170 : 0 : {
3171 : : // Randomize the order in which we process messages from/to our peers.
3172 : : // This prevents attacks in which an attacker exploits having multiple
3173 : : // consecutive connections in the m_nodes list.
3174 [ # # ]: 0 : const NodesSnapshot snap{*this, /*shuffle=*/true};
3175 : :
3176 [ # # ]: 0 : for (CNode* pnode : snap.Nodes()) {
3177 [ # # ]: 0 : if (pnode->fDisconnect)
3178 : 0 : continue;
3179 : :
3180 : : // Receive messages
3181 [ # # ]: 0 : bool fMoreNodeWork{m_msgproc->ProcessMessages(*pnode, flagInterruptMsgProc)};
3182 [ # # # # ]: 0 : fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
3183 [ # # ]: 0 : if (flagInterruptMsgProc)
3184 : : return;
3185 : : // Send messages
3186 [ # # ]: 0 : m_msgproc->SendMessages(*pnode);
3187 : :
3188 [ # # ]: 0 : if (flagInterruptMsgProc)
3189 : : return;
3190 : : }
3191 [ # # ]: 0 : }
3192 : :
3193 [ # # ]: 0 : WAIT_LOCK(mutexMsgProc, lock);
3194 [ # # ]: 0 : if (!fMoreWork) {
3195 [ # # # # ]: 0 : condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this]() EXCLUSIVE_LOCKS_REQUIRED(mutexMsgProc) { return fMsgProcWake; });
3196 : : }
3197 [ # # ]: 0 : fMsgProcWake = false;
3198 : 0 : }
3199 : 0 : }
3200 : :
3201 : 0 : void CConnman::ThreadI2PAcceptIncoming()
3202 : : {
3203 : 0 : AssertLockNotHeld(m_nodes_mutex);
3204 : :
3205 : 0 : static constexpr auto err_wait_begin = 1s;
3206 : 0 : static constexpr auto err_wait_cap = 5min;
3207 : 0 : auto err_wait = err_wait_begin;
3208 : :
3209 : 0 : bool advertising_listen_addr = false;
3210 : 0 : i2p::Connection conn;
3211 : :
3212 : 0 : auto SleepOnFailure = [&]() {
3213 : 0 : m_interrupt_net->sleep_for(err_wait);
3214 [ # # ]: 0 : if (err_wait < err_wait_cap) {
3215 : 0 : err_wait += 1s;
3216 : : }
3217 : 0 : };
3218 : :
3219 [ # # # # ]: 0 : while (!m_interrupt_net->interrupted()) {
3220 : :
3221 [ # # # # ]: 0 : if (!m_i2p_sam_session->Listen(conn)) {
3222 [ # # # # : 0 : if (advertising_listen_addr && conn.me.IsValid()) {
# # ]
3223 [ # # ]: 0 : RemoveLocal(conn.me);
3224 : : advertising_listen_addr = false;
3225 : : }
3226 [ # # ]: 0 : SleepOnFailure();
3227 : 0 : continue;
3228 : : }
3229 : :
3230 [ # # ]: 0 : if (!advertising_listen_addr) {
3231 [ # # ]: 0 : AddLocal(conn.me, LOCAL_MANUAL);
3232 : : advertising_listen_addr = true;
3233 : : }
3234 : :
3235 [ # # # # ]: 0 : if (!m_i2p_sam_session->Accept(conn)) {
3236 [ # # ]: 0 : SleepOnFailure();
3237 : 0 : continue;
3238 : : }
3239 : :
3240 [ # # ]: 0 : CreateNodeFromAcceptedSocket(std::move(conn.sock), NetPermissionFlags::None, conn.me, conn.peer);
3241 : :
3242 : 0 : err_wait = err_wait_begin;
3243 : : }
3244 : 0 : }
3245 : :
3246 : 0 : void CConnman::ThreadPrivateBroadcast()
3247 : : {
3248 : 0 : AssertLockNotHeld(m_nodes_mutex);
3249 : 0 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
3250 : :
3251 : 0 : size_t addrman_num_bad_addresses{0};
3252 [ # # ]: 0 : while (!m_interrupt_net->interrupted()) {
3253 : :
3254 [ # # ]: 0 : if (!fNetworkActive) {
3255 : 0 : m_interrupt_net->sleep_for(5s);
3256 : 0 : continue;
3257 : : }
3258 : :
3259 : 0 : CountingSemaphoreGrant<> conn_max_grant{m_private_broadcast.m_sem_conn_max}; // Would block if too many are opened.
3260 : :
3261 [ # # ]: 0 : m_private_broadcast.NumToOpenWait();
3262 : :
3263 [ # # # # ]: 0 : if (m_interrupt_net->interrupted()) {
3264 : : break;
3265 : : }
3266 : :
3267 : 0 : std::optional<Proxy> proxy;
3268 [ # # ]: 0 : const std::optional<Network> net{m_private_broadcast.PickNetwork(proxy)};
3269 [ # # ]: 0 : if (!net.has_value()) {
3270 [ # # ]: 0 : LogWarning("Unable to open -privatebroadcast connections: neither Tor nor I2P is reachable");
3271 [ # # ]: 0 : m_interrupt_net->sleep_for(5s);
3272 : 0 : continue;
3273 : : }
3274 : :
3275 [ # # # # : 0 : const auto [addr, _] = addrman.get().Select(/*new_only=*/false, {net.value()});
# # ]
3276 : :
3277 [ # # # # : 0 : if (!addr.IsValid() || IsLocal(addr)) {
# # # # ]
3278 : 0 : ++addrman_num_bad_addresses;
3279 [ # # ]: 0 : if (addrman_num_bad_addresses > 100) {
3280 [ # # # # : 0 : LogDebug(BCLog::PRIVBROADCAST, "Connections needed but addrman keeps returning bad addresses, will retry");
# # ]
3281 [ # # ]: 0 : m_interrupt_net->sleep_for(500ms);
3282 : : }
3283 : 0 : continue;
3284 : 0 : }
3285 : 0 : addrman_num_bad_addresses = 0;
3286 : :
3287 [ # # ]: 0 : auto target_str{addr.ToStringAddrPort()};
3288 [ # # ]: 0 : if (proxy.has_value()) {
3289 [ # # # # ]: 0 : target_str += " through the proxy at " + proxy->ToString();
3290 : : }
3291 : :
3292 [ # # ]: 0 : const bool use_v2transport(addr.nServices & GetLocalServices() & NODE_P2P_V2);
3293 : :
3294 [ # # # # ]: 0 : if (OpenNetworkConnection(addr,
3295 : : /*fCountFailure=*/true,
3296 : : std::move(conn_max_grant),
3297 : : /*pszDest=*/nullptr,
3298 : : ConnectionType::PRIVATE_BROADCAST,
3299 : : use_v2transport,
3300 : : proxy)) {
3301 [ # # ]: 0 : const size_t remaining{m_private_broadcast.NumToOpenSub(1)};
3302 [ # # # # : 0 : LogDebug(BCLog::PRIVBROADCAST, "Socket connected to %s; remaining connections to open: %d", target_str, remaining);
# # ]
3303 : : } else {
3304 [ # # ]: 0 : const size_t remaining{m_private_broadcast.NumToOpen()};
3305 [ # # ]: 0 : if (remaining == 0) {
3306 [ # # # # : 0 : LogDebug(BCLog::PRIVBROADCAST, "Failed to connect to %s, will not retry, no more connections needed", target_str);
# # ]
3307 : : } else {
3308 [ # # # # : 0 : LogDebug(BCLog::PRIVBROADCAST, "Failed to connect to %s, will retry to a different address; remaining connections to open: %d", target_str, remaining);
# # ]
3309 [ # # ]: 0 : m_interrupt_net->sleep_for(100ms); // Prevent busy loop if OpenNetworkConnection() fails fast repeatedly.
3310 : : }
3311 : : }
3312 [ # # ]: 0 : }
3313 : 0 : }
3314 : :
3315 : 18450 : bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError, NetPermissionFlags permissions)
3316 : : {
3317 : 18450 : int nOne = 1;
3318 : :
3319 : : // Create socket for listening for incoming connections
3320 : 18450 : struct sockaddr_storage sockaddr;
3321 : 18450 : socklen_t len = sizeof(sockaddr);
3322 [ + + ]: 18450 : if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
3323 : : {
3324 [ + - + - ]: 3762 : strError = Untranslated(strprintf("Bind address family for %s not supported", addrBind.ToStringAddrPort()));
3325 : 1881 : LogError("%s\n", strError.original);
3326 : 1881 : return false;
3327 : : }
3328 : :
3329 : 16569 : std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP);
3330 [ - + ]: 16569 : if (!sock) {
3331 [ # # # # : 0 : strError = Untranslated(strprintf("Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError())));
# # ]
3332 [ # # ]: 0 : LogError("%s\n", strError.original);
3333 : : return false;
3334 : : }
3335 : :
3336 : : // Allow binding if the port is still in TIME_WAIT state after
3337 : : // the program was closed and restarted.
3338 [ + - + + ]: 16569 : if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &nOne, sizeof(int)) == SOCKET_ERROR) {
3339 [ + - + - : 12850 : strError = Untranslated(strprintf("Error setting SO_REUSEADDR on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError())));
+ - ]
3340 [ + - ]: 6425 : LogInfo("%s\n", strError.original);
3341 : : }
3342 : :
3343 : : // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
3344 : : // and enable it by default or not. Try to enable it, if possible.
3345 [ + + ]: 16569 : if (addrBind.IsIPv6()) {
3346 : : #ifdef IPV6_V6ONLY
3347 [ + - + + ]: 7966 : if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, &nOne, sizeof(int)) == SOCKET_ERROR) {
3348 [ + - + - : 11366 : strError = Untranslated(strprintf("Error setting IPV6_V6ONLY on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError())));
+ - ]
3349 [ + - ]: 5683 : LogInfo("%s\n", strError.original);
3350 : : }
3351 : : #endif
3352 : : #ifdef WIN32
3353 : : int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
3354 : : if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &nProtLevel, sizeof(int)) == SOCKET_ERROR) {
3355 : : strError = Untranslated(strprintf("Error setting IPV6_PROTECTION_LEVEL on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError())));
3356 : : LogInfo("%s\n", strError.original);
3357 : : }
3358 : : #endif
3359 : : }
3360 : :
3361 [ + - + + ]: 16569 : if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
3362 : 6872 : int nErr = WSAGetLastError();
3363 [ + + ]: 6872 : if (nErr == WSAEADDRINUSE)
3364 [ + - + - ]: 5020 : strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToStringAddrPort(), CLIENT_NAME);
3365 : : else
3366 [ + - + - : 8724 : strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToStringAddrPort(), NetworkErrorString(nErr));
+ - ]
3367 [ + - ]: 6872 : LogError("%s\n", strError.original);
3368 : : return false;
3369 : : }
3370 [ + - + - ]: 9697 : LogInfo("Bound to %s\n", addrBind.ToStringAddrPort());
3371 : :
3372 : : // Listen for incoming connections
3373 [ + - + + ]: 9697 : if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)
3374 : : {
3375 [ + - + - ]: 858 : strError = strprintf(_("Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
3376 [ + - ]: 429 : LogError("%s\n", strError.original);
3377 : : return false;
3378 : : }
3379 : :
3380 [ + - ]: 9268 : vhListenSocket.emplace_back(std::move(sock), permissions);
3381 : : return true;
3382 : 16569 : }
3383 : :
3384 : 0 : void Discover()
3385 : : {
3386 [ # # ]: 0 : if (!fDiscover)
3387 : : return;
3388 : :
3389 [ # # ]: 0 : for (const CNetAddr &addr: GetLocalAddresses()) {
3390 [ # # # # : 0 : if (AddLocal(addr, LOCAL_IF) && fLogIPs) {
# # ]
3391 [ # # # # ]: 0 : LogInfo("%s: %s\n", __func__, addr.ToStringAddr());
3392 : : }
3393 : : }
3394 : : }
3395 : :
3396 : 277410 : void CConnman::SetNetworkActive(bool active)
3397 : : {
3398 : 277410 : LogInfo("%s: %s\n", __func__, active);
3399 : :
3400 [ + + ]: 277410 : if (fNetworkActive == active) {
3401 : : return;
3402 : : }
3403 : :
3404 [ - + ]: 2078 : fNetworkActive = active;
3405 : :
3406 [ - + ]: 2078 : if (m_client_interface) {
3407 : 0 : m_client_interface->NotifyNetworkActiveChanged(fNetworkActive);
3408 : : }
3409 : : }
3410 : :
3411 : 3416 : CConnman::CConnman(uint64_t nSeed0In,
3412 : : uint64_t nSeed1In,
3413 : : AddrMan& addrman_in,
3414 : : const NetGroupManager& netgroupman,
3415 : : const CChainParams& params,
3416 : : bool network_active,
3417 : 3416 : std::shared_ptr<CThreadInterrupt> interrupt_net)
3418 [ + - ]: 3416 : : addrman(addrman_in)
3419 [ + - ]: 3416 : , m_netgroupman{netgroupman}
3420 : 3416 : , nSeed0(nSeed0In)
3421 : 3416 : , nSeed1(nSeed1In)
3422 [ + - - - ]: 3416 : , m_interrupt_net{interrupt_net}
3423 [ + - + - : 6832 : , m_params(params)
+ - + - ]
3424 : : {
3425 [ + - ]: 3416 : SetTryNewOutboundPeer(false);
3426 : :
3427 : 3416 : Options connOptions;
3428 [ + - ]: 3416 : Init(connOptions);
3429 [ + - ]: 3416 : SetNetworkActive(network_active);
3430 : 3416 : }
3431 : :
3432 : 29999 : NodeId CConnman::GetNewNodeId()
3433 : : {
3434 : 29999 : return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
3435 : : }
3436 : :
3437 : 728 : uint16_t CConnman::GetDefaultPort(Network net) const
3438 : : {
3439 [ + + ]: 728 : return net == NET_I2P ? I2P_SAM31_PORT : m_params.GetDefaultPort();
3440 : : }
3441 : :
3442 : 82503 : uint16_t CConnman::GetDefaultPort(const std::string& addr) const
3443 : : {
3444 : 82503 : CNetAddr a;
3445 [ - + + - : 82503 : return a.SetSpecial(addr) ? GetDefaultPort(a.GetNetwork()) : m_params.GetDefaultPort();
+ + + - +
- ]
3446 : 82503 : }
3447 : :
3448 : 18450 : bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlags permissions)
3449 : : {
3450 : 18450 : const CService addr{MaybeFlipIPv6toCJDNS(addr_)};
3451 : :
3452 [ + - ]: 18450 : bilingual_str strError;
3453 [ + - + + ]: 18450 : if (!BindListenPort(addr, strError, permissions)) {
3454 [ + + - + ]: 9182 : if ((flags & BF_REPORT_ERROR) && m_client_interface) {
3455 [ # # ]: 0 : m_client_interface->ThreadSafeMessageBox(strError, CClientUIInterface::MSG_ERROR);
3456 : : }
3457 : 9182 : return false;
3458 : : }
3459 : :
3460 [ + - + + : 9268 : if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !NetPermissions::HasFlag(permissions, NetPermissionFlags::NoBan)) {
+ - + + +
+ ]
3461 [ + - ]: 6578 : AddLocal(addr, LOCAL_BIND);
3462 : : }
3463 : :
3464 : : return true;
3465 : 18450 : }
3466 : :
3467 : 9752 : bool CConnman::InitBinds(const Options& options)
3468 : : {
3469 [ + + ]: 13923 : for (const auto& addrBind : options.vBinds) {
3470 [ + + ]: 11890 : if (!Bind(addrBind, BF_REPORT_ERROR, NetPermissionFlags::None)) {
3471 : : return false;
3472 : : }
3473 : : }
3474 [ + + ]: 5658 : for (const auto& addrBind : options.vWhiteBinds) {
3475 [ + + ]: 4326 : if (!Bind(addrBind.m_service, BF_REPORT_ERROR, addrBind.m_flags)) {
3476 : : return false;
3477 : : }
3478 : : }
3479 [ + + ]: 1629 : for (const auto& addr_bind : options.onion_binds) {
3480 [ + + ]: 932 : if (!Bind(addr_bind, BF_REPORT_ERROR | BF_DONT_ADVERTISE, NetPermissionFlags::None)) {
3481 : : return false;
3482 : : }
3483 : : }
3484 [ + + ]: 697 : if (options.bind_on_any) {
3485 : : // Don't consider errors to bind on IPv6 "::" fatal because the host OS
3486 : : // may not have IPv6 support and the user did not explicitly ask us to
3487 : : // bind on that.
3488 : 651 : const CService ipv6_any{in6_addr(COMPAT_IN6ADDR_ANY_INIT), GetListenPort()}; // ::
3489 [ + - ]: 651 : Bind(ipv6_any, BF_NONE, NetPermissionFlags::None);
3490 : :
3491 : 651 : struct in_addr inaddr_any;
3492 : 651 : inaddr_any.s_addr = htonl(INADDR_ANY);
3493 [ + - + - ]: 651 : const CService ipv4_any{inaddr_any, GetListenPort()}; // 0.0.0.0
3494 [ + - + + ]: 651 : if (!Bind(ipv4_any, BF_REPORT_ERROR, NetPermissionFlags::None)) {
3495 : 59 : return false;
3496 : : }
3497 : 651 : }
3498 : : return true;
3499 : : }
3500 : :
3501 : 0 : bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
3502 : : {
3503 : 0 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3504 : 0 : Init(connOptions);
3505 : :
3506 [ # # # # ]: 0 : if (fListen && !InitBinds(connOptions)) {
3507 [ # # ]: 0 : if (m_client_interface) {
3508 [ # # ]: 0 : m_client_interface->ThreadSafeMessageBox(
3509 : 0 : _("Failed to listen on any port. Use -listen=0 if you want this."),
3510 : : CClientUIInterface::MSG_ERROR);
3511 : : }
3512 : 0 : return false;
3513 : : }
3514 : :
3515 [ # # ]: 0 : if (connOptions.m_i2p_accept_incoming) {
3516 [ # # ]: 0 : if (const auto i2p_sam = GetProxy(NET_I2P)) {
3517 [ # # ]: 0 : m_i2p_sam_session = std::make_unique<i2p::sam::Session>(gArgs.GetDataDirNet() / "i2p_private_key",
3518 [ # # ]: 0 : *i2p_sam, m_interrupt_net);
3519 : 0 : }
3520 : : }
3521 : :
3522 : : // Randomize the order in which we may query seednode to potentially prevent connecting to the same one every restart (and signal that we have restarted)
3523 : 0 : std::vector<std::string> seed_nodes = connOptions.vSeedNodes;
3524 [ # # ]: 0 : if (!seed_nodes.empty()) {
3525 : 0 : std::shuffle(seed_nodes.begin(), seed_nodes.end(), FastRandomContext{});
3526 : : }
3527 : :
3528 [ # # ]: 0 : if (m_use_addrman_outgoing) {
3529 : : // Load addresses from anchors.dat
3530 [ # # # # ]: 0 : m_anchors = ReadAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME);
3531 [ # # # # ]: 0 : if (m_anchors.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
3532 [ # # ]: 0 : m_anchors.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
3533 : : }
3534 [ # # # # ]: 0 : LogInfo("%i block-relay-only anchors will be tried for connections.\n", m_anchors.size());
3535 : : }
3536 : :
3537 [ # # ]: 0 : if (m_client_interface) {
3538 [ # # # # ]: 0 : m_client_interface->InitMessage(_("Starting network threads…"));
3539 : : }
3540 : :
3541 : 0 : fAddressesInitialized = true;
3542 : :
3543 [ # # ]: 0 : if (semOutbound == nullptr) {
3544 : : // initialize semaphore
3545 [ # # # # ]: 0 : semOutbound = std::make_unique<std::counting_semaphore<>>(std::min(m_max_automatic_outbound, m_max_automatic_connections));
3546 : : }
3547 [ # # ]: 0 : if (semAddnode == nullptr) {
3548 : : // initialize semaphore
3549 [ # # ]: 0 : semAddnode = std::make_unique<std::counting_semaphore<>>(m_max_addnode);
3550 : : }
3551 : :
3552 : : //
3553 : : // Start threads
3554 : : //
3555 [ # # ]: 0 : assert(m_msgproc);
3556 [ # # ]: 0 : m_interrupt_net->reset();
3557 [ # # ]: 0 : flagInterruptMsgProc = false;
3558 : :
3559 : 0 : {
3560 [ # # ]: 0 : LOCK(mutexMsgProc);
3561 [ # # ]: 0 : fMsgProcWake = false;
3562 : 0 : }
3563 : :
3564 : : // Send and receive from sockets, accept connections
3565 [ # # ]: 0 : threadSocketHandler = std::thread(&util::TraceThread, "net", [this] { ThreadSocketHandler(); });
3566 : :
3567 [ # # # # : 0 : if (!gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED))
# # ]
3568 [ # # ]: 0 : LogInfo("DNS seeding disabled\n");
3569 : : else
3570 [ # # ]: 0 : threadDNSAddressSeed = std::thread(&util::TraceThread, "dnsseed", [this] { ThreadDNSAddressSeed(); });
3571 : :
3572 : : // Initiate manual connections
3573 [ # # ]: 0 : threadOpenAddedConnections = std::thread(&util::TraceThread, "addcon", [this] { ThreadOpenAddedConnections(); });
3574 : :
3575 [ # # # # ]: 0 : if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
3576 [ # # ]: 0 : if (m_client_interface) {
3577 [ # # ]: 0 : m_client_interface->ThreadSafeMessageBox(
3578 [ # # ]: 0 : _("Cannot provide specific connections and have addrman find outgoing connections at the same time."),
3579 : : CClientUIInterface::MSG_ERROR);
3580 : : }
3581 : 0 : return false;
3582 : : }
3583 [ # # # # ]: 0 : if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
3584 : 0 : threadOpenConnections = std::thread(
3585 [ # # ]: 0 : &util::TraceThread, "opencon",
3586 [ # # # # : 0 : [this, connect = connOptions.m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });
# # # # ]
3587 : : }
3588 : :
3589 : : // Process messages
3590 [ # # ]: 0 : threadMessageHandler = std::thread(&util::TraceThread, "msghand", [this] { ThreadMessageHandler(); });
3591 : :
3592 [ # # ]: 0 : if (m_i2p_sam_session) {
3593 : 0 : threadI2PAcceptIncoming =
3594 [ # # ]: 0 : std::thread(&util::TraceThread, "i2paccept", [this] { ThreadI2PAcceptIncoming(); });
3595 : : }
3596 : :
3597 [ # # # # : 0 : if (gArgs.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)) {
# # ]
3598 : 0 : threadPrivateBroadcast =
3599 [ # # ]: 0 : std::thread(&util::TraceThread, "privbcast", [this] { ThreadPrivateBroadcast(); });
3600 : : }
3601 : :
3602 : : // Dump network addresses
3603 [ # # ]: 0 : scheduler.scheduleEvery([this] { DumpAddresses(); }, DUMP_PEERS_INTERVAL);
3604 : :
3605 : : // Run the ASMap Health check once and then schedule it to run every 24h.
3606 [ # # # # ]: 0 : if (m_netgroupman.UsingASMap()) {
3607 [ # # ]: 0 : ASMapHealthCheck();
3608 [ # # ]: 0 : scheduler.scheduleEvery([this] { ASMapHealthCheck(); }, ASMAP_HEALTH_CHECK_INTERVAL);
3609 : : }
3610 : :
3611 : : return true;
3612 : 0 : }
3613 : :
3614 : : class CNetCleanup
3615 : : {
3616 : : public:
3617 : : CNetCleanup() = default;
3618 : :
3619 : : ~CNetCleanup()
3620 : : {
3621 : : #ifdef WIN32
3622 : : // Shutdown Windows Sockets
3623 : : WSACleanup();
3624 : : #endif
3625 : : }
3626 : : };
3627 : : static CNetCleanup instance_of_cnetcleanup;
3628 : :
3629 : 3416 : void CConnman::Interrupt()
3630 : : {
3631 : 3416 : {
3632 : 3416 : LOCK(mutexMsgProc);
3633 [ + - ]: 3416 : flagInterruptMsgProc = true;
3634 : 3416 : }
3635 : 3416 : condMsgProc.notify_all();
3636 : :
3637 : 3416 : (*m_interrupt_net)();
3638 : 3416 : g_socks5_interrupt();
3639 : :
3640 [ - + ]: 3416 : if (semOutbound) {
3641 [ # # ]: 0 : for (int i=0; i<m_max_automatic_outbound; i++) {
3642 : 0 : semOutbound->release();
3643 : : }
3644 : : }
3645 : :
3646 [ - + ]: 3416 : if (semAddnode) {
3647 [ # # ]: 0 : for (int i=0; i<m_max_addnode; i++) {
3648 : 0 : semAddnode->release();
3649 : : }
3650 : : }
3651 : :
3652 : 3416 : m_private_broadcast.m_sem_conn_max.release();
3653 : 3416 : m_private_broadcast.NumToOpenAdd(1); // Just unblock NumToOpenWait() to be able to continue with shutdown.
3654 : 3416 : }
3655 : :
3656 : 3416 : void CConnman::StopThreads()
3657 : : {
3658 [ - + ]: 3416 : if (threadPrivateBroadcast.joinable()) {
3659 : 0 : threadPrivateBroadcast.join();
3660 : : }
3661 [ - + ]: 3416 : if (threadI2PAcceptIncoming.joinable()) {
3662 : 0 : threadI2PAcceptIncoming.join();
3663 : : }
3664 [ - + ]: 3416 : if (threadMessageHandler.joinable())
3665 : 0 : threadMessageHandler.join();
3666 [ - + ]: 3416 : if (threadOpenConnections.joinable())
3667 : 0 : threadOpenConnections.join();
3668 [ - + ]: 3416 : if (threadOpenAddedConnections.joinable())
3669 : 0 : threadOpenAddedConnections.join();
3670 [ - + ]: 3416 : if (threadDNSAddressSeed.joinable())
3671 : 0 : threadDNSAddressSeed.join();
3672 [ - + ]: 3416 : if (threadSocketHandler.joinable())
3673 : 0 : threadSocketHandler.join();
3674 : 3416 : }
3675 : :
3676 : 11249 : void CConnman::StopNodes()
3677 : : {
3678 : 11249 : AssertLockNotHeld(m_nodes_mutex);
3679 : 11249 : AssertLockNotHeld(m_reconnections_mutex);
3680 : :
3681 [ - + ]: 11249 : if (fAddressesInitialized) {
3682 : 0 : DumpAddresses();
3683 : 0 : fAddressesInitialized = false;
3684 : :
3685 [ # # ]: 0 : if (m_use_addrman_outgoing) {
3686 : : // Anchor connections are only dumped during clean shutdown.
3687 : 0 : std::vector<CAddress> anchors_to_dump = GetCurrentBlockRelayOnlyConns();
3688 [ # # # # ]: 0 : if (anchors_to_dump.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
3689 [ # # ]: 0 : anchors_to_dump.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
3690 : : }
3691 [ # # # # ]: 0 : DumpAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME, anchors_to_dump);
3692 : 0 : }
3693 : : }
3694 : :
3695 : : // Delete peer connections.
3696 : 11249 : std::vector<CNode*> nodes;
3697 [ + - + - ]: 22498 : WITH_LOCK(m_nodes_mutex, nodes.swap(m_nodes));
3698 [ + + ]: 24108 : for (CNode* pnode : nodes) {
3699 [ + - - + : 12859 : LogDebug(BCLog::NET, "Stopping node, %s", pnode->DisconnectMsg());
- - - - ]
3700 [ + - ]: 12859 : pnode->CloseSocketDisconnect();
3701 [ + - ]: 12859 : DeleteNode(pnode);
3702 : : }
3703 : :
3704 [ - + ]: 11249 : for (CNode* pnode : m_nodes_disconnected) {
3705 [ # # ]: 0 : DeleteNode(pnode);
3706 : : }
3707 : 11249 : m_nodes_disconnected.clear();
3708 [ + - + - ]: 22498 : WITH_LOCK(m_reconnections_mutex, m_reconnections.clear());
3709 : 11249 : vhListenSocket.clear();
3710 [ - + ]: 11249 : semOutbound.reset();
3711 [ - + ]: 11249 : semAddnode.reset();
3712 : 11249 : }
3713 : :
3714 : 12859 : void CConnman::DeleteNode(CNode* pnode)
3715 : : {
3716 [ - + ]: 12859 : assert(pnode);
3717 : 12859 : m_msgproc->FinalizeNode(*pnode);
3718 : 12859 : delete pnode;
3719 : 12859 : }
3720 : :
3721 [ + - ]: 3416 : CConnman::~CConnman()
3722 : : {
3723 : 3416 : Interrupt();
3724 : 3416 : Stop();
3725 : 6832 : }
3726 : :
3727 : 40992 : std::vector<CAddress> CConnman::GetAddressesUnsafe(size_t max_addresses, size_t max_pct, std::optional<Network> network, const bool filtered) const
3728 : : {
3729 : 40992 : std::vector<CAddress> addresses = addrman.get().GetAddr(max_addresses, max_pct, network, filtered);
3730 [ - + ]: 40992 : if (m_banman) {
3731 [ # # ]: 0 : addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
3732 [ # # # # ]: 0 : [this](const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
3733 [ # # ]: 0 : addresses.end());
3734 : : }
3735 : 40992 : return addresses;
3736 : 0 : }
3737 : :
3738 : 11979 : std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct)
3739 : : {
3740 : 11979 : uint64_t network_id = requestor.m_network_key;
3741 : 11979 : const auto current_time = GetTime<std::chrono::microseconds>();
3742 [ + - ]: 11979 : auto r = m_addr_response_caches.emplace(network_id, CachedAddrResponse{});
3743 [ + + ]: 11979 : CachedAddrResponse& cache_entry = r.first->second;
3744 [ + + ]: 11979 : if (cache_entry.m_cache_entry_expiration < current_time) { // If emplace() added new one it has expiration 0.
3745 : 575 : cache_entry.m_addrs_response_cache = GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt);
3746 : : // Choosing a proper cache lifetime is a trade-off between the privacy leak minimization
3747 : : // and the usefulness of ADDR responses to honest users.
3748 : : //
3749 : : // Longer cache lifetime makes it more difficult for an attacker to scrape
3750 : : // enough AddrMan data to maliciously infer something useful.
3751 : : // By the time an attacker scraped enough AddrMan records, most of
3752 : : // the records should be old enough to not leak topology info by
3753 : : // e.g. analyzing real-time changes in timestamps.
3754 : : //
3755 : : // It takes only several hundred requests to scrape everything from an AddrMan containing 100,000 nodes,
3756 : : // so ~24 hours of cache lifetime indeed makes the data less inferable by the time
3757 : : // most of it could be scraped (considering that timestamps are updated via
3758 : : // ADDR self-announcements and when nodes communicate).
3759 : : // We also should be robust to those attacks which may not require scraping *full* victim's AddrMan
3760 : : // (because even several timestamps of the same handful of nodes may leak privacy).
3761 : : //
3762 : : // On the other hand, longer cache lifetime makes ADDR responses
3763 : : // outdated and less useful for an honest requestor, e.g. if most nodes
3764 : : // in the ADDR response are no longer active.
3765 : : //
3766 : : // However, the churn in the network is known to be rather low. Since we consider
3767 : : // nodes to be "terrible" (see IsTerrible()) if the timestamps are older than 30 days,
3768 : : // max. 24 hours of "penalty" due to cache shouldn't make any meaningful difference
3769 : : // in terms of the freshness of the response.
3770 : 575 : cache_entry.m_cache_entry_expiration = current_time +
3771 : 575 : 21h + FastRandomContext().randrange<std::chrono::microseconds>(6h);
3772 : : }
3773 : 11979 : return cache_entry.m_addrs_response_cache;
3774 : : }
3775 : :
3776 : 49444 : bool CConnman::AddNode(const AddedNodeParams& add)
3777 : : {
3778 [ + - + - ]: 49444 : const CService resolved(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)));
3779 [ + - ]: 49444 : const bool resolved_is_valid{resolved.IsValid()};
3780 : :
3781 [ + - ]: 49444 : LOCK(m_added_nodes_mutex);
3782 [ + + ]: 303760 : for (const auto& it : m_added_node_params) {
3783 [ + + + + : 331817 : 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;
+ - + - +
- + - + +
+ + + + -
- - - ]
3784 : : }
3785 : :
3786 [ + - ]: 2377 : m_added_node_params.push_back(add);
3787 : : return true;
3788 : 49444 : }
3789 : :
3790 : 16575 : bool CConnman::RemoveAddedNode(std::string_view node)
3791 : : {
3792 : 16575 : LOCK(m_added_nodes_mutex);
3793 [ + + ]: 127300 : for (auto it = m_added_node_params.begin(); it != m_added_node_params.end(); ++it) {
3794 [ - + + + ]: 111895 : if (node == it->m_added_node) {
3795 : 1170 : m_added_node_params.erase(it);
3796 : 1170 : return true;
3797 : : }
3798 : : }
3799 : : return false;
3800 : 16575 : }
3801 : :
3802 : 0 : bool CConnman::AddedNodesContain(const CAddress& addr) const
3803 : : {
3804 : 0 : AssertLockNotHeld(m_added_nodes_mutex);
3805 : 0 : const std::string addr_str{addr.ToStringAddr()};
3806 [ # # ]: 0 : const std::string addr_port_str{addr.ToStringAddrPort()};
3807 [ # # ]: 0 : LOCK(m_added_nodes_mutex);
3808 [ # # ]: 0 : return (m_added_node_params.size() < 24 // bound the query to a reasonable limit
3809 [ # # # # ]: 0 : && std::any_of(m_added_node_params.cbegin(), m_added_node_params.cend(),
3810 [ # # # # : 0 : [&](const auto& p) { return p.m_added_node == addr_str || p.m_added_node == addr_port_str; }));
# # ]
3811 : 0 : }
3812 : :
3813 : 13923 : size_t CConnman::GetNodeCount(ConnectionDirection flags) const
3814 : : {
3815 : 13923 : LOCK(m_nodes_mutex);
3816 [ + + ]: 13923 : if (flags == ConnectionDirection::Both) // Shortcut if we want total
3817 [ - + ]: 596 : return m_nodes.size();
3818 : :
3819 : 13327 : int nNum = 0;
3820 [ + + ]: 481684 : for (const auto& pnode : m_nodes) {
3821 [ + + + + ]: 703703 : if (flags & (pnode->IsInboundConn() ? ConnectionDirection::In : ConnectionDirection::Out)) {
3822 : 233590 : nNum++;
3823 : : }
3824 : : }
3825 : :
3826 : 13327 : return nNum;
3827 : 13923 : }
3828 : :
3829 : :
3830 : 0 : std::map<CNetAddr, LocalServiceInfo> CConnman::getNetLocalAddresses() const
3831 : : {
3832 : 0 : LOCK(g_maplocalhost_mutex);
3833 [ # # # # ]: 0 : return mapLocalHost;
3834 : 0 : }
3835 : :
3836 : 89166 : uint32_t CConnman::GetMappedAS(const CNetAddr& addr) const
3837 : : {
3838 : 89166 : return m_netgroupman.GetMappedAS(addr);
3839 : : }
3840 : :
3841 : 3392 : void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats) const
3842 : : {
3843 : 3392 : AssertLockNotHeld(m_nodes_mutex);
3844 : :
3845 : 3392 : vstats.clear();
3846 : 3392 : LOCK(m_nodes_mutex);
3847 [ - + + - ]: 3392 : vstats.reserve(m_nodes.size());
3848 [ + + ]: 78349 : for (CNode* pnode : m_nodes) {
3849 [ + - ]: 74957 : vstats.emplace_back();
3850 [ + - ]: 74957 : pnode->CopyStats(vstats.back());
3851 [ + - ]: 74957 : vstats.back().m_mapped_as = GetMappedAS(pnode->addr);
3852 : : }
3853 : 3392 : }
3854 : :
3855 : 2159 : bool CConnman::DisconnectNode(std::string_view strNode)
3856 : : {
3857 : 2159 : LOCK(m_nodes_mutex);
3858 [ - + ]: 136503 : auto it = std::ranges::find_if(m_nodes, [&strNode](CNode* node) { return node->m_addr_name == strNode; });
3859 [ + + ]: 2159 : if (it != m_nodes.end()) {
3860 : 291 : CNode* node{*it};
3861 [ + - - + : 291 : LogDebug(BCLog::NET, "disconnect by address%s match, %s", (fLogIPs ? strprintf("=%s", strNode) : ""), node->DisconnectMsg());
- - - - -
- - - -
- ]
3862 : 291 : node->fDisconnect = true;
3863 : 291 : return true;
3864 : : }
3865 : : return false;
3866 : 2159 : }
3867 : :
3868 : 10252 : bool CConnman::DisconnectNode(const CSubNet& subnet)
3869 : : {
3870 : 10252 : AssertLockNotHeld(m_nodes_mutex);
3871 : 10252 : bool disconnected = false;
3872 : 10252 : LOCK(m_nodes_mutex);
3873 [ + + ]: 854664 : for (CNode* pnode : m_nodes) {
3874 [ + - + + ]: 844412 : if (subnet.Match(pnode->addr)) {
3875 [ + - - + : 3667 : LogDebug(BCLog::NET, "disconnect by subnet%s match, %s", (fLogIPs ? strprintf("=%s", subnet.ToString()) : ""), pnode->DisconnectMsg());
- - - - -
- - - - -
- - - - -
- ]
3876 : 3667 : pnode->fDisconnect = true;
3877 : 3667 : disconnected = true;
3878 : : }
3879 : : }
3880 [ + - ]: 10252 : return disconnected;
3881 : 10252 : }
3882 : :
3883 : 9194 : bool CConnman::DisconnectNode(const CNetAddr& addr)
3884 : : {
3885 : 9194 : AssertLockNotHeld(m_nodes_mutex);
3886 [ + - ]: 9194 : return DisconnectNode(CSubNet(addr));
3887 : : }
3888 : :
3889 : 7882 : bool CConnman::DisconnectNode(NodeId id)
3890 : : {
3891 : 7882 : LOCK(m_nodes_mutex);
3892 [ + + ]: 720986 : for(CNode* pnode : m_nodes) {
3893 [ + + ]: 713204 : if (id == pnode->GetId()) {
3894 [ + - - + : 100 : LogDebug(BCLog::NET, "disconnect by id, %s", pnode->DisconnectMsg());
- - - - ]
3895 : 100 : pnode->fDisconnect = true;
3896 : 100 : return true;
3897 : : }
3898 : : }
3899 : : return false;
3900 : 7882 : }
3901 : :
3902 : 2680 : void CConnman::RecordBytesRecv(uint64_t bytes)
3903 : : {
3904 : 2680 : nTotalBytesRecv += bytes;
3905 : 2680 : }
3906 : :
3907 : 115229 : void CConnman::RecordBytesSent(uint64_t bytes)
3908 : : {
3909 : 115229 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3910 : 115229 : LOCK(m_total_bytes_sent_mutex);
3911 : :
3912 : 115229 : nTotalBytesSent += bytes;
3913 : :
3914 : 115229 : const auto now = GetTime<std::chrono::seconds>();
3915 [ + + ]: 115229 : if (nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME < now)
3916 : : {
3917 : : // timeframe expired, reset cycle
3918 : 7661 : nMaxOutboundCycleStartTime = now;
3919 : 7661 : nMaxOutboundTotalBytesSentInCycle = 0;
3920 : : }
3921 : :
3922 [ + - ]: 115229 : nMaxOutboundTotalBytesSentInCycle += bytes;
3923 : 115229 : }
3924 : :
3925 : 3392 : uint64_t CConnman::GetMaxOutboundTarget() const
3926 : : {
3927 : 3392 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3928 : 3392 : LOCK(m_total_bytes_sent_mutex);
3929 [ + - ]: 3392 : return nMaxOutboundLimit;
3930 : 3392 : }
3931 : :
3932 : 3392 : std::chrono::seconds CConnman::GetMaxOutboundTimeframe() const
3933 : : {
3934 : 3392 : return MAX_UPLOAD_TIMEFRAME;
3935 : : }
3936 : :
3937 : 3392 : std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle() const
3938 : : {
3939 : 3392 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3940 : 3392 : LOCK(m_total_bytes_sent_mutex);
3941 [ + - ]: 3392 : return GetMaxOutboundTimeLeftInCycle_();
3942 : 3392 : }
3943 : :
3944 : 351290 : std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle_() const
3945 : : {
3946 : 351290 : AssertLockHeld(m_total_bytes_sent_mutex);
3947 : :
3948 [ + + ]: 351290 : if (nMaxOutboundLimit == 0)
3949 : 1023 : return 0s;
3950 : :
3951 [ + + ]: 350267 : if (nMaxOutboundCycleStartTime.count() == 0)
3952 : 323756 : return MAX_UPLOAD_TIMEFRAME;
3953 : :
3954 : 26511 : const std::chrono::seconds cycleEndTime = nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME;
3955 : 26511 : const auto now = GetTime<std::chrono::seconds>();
3956 [ + + ]: 26511 : return (cycleEndTime < now) ? 0s : cycleEndTime - now;
3957 : : }
3958 : :
3959 : 373898 : bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit) const
3960 : : {
3961 : 373898 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3962 : 373898 : LOCK(m_total_bytes_sent_mutex);
3963 [ + + ]: 373898 : if (nMaxOutboundLimit == 0)
3964 : : return false;
3965 : :
3966 [ + + ]: 349007 : if (historicalBlockServingLimit)
3967 : : {
3968 : : // keep a large enough buffer to at least relay each block once
3969 [ + - ]: 347898 : const std::chrono::seconds timeLeftInCycle = GetMaxOutboundTimeLeftInCycle_();
3970 : 347898 : const uint64_t buffer = timeLeftInCycle / std::chrono::minutes{10} * MAX_BLOCK_SERIALIZED_SIZE;
3971 [ + + + + ]: 347898 : if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
3972 : 19615 : return true;
3973 : : }
3974 [ + + ]: 1109 : else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
3975 : 8 : return true;
3976 : :
3977 : : return false;
3978 : 373898 : }
3979 : :
3980 : 3392 : uint64_t CConnman::GetOutboundTargetBytesLeft() const
3981 : : {
3982 : 3392 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3983 : 3392 : LOCK(m_total_bytes_sent_mutex);
3984 [ + + ]: 3392 : if (nMaxOutboundLimit == 0)
3985 : : return 0;
3986 : :
3987 [ + + ]: 2369 : return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
3988 : 3392 : }
3989 : :
3990 : 3392 : uint64_t CConnman::GetTotalBytesRecv() const
3991 : : {
3992 : 3392 : return nTotalBytesRecv;
3993 : : }
3994 : :
3995 : 3392 : uint64_t CConnman::GetTotalBytesSent() const
3996 : : {
3997 : 3392 : AssertLockNotHeld(m_total_bytes_sent_mutex);
3998 : 3392 : LOCK(m_total_bytes_sent_mutex);
3999 [ + - ]: 3392 : return nTotalBytesSent;
4000 : 3392 : }
4001 : :
4002 : 26013 : ServiceFlags CConnman::GetLocalServices() const
4003 : : {
4004 : 26013 : return m_local_services;
4005 : : }
4006 : :
4007 : 93573 : static std::unique_ptr<Transport> MakeTransport(NodeId id, bool use_v2transport, bool inbound) noexcept
4008 : : {
4009 [ + + ]: 93573 : if (use_v2transport) {
4010 [ - + ]: 12740 : return std::make_unique<V2Transport>(id, /*initiating=*/!inbound);
4011 : : } else {
4012 [ - + ]: 80833 : return std::make_unique<V1Transport>(id);
4013 : : }
4014 : : }
4015 : :
4016 : 93573 : CNode::CNode(NodeId idIn,
4017 : : std::shared_ptr<Sock> sock,
4018 : : const CAddress& addrIn,
4019 : : uint64_t nKeyedNetGroupIn,
4020 : : uint64_t nLocalHostNonceIn,
4021 : : const CService& addrBindIn,
4022 : : const std::string& addrNameIn,
4023 : : ConnectionType conn_type_in,
4024 : : bool inbound_onion,
4025 : : uint64_t network_key,
4026 : 93573 : CNodeOptions&& node_opts)
4027 : 93573 : : m_transport{MakeTransport(idIn, node_opts.use_v2transport, conn_type_in == ConnectionType::INBOUND)},
4028 : 93573 : m_permission_flags{node_opts.permission_flags},
4029 [ + + ]: 93573 : m_sock{sock},
4030 : 93573 : m_connected{NodeClock::now()},
4031 : 93573 : addr{addrIn},
4032 : 93573 : addrBind{addrBindIn},
4033 [ + + + - ]: 93573 : m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
4034 [ - + ]: 93573 : m_dest(addrNameIn),
4035 : 93573 : m_inbound_onion{inbound_onion},
4036 [ + - ]: 93573 : m_prefer_evict{node_opts.prefer_evict},
4037 : 93573 : nKeyedNetGroup{nKeyedNetGroupIn},
4038 : 93573 : m_network_key{network_key},
4039 : 93573 : m_conn_type{conn_type_in},
4040 : 93573 : id{idIn},
4041 : 93573 : nLocalHostNonce{nLocalHostNonceIn},
4042 [ + - ]: 93573 : m_recv_flood_size{node_opts.recv_flood_size},
4043 [ + - + - : 187146 : m_i2p_sam_session{std::move(node_opts.i2p_sam_session)}
+ + ]
4044 : : {
4045 [ + + + - ]: 93573 : if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
4046 : :
4047 [ + + ]: 3368628 : for (const auto& msg : ALL_NET_MESSAGE_TYPES) {
4048 [ + - ]: 3275055 : mapRecvBytesPerMsgType[msg] = 0;
4049 : : }
4050 [ + - ]: 93573 : mapRecvBytesPerMsgType[NET_MESSAGE_TYPE_OTHER] = 0;
4051 : :
4052 [ - + ]: 93573 : if (fLogIPs) {
4053 [ # # # # : 0 : LogDebug(BCLog::NET, "Added connection to %s peer=%d\n", m_addr_name, id);
# # ]
4054 : : } else {
4055 [ + - - + : 93573 : LogDebug(BCLog::NET, "Added connection peer=%d\n", id);
- - ]
4056 : : }
4057 [ - - ]: 93573 : }
4058 : :
4059 : 99927 : void CNode::MarkReceivedMsgsForProcessing()
4060 : : {
4061 : 99927 : AssertLockNotHeld(m_msg_process_queue_mutex);
4062 : :
4063 : 99927 : size_t nSizeAdded = 0;
4064 [ + + ]: 199854 : for (const auto& msg : vRecvMsg) {
4065 : : // vRecvMsg contains only completed CNetMessage
4066 : : // the single possible partially deserialized message are held by TransportDeserializer
4067 : 99927 : nSizeAdded += msg.GetMemoryUsage();
4068 : : }
4069 : :
4070 : 99927 : LOCK(m_msg_process_queue_mutex);
4071 : 99927 : m_msg_process_queue.splice(m_msg_process_queue.end(), vRecvMsg);
4072 : 99927 : m_msg_process_queue_size += nSizeAdded;
4073 [ + - ]: 99927 : fPauseRecv = m_msg_process_queue_size > m_recv_flood_size;
4074 : 99927 : }
4075 : :
4076 : 102374 : std::optional<std::pair<CNetMessage, bool>> CNode::PollMessage()
4077 : : {
4078 : 102374 : LOCK(m_msg_process_queue_mutex);
4079 [ + + ]: 102374 : if (m_msg_process_queue.empty()) return std::nullopt;
4080 : :
4081 : 95855 : std::list<CNetMessage> msgs;
4082 : : // Just take one message
4083 : 95855 : msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
4084 : 95855 : m_msg_process_queue_size -= msgs.front().GetMemoryUsage();
4085 : 95855 : fPauseRecv = m_msg_process_queue_size > m_recv_flood_size;
4086 : :
4087 : 191710 : return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
4088 : 95855 : }
4089 : :
4090 : 3324292 : bool CConnman::NodeFullyConnected(const CNode* pnode)
4091 : : {
4092 [ + - + + : 3324292 : return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
+ + ]
4093 : : }
4094 : :
4095 : : /// Private broadcast connections only need to send certain message types.
4096 : : /// Other messages are not needed and may degrade privacy.
4097 : 30843 : static bool IsOutboundMessageAllowedInPrivateBroadcast(std::string_view type) noexcept
4098 : : {
4099 : 61170 : return type == NetMsgType::VERSION ||
4100 [ + + ]: 30327 : type == NetMsgType::VERACK ||
4101 [ + + ]: 30142 : type == NetMsgType::INV ||
4102 [ + + + + ]: 60941 : type == NetMsgType::TX ||
4103 [ + + ]: 30095 : type == NetMsgType::PING;
4104 : : }
4105 : :
4106 : 211225 : void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
4107 : : {
4108 : 211225 : AssertLockNotHeld(m_total_bytes_sent_mutex);
4109 : :
4110 [ + + - + : 211225 : if (pnode->IsPrivateBroadcastConn() && !IsOutboundMessageAllowedInPrivateBroadcast(msg.m_type)) {
+ + ]
4111 [ - + - - ]: 30029 : LogDebug(BCLog::PRIVBROADCAST, "Omitting send of message '%s', %s", msg.m_type, pnode->LogPeer());
4112 : 30029 : return;
4113 : : }
4114 : :
4115 [ + + + + : 181196 : if (!m_private_broadcast.m_outbound_tor_ok_at_least_once.load() && !pnode->IsInboundConn() &&
+ + ]
4116 [ + + + + : 278880 : pnode->addr.IsTor() && msg.m_type == NetMsgType::VERACK) {
+ + ]
4117 : : // If we are sending the peer VERACK that means we successfully sent
4118 : : // and received another message to/from that peer (VERSION).
4119 : 317 : m_private_broadcast.m_outbound_tor_ok_at_least_once.store(true);
4120 : : }
4121 : :
4122 [ - + ]: 181196 : size_t nMessageSize = msg.data.size();
4123 [ - + ]: 181196 : LogDebug(BCLog::NET, "sending %s (%d bytes) peer=%d\n", msg.m_type, nMessageSize, pnode->GetId());
4124 [ - + ]: 181196 : if (m_capture_messages) {
4125 [ # # ]: 0 : CaptureMessage(pnode->addr, msg.m_type, msg.data, /*is_incoming=*/false);
4126 : : }
4127 : :
4128 : : TRACEPOINT(net, outbound_message,
4129 : : pnode->GetId(),
4130 : : pnode->m_addr_name.c_str(),
4131 : : pnode->ConnectionTypeAsString().c_str(),
4132 : : msg.m_type.c_str(),
4133 : : msg.data.size(),
4134 : : msg.data.data()
4135 : 181196 : );
4136 : :
4137 : 181196 : size_t nBytesSent = 0;
4138 : 181196 : {
4139 : 181196 : LOCK(pnode->cs_vSend);
4140 : : // Check if the transport still has unsent bytes, and indicate to it that we're about to
4141 : : // give it a message to send.
4142 [ + + ]: 181196 : const auto& [to_send, more, _msg_type] =
4143 [ + + ]: 181196 : pnode->m_transport->GetBytesToSend(/*have_next_message=*/true);
4144 [ + + - + ]: 181196 : const bool queue_was_empty{to_send.empty() && pnode->vSendMsg.empty()};
4145 : :
4146 : : // Update memory usage of send buffer.
4147 : 181196 : pnode->m_send_memusage += msg.GetMemoryUsage();
4148 [ + - ]: 181196 : if (pnode->m_send_memusage + pnode->m_transport->GetSendMemoryUsage() > nSendBufferMaxSize) pnode->fPauseSend = true;
4149 : : // Move message to vSendMsg queue.
4150 [ + - ]: 181196 : pnode->vSendMsg.push_back(std::move(msg));
4151 : :
4152 : : // If there was nothing to send before, and there is now (predicted by the "more" value
4153 : : // returned by the GetBytesToSend call above), attempt "optimistic write":
4154 : : // because the poll/select loop may pause for SELECT_TIMEOUT_MILLISECONDS before actually
4155 : : // doing a send, try sending from the calling thread if the queue was empty before.
4156 : : // With a V1Transport, more will always be true here, because adding a message always
4157 : : // results in sendable bytes there, but with V2Transport this is not the case (it may
4158 : : // still be in the handshake).
4159 [ + + + - ]: 181196 : if (queue_was_empty && more) {
4160 [ + - ]: 125139 : std::tie(nBytesSent, std::ignore) = SocketSendData(*pnode);
4161 : : }
4162 : 181196 : }
4163 [ + + ]: 181196 : if (nBytesSent) RecordBytesSent(nBytesSent);
4164 : : }
4165 : :
4166 : 1693 : bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
4167 : : {
4168 : 1693 : AssertLockNotHeld(m_nodes_mutex);
4169 : :
4170 : 1693 : CNode* found = nullptr;
4171 : 1693 : LOCK(m_nodes_mutex);
4172 [ + + ]: 148419 : for (auto&& pnode : m_nodes) {
4173 [ + + ]: 146810 : if(pnode->GetId() == id) {
4174 : : found = pnode;
4175 : : break;
4176 : : }
4177 : : }
4178 [ + + + - : 1698 : return found != nullptr && NodeFullyConnected(found) && func(found);
+ + + - +
+ + - ]
4179 : 1693 : }
4180 : :
4181 : 91216 : CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const
4182 : : {
4183 : 91216 : return CSipHasher(nSeed0, nSeed1).Write(id);
4184 : : }
4185 : :
4186 : 29999 : uint64_t CConnman::CalculateKeyedNetGroup(const CNetAddr& address) const
4187 : : {
4188 : 29999 : std::vector<unsigned char> vchNetGroup(m_netgroupman.GetGroup(address));
4189 : :
4190 [ + - + - : 59998 : return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup).Finalize();
+ - ]
4191 : 29999 : }
4192 : :
4193 : 0 : void CConnman::PerformReconnections()
4194 : : {
4195 : 0 : AssertLockNotHeld(m_nodes_mutex);
4196 : 0 : AssertLockNotHeld(m_reconnections_mutex);
4197 : 0 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
4198 : 0 : while (true) {
4199 : : // Move first element of m_reconnections to todo (avoiding an allocation inside the lock).
4200 [ # # ]: 0 : decltype(m_reconnections) todo;
4201 : 0 : {
4202 [ # # ]: 0 : LOCK(m_reconnections_mutex);
4203 [ # # ]: 0 : if (m_reconnections.empty()) break;
4204 [ # # ]: 0 : todo.splice(todo.end(), m_reconnections, m_reconnections.begin());
4205 : 0 : }
4206 : :
4207 [ # # ]: 0 : auto& item = *todo.begin();
4208 [ # # ]: 0 : OpenNetworkConnection(item.addr_connect,
4209 : : // We only reconnect if the first attempt to connect succeeded at
4210 : : // connection time, but then failed after the CNode object was
4211 : : // created. Since we already know connecting is possible, do not
4212 : : // count failure to reconnect.
4213 : : /*fCountFailure=*/false,
4214 [ # # ]: 0 : std::move(item.grant),
4215 : 0 : item.destination.empty() ? nullptr : item.destination.c_str(),
4216 : : item.conn_type,
4217 [ # # ]: 0 : item.use_v2transport);
4218 : 0 : }
4219 : 0 : }
4220 : :
4221 : 3391 : void CConnman::ASMapHealthCheck()
4222 : : {
4223 : 3391 : const std::vector<CAddress> v4_addrs{GetAddressesUnsafe(/*max_addresses=*/0, /*max_pct=*/0, Network::NET_IPV4, /*filtered=*/false)};
4224 [ + - ]: 3391 : const std::vector<CAddress> v6_addrs{GetAddressesUnsafe(/*max_addresses=*/0, /*max_pct=*/0, Network::NET_IPV6, /*filtered=*/false)};
4225 : 3391 : std::vector<CNetAddr> clearnet_addrs;
4226 [ - + - + : 3391 : clearnet_addrs.reserve(v4_addrs.size() + v6_addrs.size());
+ - ]
4227 [ + - ]: 3391 : std::transform(v4_addrs.begin(), v4_addrs.end(), std::back_inserter(clearnet_addrs),
4228 [ + - ]: 105 : [](const CAddress& addr) { return static_cast<CNetAddr>(addr); });
4229 [ + - ]: 3391 : std::transform(v6_addrs.begin(), v6_addrs.end(), std::back_inserter(clearnet_addrs),
4230 [ + - ]: 1405 : [](const CAddress& addr) { return static_cast<CNetAddr>(addr); });
4231 [ + - ]: 3391 : m_netgroupman.ASMapHealthCheck(clearnet_addrs);
4232 : 3391 : }
4233 : :
4234 : : // Dump binary message to file, with timestamp.
4235 : 0 : static void CaptureMessageToFile(const CAddress& addr,
4236 : : const std::string& msg_type,
4237 : : std::span<const unsigned char> data,
4238 : : bool is_incoming)
4239 : : {
4240 : : // Note: This function captures the message at the time of processing,
4241 : : // not at socket receive/send time.
4242 : : // This ensures that the messages are always in order from an application
4243 : : // layer (processing) perspective.
4244 : 0 : auto now = GetTime<std::chrono::microseconds>();
4245 : :
4246 : : // Windows folder names cannot include a colon
4247 : 0 : std::string clean_addr = addr.ToStringAddrPort();
4248 [ # # ]: 0 : std::replace(clean_addr.begin(), clean_addr.end(), ':', '_');
4249 : :
4250 [ # # # # : 0 : fs::path base_path = gArgs.GetDataDirNet() / "message_capture" / fs::u8path(clean_addr);
# # # # ]
4251 [ # # ]: 0 : fs::create_directories(base_path);
4252 : :
4253 [ # # # # ]: 0 : fs::path path = base_path / (is_incoming ? "msgs_recv.dat" : "msgs_sent.dat");
4254 [ # # # # ]: 0 : AutoFile f{fsbridge::fopen(path, "ab")};
4255 : :
4256 [ # # ]: 0 : ser_writedata64(f, now.count());
4257 [ # # # # ]: 0 : f << std::span{msg_type};
4258 [ # # # # ]: 0 : for (auto i = msg_type.length(); i < CMessageHeader::MESSAGE_TYPE_SIZE; ++i) {
4259 [ # # ]: 0 : f << uint8_t{'\0'};
4260 : : }
4261 [ # # ]: 0 : uint32_t size = data.size();
4262 [ # # ]: 0 : ser_writedata32(f, size);
4263 [ # # ]: 0 : f << data;
4264 : :
4265 [ # # # # ]: 0 : if (f.fclose() != 0) {
4266 : 0 : throw std::ios_base::failure(
4267 [ # # # # : 0 : strprintf("Error closing %s after write, file contents are likely incomplete", fs::PathToString(path)));
# # ]
4268 : : }
4269 : 0 : }
4270 : :
4271 : : std::function<void(const CAddress& addr,
4272 : : const std::string& msg_type,
4273 : : std::span<const unsigned char> data,
4274 : : bool is_incoming)>
4275 : : CaptureMessage = CaptureMessageToFile;
|