Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2022 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 : : #if defined(HAVE_CONFIG_H)
# 7 : : #include <config/bitcoin-config.h>
# 8 : : #endif
# 9 : :
# 10 : : #include <net.h>
# 11 : :
# 12 : : #include <addrdb.h>
# 13 : : #include <addrman.h>
# 14 : : #include <banman.h>
# 15 : : #include <clientversion.h>
# 16 : : #include <common/args.h>
# 17 : : #include <compat/compat.h>
# 18 : : #include <consensus/consensus.h>
# 19 : : #include <crypto/sha256.h>
# 20 : : #include <i2p.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 : :
# 39 : : #ifdef WIN32
# 40 : : #include <string.h>
# 41 : : #endif
# 42 : :
# 43 : : #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
# 44 : : #include <ifaddrs.h>
# 45 : : #endif
# 46 : :
# 47 : : #include <algorithm>
# 48 : : #include <array>
# 49 : : #include <cstdint>
# 50 : : #include <functional>
# 51 : : #include <optional>
# 52 : : #include <unordered_map>
# 53 : :
# 54 : : #include <math.h>
# 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 : : /** How long to delay before querying DNS seeds
# 69 : : *
# 70 : : * If we have more than THRESHOLD entries in addrman, then it's likely
# 71 : : * that we got those addresses from having previously connected to the P2P
# 72 : : * network, and that we'll be able to successfully reconnect to the P2P
# 73 : : * network via contacting one of them. So if that's the case, spend a
# 74 : : * little longer trying to connect to known peers before querying the
# 75 : : * DNS seeds.
# 76 : : */
# 77 : : static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11};
# 78 : : static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS{5};
# 79 : : static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers
# 80 : :
# 81 : : /** The default timeframe for -maxuploadtarget. 1 day. */
# 82 : : static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME{60 * 60 * 24};
# 83 : :
# 84 : : // A random time period (0 to 1 seconds) is added to feeler connections to prevent synchronization.
# 85 : : static constexpr auto FEELER_SLEEP_WINDOW{1s};
# 86 : :
# 87 : : /** Frequency to attempt extra connections to reachable networks we're not connected to yet **/
# 88 : : static constexpr auto EXTRA_NETWORK_PEER_INTERVAL{5min};
# 89 : :
# 90 : : /** Used to pass flags to the Bind() function */
# 91 : : enum BindFlags {
# 92 : : BF_NONE = 0,
# 93 : : BF_REPORT_ERROR = (1U << 0),
# 94 : : /**
# 95 : : * Do not call AddLocal() for our special addresses, e.g., for incoming
# 96 : : * Tor connections, to prevent gossiping them over the network.
# 97 : : */
# 98 : : BF_DONT_ADVERTISE = (1U << 1),
# 99 : : };
# 100 : :
# 101 : : // The set of sockets cannot be modified while waiting
# 102 : : // The sleep time needs to be small to avoid new sockets stalling
# 103 : : static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
# 104 : :
# 105 : : const std::string NET_MESSAGE_TYPE_OTHER = "*other*";
# 106 : :
# 107 : : static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
# 108 : : static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
# 109 : : static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256("addrcache")[0:8]
# 110 : : //
# 111 : : // Global state variables
# 112 : : //
# 113 : : bool fDiscover = true;
# 114 : : bool fListen = true;
# 115 : : GlobalMutex g_maplocalhost_mutex;
# 116 : : std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(g_maplocalhost_mutex);
# 117 : : static bool vfLimited[NET_MAX] GUARDED_BY(g_maplocalhost_mutex) = {};
# 118 : : std::string strSubVersion;
# 119 : :
# 120 : : size_t CSerializedNetMsg::GetMemoryUsage() const noexcept
# 121 : 523261 : {
# 122 : : // Don't count the dynamic memory used for the m_type string, by assuming it fits in the
# 123 : : // "small string" optimization area (which stores data inside the object itself, up to some
# 124 : : // size; 15 bytes in modern libstdc++).
# 125 : 523261 : return sizeof(*this) + memusage::DynamicUsage(data);
# 126 : 523261 : }
# 127 : :
# 128 : : void CConnman::AddAddrFetch(const std::string& strDest)
# 129 : 10 : {
# 130 : 10 : LOCK(m_addr_fetches_mutex);
# 131 : 10 : m_addr_fetches.push_back(strDest);
# 132 : 10 : }
# 133 : :
# 134 : : uint16_t GetListenPort()
# 135 : 1181 : {
# 136 : : // If -bind= is provided with ":port" part, use that (first one if multiple are provided).
# 137 [ + + ]: 1228 : for (const std::string& bind_arg : gArgs.GetArgs("-bind")) {
# 138 : 1228 : constexpr uint16_t dummy_port = 0;
# 139 : :
# 140 : 1228 : const std::optional<CService> bind_addr{Lookup(bind_arg, dummy_port, /*fAllowLookup=*/false)};
# 141 [ + + ][ + + ]: 1228 : if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port) return bind_addr->GetPort();
# 142 : 1228 : }
# 143 : :
# 144 : : // Otherwise, if -whitebind= without NetPermissionFlags::NoBan is provided, use that
# 145 : : // (-whitebind= is required to have ":port").
# 146 [ + + ]: 1175 : for (const std::string& whitebind_arg : gArgs.GetArgs("-whitebind")) {
# 147 : 1 : NetWhitebindPermissions whitebind;
# 148 : 1 : bilingual_str error;
# 149 [ + - ]: 1 : if (NetWhitebindPermissions::TryParse(whitebind_arg, whitebind, error)) {
# 150 [ + - ]: 1 : if (!NetPermissions::HasFlag(whitebind.m_flags, NetPermissionFlags::NoBan)) {
# 151 : 1 : return whitebind.m_service.GetPort();
# 152 : 1 : }
# 153 : 1 : }
# 154 : 1 : }
# 155 : :
# 156 : : // Otherwise, if -port= is provided, use that. Otherwise use the default port.
# 157 : 1174 : return static_cast<uint16_t>(gArgs.GetIntArg("-port", Params().GetDefaultPort()));
# 158 : 1175 : }
# 159 : :
# 160 : : // find 'best' local address for a particular peer
# 161 : : bool GetLocal(CService& addr, const CNode& peer)
# 162 : 1192 : {
# 163 [ - + ]: 1192 : if (!fListen)
# 164 : 0 : return false;
# 165 : :
# 166 : 1192 : int nBestScore = -1;
# 167 : 1192 : int nBestReachability = -1;
# 168 : 1192 : {
# 169 : 1192 : LOCK(g_maplocalhost_mutex);
# 170 [ + + ]: 1192 : for (const auto& entry : mapLocalHost)
# 171 : 142 : {
# 172 : : // For privacy reasons, don't advertise our privacy-network address
# 173 : : // to other networks and don't advertise our other-network address
# 174 : : // to privacy networks.
# 175 : 142 : const Network our_net{entry.first.GetNetwork()};
# 176 : 142 : const Network peers_net{peer.ConnectedThroughNetwork()};
# 177 [ + + ]: 142 : if (our_net != peers_net &&
# 178 [ + + ][ + + ]: 142 : (our_net == NET_ONION || our_net == NET_I2P ||
# 179 [ + + ][ + + ]: 114 : peers_net == NET_ONION || peers_net == NET_I2P)) {
# 180 : 72 : continue;
# 181 : 72 : }
# 182 : 70 : int nScore = entry.second.nScore;
# 183 : 70 : int nReachability = entry.first.GetReachabilityFrom(peer.addr);
# 184 [ + + ][ + + ]: 70 : if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
# [ - + ]
# 185 : 36 : {
# 186 : 36 : addr = CService(entry.first, entry.second.nPort);
# 187 : 36 : nBestReachability = nReachability;
# 188 : 36 : nBestScore = nScore;
# 189 : 36 : }
# 190 : 70 : }
# 191 : 1192 : }
# 192 : 1192 : return nBestScore >= 0;
# 193 : 1192 : }
# 194 : :
# 195 : : //! Convert the serialized seeds into usable address objects.
# 196 : : static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
# 197 : 3 : {
# 198 : : // It'll only connect to one or two seed nodes because once it connects,
# 199 : : // it'll get a pile of addresses with newer timestamps.
# 200 : : // Seed nodes are given a random 'last seen time' of between one and two
# 201 : : // weeks ago.
# 202 : 3 : const auto one_week{7 * 24h};
# 203 : 3 : std::vector<CAddress> vSeedsOut;
# 204 : 3 : FastRandomContext rng;
# 205 : 3 : CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
# 206 [ - + ]: 3 : while (!s.eof()) {
# 207 : 0 : CService endpoint;
# 208 : 0 : s >> endpoint;
# 209 : 0 : CAddress addr{endpoint, GetDesirableServiceFlags(NODE_NONE)};
# 210 : 0 : addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - one_week, -one_week);
# 211 [ # # ]: 0 : LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToStringAddrPort());
# 212 : 0 : vSeedsOut.push_back(addr);
# 213 : 0 : }
# 214 : 3 : return vSeedsOut;
# 215 : 3 : }
# 216 : :
# 217 : : // get best local address for a particular peer as a CAddress
# 218 : : // Otherwise, return the unroutable 0.0.0.0 but filled in with
# 219 : : // the normal parameters, since the IP may be changed to a useful
# 220 : : // one by discovery.
# 221 : : CService GetLocalAddress(const CNode& peer)
# 222 : 1192 : {
# 223 : 1192 : CService addr;
# 224 [ + + ]: 1192 : if (GetLocal(addr, peer)) {
# 225 : 30 : return addr;
# 226 : 30 : }
# 227 : 1162 : return CService{CNetAddr(), GetListenPort()};
# 228 : 1192 : }
# 229 : :
# 230 : : static int GetnScore(const CService& addr)
# 231 : 0 : {
# 232 : 0 : LOCK(g_maplocalhost_mutex);
# 233 : 0 : const auto it = mapLocalHost.find(addr);
# 234 [ # # ]: 0 : return (it != mapLocalHost.end()) ? it->second.nScore : 0;
# 235 : 0 : }
# 236 : :
# 237 : : // Is our peer's addrLocal potentially useful as an external IP source?
# 238 : : bool IsPeerAddrLocalGood(CNode *pnode)
# 239 : 1150 : {
# 240 : 1150 : CService addrLocal = pnode->GetAddrLocal();
# 241 [ + + ][ + - ]: 1150 : return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
# [ + - ]
# 242 [ + - ]: 1150 : IsReachable(addrLocal.GetNetwork());
# 243 : 1150 : }
# 244 : :
# 245 : : std::optional<CService> GetLocalAddrForPeer(CNode& node)
# 246 : 1150 : {
# 247 : 1150 : CService addrLocal{GetLocalAddress(node)};
# 248 [ + + ]: 1150 : if (gArgs.GetBoolArg("-addrmantest", false)) {
# 249 : : // use IPv4 loopback during addrmantest
# 250 : 5 : addrLocal = CService(LookupNumeric("127.0.0.1", GetListenPort()));
# 251 : 5 : }
# 252 : : // If discovery is enabled, sometimes give our peer the address it
# 253 : : // tells us that it sees us as in case it has a better idea of our
# 254 : : // address than we do.
# 255 : 1150 : FastRandomContext rng;
# 256 [ + + ][ + - ]: 1150 : if (IsPeerAddrLocalGood(&node) && (!addrLocal.IsRoutable() ||
# 257 [ # # ][ # # ]: 8 : rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0))
# 258 : 8 : {
# 259 [ + + ]: 8 : if (node.IsInboundConn()) {
# 260 : : // For inbound connections, assume both the address and the port
# 261 : : // as seen from the peer.
# 262 : 2 : addrLocal = CService{node.GetAddrLocal()};
# 263 : 6 : } else {
# 264 : : // For outbound connections, assume just the address as seen from
# 265 : : // the peer and leave the port in `addrLocal` as returned by
# 266 : : // `GetLocalAddress()` above. The peer has no way to observe our
# 267 : : // listening port when we have initiated the connection.
# 268 : 6 : addrLocal.SetIP(node.GetAddrLocal());
# 269 : 6 : }
# 270 : 8 : }
# 271 [ + + ][ + + ]: 1150 : if (addrLocal.IsRoutable() || gArgs.GetBoolArg("-addrmantest", false))
# [ + + ]
# 272 : 13 : {
# 273 [ + - ]: 13 : LogPrint(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToStringAddrPort(), node.GetId());
# 274 : 13 : return addrLocal;
# 275 : 13 : }
# 276 : : // Address is unroutable. Don't advertise.
# 277 : 1137 : return std::nullopt;
# 278 : 1150 : }
# 279 : :
# 280 : : /**
# 281 : : * If an IPv6 address belongs to the address range used by the CJDNS network and
# 282 : : * the CJDNS network is reachable (-cjdnsreachable config is set), then change
# 283 : : * the type from NET_IPV6 to NET_CJDNS.
# 284 : : * @param[in] service Address to potentially convert.
# 285 : : * @return a copy of `service` either unmodified or changed to CJDNS.
# 286 : : */
# 287 : : CService MaybeFlipIPv6toCJDNS(const CService& service)
# 288 : 25254 : {
# 289 : 25254 : CService ret{service};
# 290 [ + + ][ + + ]: 25254 : if (ret.m_net == NET_IPV6 && ret.m_addr[0] == 0xfc && IsReachable(NET_CJDNS)) {
# [ + - ]
# 291 : 3 : ret.m_net = NET_CJDNS;
# 292 : 3 : }
# 293 : 25254 : return ret;
# 294 : 25254 : }
# 295 : :
# 296 : : // learn a new local address
# 297 : : bool AddLocal(const CService& addr_, int nScore)
# 298 : 28 : {
# 299 : 28 : CService addr{MaybeFlipIPv6toCJDNS(addr_)};
# 300 : :
# 301 [ + + ]: 28 : if (!addr.IsRoutable())
# 302 : 6 : return false;
# 303 : :
# 304 [ - + ][ # # ]: 22 : if (!fDiscover && nScore < LOCAL_MANUAL)
# 305 : 0 : return false;
# 306 : :
# 307 [ - + ]: 22 : if (!IsReachable(addr))
# 308 : 0 : return false;
# 309 : :
# 310 : 22 : LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
# 311 : :
# 312 : 22 : {
# 313 : 22 : LOCK(g_maplocalhost_mutex);
# 314 : 22 : const auto [it, is_newly_added] = mapLocalHost.emplace(addr, LocalServiceInfo());
# 315 : 22 : LocalServiceInfo &info = it->second;
# 316 [ + - ][ # # ]: 22 : if (is_newly_added || nScore >= info.nScore) {
# 317 [ + - ]: 22 : info.nScore = nScore + (is_newly_added ? 0 : 1);
# 318 : 22 : info.nPort = addr.GetPort();
# 319 : 22 : }
# 320 : 22 : }
# 321 : :
# 322 : 22 : return true;
# 323 : 22 : }
# 324 : :
# 325 : : bool AddLocal(const CNetAddr &addr, int nScore)
# 326 : 6 : {
# 327 : 6 : return AddLocal(CService(addr, GetListenPort()), nScore);
# 328 : 6 : }
# 329 : :
# 330 : : void RemoveLocal(const CService& addr)
# 331 : 22 : {
# 332 : 22 : LOCK(g_maplocalhost_mutex);
# 333 : 22 : LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort());
# 334 : 22 : mapLocalHost.erase(addr);
# 335 : 22 : }
# 336 : :
# 337 : : void SetReachable(enum Network net, bool reachable)
# 338 : 2124 : {
# 339 [ + + ][ + + ]: 2124 : if (net == NET_UNROUTABLE || net == NET_INTERNAL)
# 340 : 18 : return;
# 341 : 2106 : LOCK(g_maplocalhost_mutex);
# 342 : 2106 : vfLimited[net] = !reachable;
# 343 : 2106 : }
# 344 : :
# 345 : : bool IsReachable(enum Network net)
# 346 : 2198 : {
# 347 : 2198 : LOCK(g_maplocalhost_mutex);
# 348 : 2198 : return !vfLimited[net];
# 349 : 2198 : }
# 350 : :
# 351 : : bool IsReachable(const CNetAddr &addr)
# 352 : 1308 : {
# 353 : 1308 : return IsReachable(addr.GetNetwork());
# 354 : 1308 : }
# 355 : :
# 356 : : /** vote for a local address */
# 357 : : bool SeenLocal(const CService& addr)
# 358 : 0 : {
# 359 : 0 : LOCK(g_maplocalhost_mutex);
# 360 : 0 : const auto it = mapLocalHost.find(addr);
# 361 [ # # ]: 0 : if (it == mapLocalHost.end()) return false;
# 362 : 0 : ++it->second.nScore;
# 363 : 0 : return true;
# 364 : 0 : }
# 365 : :
# 366 : :
# 367 : : /** check whether a given address is potentially local */
# 368 : : bool IsLocal(const CService& addr)
# 369 : 9 : {
# 370 : 9 : LOCK(g_maplocalhost_mutex);
# 371 : 9 : return mapLocalHost.count(addr) > 0;
# 372 : 9 : }
# 373 : :
# 374 : : CNode* CConnman::FindNode(const CNetAddr& ip)
# 375 : 1 : {
# 376 : 1 : LOCK(m_nodes_mutex);
# 377 [ - + ]: 1 : for (CNode* pnode : m_nodes) {
# 378 [ # # ]: 0 : if (static_cast<CNetAddr>(pnode->addr) == ip) {
# 379 : 0 : return pnode;
# 380 : 0 : }
# 381 : 0 : }
# 382 : 1 : return nullptr;
# 383 : 1 : }
# 384 : :
# 385 : : CNode* CConnman::FindNode(const CSubNet& subNet)
# 386 : 0 : {
# 387 : 0 : LOCK(m_nodes_mutex);
# 388 [ # # ]: 0 : for (CNode* pnode : m_nodes) {
# 389 [ # # ]: 0 : if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
# 390 : 0 : return pnode;
# 391 : 0 : }
# 392 : 0 : }
# 393 : 0 : return nullptr;
# 394 : 0 : }
# 395 : :
# 396 : : CNode* CConnman::FindNode(const std::string& addrName)
# 397 : 384 : {
# 398 : 384 : LOCK(m_nodes_mutex);
# 399 [ + + ]: 386 : for (CNode* pnode : m_nodes) {
# 400 [ + + ]: 386 : if (pnode->m_addr_name == addrName) {
# 401 : 1 : return pnode;
# 402 : 1 : }
# 403 : 386 : }
# 404 : 383 : return nullptr;
# 405 : 384 : }
# 406 : :
# 407 : : CNode* CConnman::FindNode(const CService& addr)
# 408 : 367 : {
# 409 : 367 : LOCK(m_nodes_mutex);
# 410 [ + + ]: 367 : for (CNode* pnode : m_nodes) {
# 411 [ - + ]: 364 : if (static_cast<CService>(pnode->addr) == addr) {
# 412 : 0 : return pnode;
# 413 : 0 : }
# 414 : 364 : }
# 415 : 367 : return nullptr;
# 416 : 367 : }
# 417 : :
# 418 : : bool CConnman::AlreadyConnectedToAddress(const CAddress& addr)
# 419 : 1 : {
# 420 [ - + ][ - + ]: 1 : return FindNode(static_cast<CNetAddr>(addr)) || FindNode(addr.ToStringAddrPort());
# 421 : 1 : }
# 422 : :
# 423 : : bool CConnman::CheckIncomingNonce(uint64_t nonce)
# 424 : 701 : {
# 425 : 701 : LOCK(m_nodes_mutex);
# 426 [ + + ]: 2184 : for (const CNode* pnode : m_nodes) {
# 427 [ + + ][ - + ]: 2184 : if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() == nonce)
# [ # # ]
# 428 : 0 : return false;
# 429 : 2184 : }
# 430 : 701 : return true;
# 431 : 701 : }
# 432 : :
# 433 : : /** Get the bind address for a socket as CAddress */
# 434 : : static CAddress GetBindAddress(const Sock& sock)
# 435 : 1073 : {
# 436 : 1073 : CAddress addr_bind;
# 437 : 1073 : struct sockaddr_storage sockaddr_bind;
# 438 : 1073 : socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
# 439 [ + - ]: 1073 : if (sock.Get() != INVALID_SOCKET) {
# 440 [ + - ]: 1073 : if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
# 441 : 1073 : addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
# 442 : 1073 : } else {
# 443 [ # # ]: 0 : LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
# 444 : 0 : }
# 445 : 1073 : }
# 446 : 1073 : return addr_bind;
# 447 : 1073 : }
# 448 : :
# 449 : : CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type)
# 450 : 382 : {
# 451 : 382 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
# 452 : 382 : assert(conn_type != ConnectionType::INBOUND);
# 453 : :
# 454 [ + + ]: 382 : if (pszDest == nullptr) {
# 455 [ - + ]: 1 : if (IsLocal(addrConnect))
# 456 : 0 : return nullptr;
# 457 : :
# 458 : : // Look for an existing connection
# 459 : 1 : CNode* pnode = FindNode(static_cast<CService>(addrConnect));
# 460 [ - + ]: 1 : if (pnode)
# 461 : 0 : {
# 462 : 0 : LogPrintf("Failed to open new connection, already connected\n");
# 463 : 0 : return nullptr;
# 464 : 0 : }
# 465 : 1 : }
# 466 : :
# 467 [ + - ][ + + ]: 382 : LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "trying connection %s lastseen=%.1fhrs\n",
# [ + + ]
# 468 : 382 : pszDest ? pszDest : addrConnect.ToStringAddrPort(),
# 469 : 382 : Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.nTime));
# 470 : :
# 471 : : // Resolve
# 472 [ + + ]: 382 : const uint16_t default_port{pszDest != nullptr ? Params().GetDefaultPort(pszDest) :
# 473 : 382 : Params().GetDefaultPort()};
# 474 [ + + ]: 382 : if (pszDest) {
# 475 [ + - ][ + + ]: 381 : const std::vector<CService> resolved{Lookup(pszDest, default_port, fNameLookup && !HaveNameProxy(), 256)};
# 476 [ + + ]: 381 : if (!resolved.empty()) {
# 477 : 368 : const CService& rnd{resolved[GetRand(resolved.size())]};
# 478 : 368 : addrConnect = CAddress{MaybeFlipIPv6toCJDNS(rnd), NODE_NONE};
# 479 [ + + ]: 368 : if (!addrConnect.IsValid()) {
# 480 [ + - ]: 2 : LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToStringAddrPort(), pszDest);
# 481 : 2 : return nullptr;
# 482 : 2 : }
# 483 : : // It is possible that we already have a connection to the IP/port pszDest resolved to.
# 484 : : // In that case, drop the connection that was just created.
# 485 : 366 : LOCK(m_nodes_mutex);
# 486 : 366 : CNode* pnode = FindNode(static_cast<CService>(addrConnect));
# 487 [ - + ]: 366 : if (pnode) {
# 488 : 0 : LogPrintf("Failed to open new connection, already connected\n");
# 489 : 0 : return nullptr;
# 490 : 0 : }
# 491 : 366 : }
# 492 : 381 : }
# 493 : :
# 494 : : // Connect
# 495 : 380 : bool connected = false;
# 496 : 380 : std::unique_ptr<Sock> sock;
# 497 : 380 : Proxy proxy;
# 498 : 380 : CAddress addr_bind;
# 499 : 380 : assert(!addr_bind.IsValid());
# 500 : 380 : std::unique_ptr<i2p::sam::Session> i2p_transient_session;
# 501 : :
# 502 [ + + ]: 380 : if (addrConnect.IsValid()) {
# 503 : 367 : const bool use_proxy{GetProxy(addrConnect.GetNetwork(), proxy)};
# 504 : 367 : bool proxyConnectionFailed = false;
# 505 : :
# 506 [ + + ][ + - ]: 367 : if (addrConnect.GetNetwork() == NET_I2P && use_proxy) {
# 507 : 4 : i2p::Connection conn;
# 508 : :
# 509 [ + + ]: 4 : if (m_i2p_sam_session) {
# 510 : 3 : connected = m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed);
# 511 : 3 : } else {
# 512 : 1 : {
# 513 : 1 : LOCK(m_unused_i2p_sessions_mutex);
# 514 [ + - ]: 1 : if (m_unused_i2p_sessions.empty()) {
# 515 : 1 : i2p_transient_session =
# 516 : 1 : std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet);
# 517 : 1 : } else {
# 518 : 0 : i2p_transient_session.swap(m_unused_i2p_sessions.front());
# 519 : 0 : m_unused_i2p_sessions.pop();
# 520 : 0 : }
# 521 : 1 : }
# 522 : 1 : connected = i2p_transient_session->Connect(addrConnect, conn, proxyConnectionFailed);
# 523 [ + - ]: 1 : if (!connected) {
# 524 : 1 : LOCK(m_unused_i2p_sessions_mutex);
# 525 [ + - ]: 1 : if (m_unused_i2p_sessions.size() < MAX_UNUSED_I2P_SESSIONS_SIZE) {
# 526 : 1 : m_unused_i2p_sessions.emplace(i2p_transient_session.release());
# 527 : 1 : }
# 528 : 1 : }
# 529 : 1 : }
# 530 : :
# 531 [ - + ]: 4 : if (connected) {
# 532 : 0 : sock = std::move(conn.sock);
# 533 : 0 : addr_bind = CAddress{conn.me, NODE_NONE};
# 534 : 0 : }
# 535 [ + + ]: 363 : } else if (use_proxy) {
# 536 : 17 : sock = CreateSock(proxy.proxy);
# 537 [ - + ]: 17 : if (!sock) {
# 538 : 0 : return nullptr;
# 539 : 0 : }
# 540 : 17 : connected = ConnectThroughProxy(proxy, addrConnect.ToStringAddr(), addrConnect.GetPort(),
# 541 : 17 : *sock, nConnectTimeout, proxyConnectionFailed);
# 542 : 346 : } else {
# 543 : : // no proxy needed (none set for target network)
# 544 : 346 : sock = CreateSock(addrConnect);
# 545 [ - + ]: 346 : if (!sock) {
# 546 : 0 : return nullptr;
# 547 : 0 : }
# 548 : 346 : connected = ConnectSocketDirectly(addrConnect, *sock, nConnectTimeout,
# 549 : 346 : conn_type == ConnectionType::MANUAL);
# 550 : 346 : }
# 551 [ + + ]: 367 : if (!proxyConnectionFailed) {
# 552 : : // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
# 553 : : // the proxy, mark this as an attempt.
# 554 : 364 : addrman.Attempt(addrConnect, fCountFailure);
# 555 : 364 : }
# 556 [ + - ][ + + ]: 367 : } else if (pszDest && GetNameProxy(proxy)) {
# 557 : 7 : sock = CreateSock(proxy.proxy);
# 558 [ - + ]: 7 : if (!sock) {
# 559 : 0 : return nullptr;
# 560 : 0 : }
# 561 : 7 : std::string host;
# 562 : 7 : uint16_t port{default_port};
# 563 : 7 : SplitHostPort(std::string(pszDest), port, host);
# 564 : 7 : bool proxyConnectionFailed;
# 565 : 7 : connected = ConnectThroughProxy(proxy, host, port, *sock, nConnectTimeout,
# 566 : 7 : proxyConnectionFailed);
# 567 : 7 : }
# 568 [ + + ]: 380 : if (!connected) {
# 569 : 14 : return nullptr;
# 570 : 14 : }
# 571 : :
# 572 : : // Add node
# 573 : 366 : NodeId id = GetNewNodeId();
# 574 : 366 : uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
# 575 [ + - ]: 366 : if (!addr_bind.IsValid()) {
# 576 : 366 : addr_bind = GetBindAddress(*sock);
# 577 : 366 : }
# 578 : 366 : CNode* pnode = new CNode(id,
# 579 : 366 : std::move(sock),
# 580 : 366 : addrConnect,
# 581 : 366 : CalculateKeyedNetGroup(addrConnect),
# 582 : 366 : nonce,
# 583 : 366 : addr_bind,
# 584 [ + - ]: 366 : pszDest ? pszDest : "",
# 585 : 366 : conn_type,
# 586 : 366 : /*inbound_onion=*/false,
# 587 : 366 : CNodeOptions{
# 588 : 366 : .i2p_sam_session = std::move(i2p_transient_session),
# 589 : 366 : .recv_flood_size = nReceiveFloodSize,
# 590 : 366 : });
# 591 : 366 : pnode->AddRef();
# 592 : :
# 593 : : // We're making a new connection, harvest entropy from the time (and our peer count)
# 594 : 366 : RandAddEvent((uint32_t)id);
# 595 : :
# 596 : 366 : return pnode;
# 597 : 380 : }
# 598 : :
# 599 : : void CNode::CloseSocketDisconnect()
# 600 : 1373 : {
# 601 : 1373 : fDisconnect = true;
# 602 : 1373 : LOCK(m_sock_mutex);
# 603 [ + + ]: 1373 : if (m_sock) {
# 604 [ + - ]: 1072 : LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
# 605 : 1072 : m_sock.reset();
# 606 : 1072 : }
# 607 : 1373 : m_i2p_sam_session.reset();
# 608 : 1373 : }
# 609 : :
# 610 : 707 : void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const {
# 611 [ + + ]: 707 : for (const auto& subnet : vWhitelistedRange) {
# 612 [ + - ]: 163 : if (subnet.m_subnet.Match(addr)) NetPermissions::AddFlag(flags, subnet.m_flags);
# 613 : 163 : }
# 614 : 707 : }
# 615 : :
# 616 : : CService CNode::GetAddrLocal() const
# 617 : 10258 : {
# 618 : 10258 : AssertLockNotHeld(m_addr_local_mutex);
# 619 : 10258 : LOCK(m_addr_local_mutex);
# 620 : 10258 : return addrLocal;
# 621 : 10258 : }
# 622 : :
# 623 : 1055 : void CNode::SetAddrLocal(const CService& addrLocalIn) {
# 624 : 1055 : AssertLockNotHeld(m_addr_local_mutex);
# 625 : 1055 : LOCK(m_addr_local_mutex);
# 626 [ - + ]: 1055 : if (addrLocal.IsValid()) {
# 627 : 0 : error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToStringAddrPort(), addrLocalIn.ToStringAddrPort());
# 628 : 1055 : } else {
# 629 : 1055 : addrLocal = addrLocalIn;
# 630 : 1055 : }
# 631 : 1055 : }
# 632 : :
# 633 : : Network CNode::ConnectedThroughNetwork() const
# 634 : 9927 : {
# 635 [ + + ]: 9927 : return m_inbound_onion ? NET_ONION : addr.GetNetClass();
# 636 : 9927 : }
# 637 : :
# 638 : : #undef X
# 639 : 191100 : #define X(name) stats.name = name
# 640 : : void CNode::CopyStats(CNodeStats& stats)
# 641 : 9100 : {
# 642 : 9100 : stats.nodeid = this->GetId();
# 643 : 9100 : X(addr);
# 644 : 9100 : X(addrBind);
# 645 : 9100 : stats.m_network = ConnectedThroughNetwork();
# 646 : 9100 : X(m_last_send);
# 647 : 9100 : X(m_last_recv);
# 648 : 9100 : X(m_last_tx_time);
# 649 : 9100 : X(m_last_block_time);
# 650 : 9100 : X(m_connected);
# 651 : 9100 : X(nTimeOffset);
# 652 : 9100 : X(m_addr_name);
# 653 : 9100 : X(nVersion);
# 654 : 9100 : {
# 655 : 9100 : LOCK(m_subver_mutex);
# 656 : 9100 : X(cleanSubVer);
# 657 : 9100 : }
# 658 : 9100 : stats.fInbound = IsInboundConn();
# 659 : 9100 : X(m_bip152_highbandwidth_to);
# 660 : 9100 : X(m_bip152_highbandwidth_from);
# 661 : 9100 : {
# 662 : 9100 : LOCK(cs_vSend);
# 663 : 9100 : X(mapSendBytesPerMsgType);
# 664 : 9100 : X(nSendBytes);
# 665 : 9100 : }
# 666 : 9100 : {
# 667 : 9100 : LOCK(cs_vRecv);
# 668 : 9100 : X(mapRecvBytesPerMsgType);
# 669 : 9100 : X(nRecvBytes);
# 670 : 9100 : }
# 671 : 9100 : X(m_permission_flags);
# 672 : :
# 673 : 9100 : X(m_last_ping_time);
# 674 : 9100 : X(m_min_ping_time);
# 675 : :
# 676 : : // Leave string empty if addrLocal invalid (not filled in yet)
# 677 : 9100 : CService addrLocalUnlocked = GetAddrLocal();
# 678 [ + + ]: 9100 : stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
# 679 : :
# 680 : 9100 : X(m_conn_type);
# 681 : 9100 : }
# 682 : : #undef X
# 683 : :
# 684 : : bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete)
# 685 : 150830 : {
# 686 : 150830 : complete = false;
# 687 : 150830 : const auto time = GetTime<std::chrono::microseconds>();
# 688 : 150830 : LOCK(cs_vRecv);
# 689 : 150830 : m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time);
# 690 : 150830 : nRecvBytes += msg_bytes.size();
# 691 [ + + ]: 422959 : while (msg_bytes.size() > 0) {
# 692 : : // absorb network data
# 693 [ + + ]: 272132 : if (!m_transport->ReceivedBytes(msg_bytes)) {
# 694 : : // Serious transport problem, disconnect from the peer.
# 695 : 3 : return false;
# 696 : 3 : }
# 697 : :
# 698 [ + + ]: 272129 : if (m_transport->ReceivedMessageComplete()) {
# 699 : : // decompose a transport agnostic CNetMessage from the deserializer
# 700 : 126732 : bool reject_message{false};
# 701 : 126732 : CNetMessage msg = m_transport->GetReceivedMessage(time, reject_message);
# 702 [ + + ]: 126732 : if (reject_message) {
# 703 : : // Message deserialization failed. Drop the message but don't disconnect the peer.
# 704 : : // store the size of the corrupt message
# 705 : 82 : mapRecvBytesPerMsgType.at(NET_MESSAGE_TYPE_OTHER) += msg.m_raw_message_size;
# 706 : 82 : continue;
# 707 : 82 : }
# 708 : :
# 709 : : // Store received bytes per message type.
# 710 : : // To prevent a memory DOS, only allow known message types.
# 711 : 126650 : auto i = mapRecvBytesPerMsgType.find(msg.m_type);
# 712 [ + + ]: 126650 : if (i == mapRecvBytesPerMsgType.end()) {
# 713 : 3 : i = mapRecvBytesPerMsgType.find(NET_MESSAGE_TYPE_OTHER);
# 714 : 3 : }
# 715 : 126650 : assert(i != mapRecvBytesPerMsgType.end());
# 716 : 126650 : i->second += msg.m_raw_message_size;
# 717 : :
# 718 : : // push the message to the process queue,
# 719 : 126650 : vRecvMsg.push_back(std::move(msg));
# 720 : :
# 721 : 126650 : complete = true;
# 722 : 126650 : }
# 723 : 272129 : }
# 724 : :
# 725 : 150827 : return true;
# 726 : 150830 : }
# 727 : :
# 728 : : V1Transport::V1Transport(const NodeId node_id, int nTypeIn, int nVersionIn) noexcept :
# 729 : : m_node_id(node_id), hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn)
# 730 : 366288 : {
# 731 : 366288 : assert(std::size(Params().MessageStart()) == std::size(m_magic_bytes));
# 732 : 366288 : std::copy(std::begin(Params().MessageStart()), std::end(Params().MessageStart()), m_magic_bytes);
# 733 : 366288 : LOCK(m_recv_mutex);
# 734 : 366288 : Reset();
# 735 : 366288 : }
# 736 : :
# 737 : : int V1Transport::readHeader(Span<const uint8_t> msg_bytes)
# 738 : 186730 : {
# 739 : 186730 : AssertLockHeld(m_recv_mutex);
# 740 : : // copy data to temporary parsing buffer
# 741 : 186730 : unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos;
# 742 : 186730 : unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
# 743 : :
# 744 : 186730 : memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy);
# 745 : 186730 : nHdrPos += nCopy;
# 746 : :
# 747 : : // if header incomplete, exit
# 748 [ + + ]: 186730 : if (nHdrPos < CMessageHeader::HEADER_SIZE)
# 749 : 32283 : return nCopy;
# 750 : :
# 751 : : // deserialize to CMessageHeader
# 752 : 154447 : try {
# 753 : 154447 : hdrbuf >> hdr;
# 754 : 154447 : }
# 755 : 154447 : catch (const std::exception&) {
# 756 [ # # ]: 0 : LogPrint(BCLog::NET, "Header error: Unable to deserialize, peer=%d\n", m_node_id);
# 757 : 0 : return -1;
# 758 : 0 : }
# 759 : :
# 760 : : // Check start string, network magic
# 761 [ + + ]: 154447 : if (memcmp(hdr.pchMessageStart, m_magic_bytes, CMessageHeader::MESSAGE_START_SIZE) != 0) {
# 762 [ + - ]: 1 : LogPrint(BCLog::NET, "Header error: Wrong MessageStart %s received, peer=%d\n", HexStr(hdr.pchMessageStart), m_node_id);
# 763 : 1 : return -1;
# 764 : 1 : }
# 765 : :
# 766 : : // reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH
# 767 [ - + ][ + + ]: 154446 : if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
# 768 [ + - ]: 2 : LogPrint(BCLog::NET, "Header error: Size too large (%s, %u bytes), peer=%d\n", SanitizeString(hdr.GetCommand()), hdr.nMessageSize, m_node_id);
# 769 : 2 : return -1;
# 770 : 2 : }
# 771 : :
# 772 : : // switch state to reading message data
# 773 : 154444 : in_data = true;
# 774 : :
# 775 : 154444 : return nCopy;
# 776 : 154446 : }
# 777 : :
# 778 : : int V1Transport::readData(Span<const uint8_t> msg_bytes)
# 779 : 191840 : {
# 780 : 191840 : AssertLockHeld(m_recv_mutex);
# 781 : 191840 : unsigned int nRemaining = hdr.nMessageSize - nDataPos;
# 782 : 191840 : unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
# 783 : :
# 784 [ + + ]: 191840 : if (vRecv.size() < nDataPos + nCopy) {
# 785 : : // Allocate up to 256 KiB ahead, but never more than the total message size.
# 786 : 152189 : vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
# 787 : 152189 : }
# 788 : :
# 789 : 191840 : hasher.Write(msg_bytes.first(nCopy));
# 790 : 191840 : memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy);
# 791 : 191840 : nDataPos += nCopy;
# 792 : :
# 793 : 191840 : return nCopy;
# 794 : 191840 : }
# 795 : :
# 796 : : const uint256& V1Transport::GetMessageHash() const
# 797 : 154441 : {
# 798 : 154441 : AssertLockHeld(m_recv_mutex);
# 799 : 154441 : assert(CompleteInternal());
# 800 [ + - ]: 154441 : if (data_hash.IsNull())
# 801 : 154441 : hasher.Finalize(data_hash);
# 802 : 154441 : return data_hash;
# 803 : 154441 : }
# 804 : :
# 805 : : CNetMessage V1Transport::GetReceivedMessage(const std::chrono::microseconds time, bool& reject_message)
# 806 : 154441 : {
# 807 : 154441 : AssertLockNotHeld(m_recv_mutex);
# 808 : : // Initialize out parameter
# 809 : 154441 : reject_message = false;
# 810 : : // decompose a single CNetMessage from the TransportDeserializer
# 811 : 154441 : LOCK(m_recv_mutex);
# 812 : 154441 : CNetMessage msg(std::move(vRecv));
# 813 : :
# 814 : : // store message type string, time, and sizes
# 815 : 154441 : msg.m_type = hdr.GetCommand();
# 816 : 154441 : msg.m_time = time;
# 817 : 154441 : msg.m_message_size = hdr.nMessageSize;
# 818 : 154441 : msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
# 819 : :
# 820 : 154441 : uint256 hash = GetMessageHash();
# 821 : :
# 822 : : // We just received a message off the wire, harvest entropy from the time (and the message checksum)
# 823 : 154441 : RandAddEvent(ReadLE32(hash.begin()));
# 824 : :
# 825 : : // Check checksum and header message type string
# 826 [ + + ]: 154441 : if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) {
# 827 [ + - ]: 1 : LogPrint(BCLog::NET, "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
# 828 : 1 : SanitizeString(msg.m_type), msg.m_message_size,
# 829 : 1 : HexStr(Span{hash}.first(CMessageHeader::CHECKSUM_SIZE)),
# 830 : 1 : HexStr(hdr.pchChecksum),
# 831 : 1 : m_node_id);
# 832 : 1 : reject_message = true;
# 833 [ + + ]: 154440 : } else if (!hdr.IsCommandValid()) {
# 834 [ + - ]: 81 : LogPrint(BCLog::NET, "Header error: Invalid message type (%s, %u bytes), peer=%d\n",
# 835 : 81 : SanitizeString(hdr.GetCommand()), msg.m_message_size, m_node_id);
# 836 : 81 : reject_message = true;
# 837 : 81 : }
# 838 : :
# 839 : : // Always reset the network deserializer (prepare for the next message)
# 840 : 154441 : Reset();
# 841 : 154441 : return msg;
# 842 : 154441 : }
# 843 : :
# 844 : : bool V1Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
# 845 : 707782 : {
# 846 : 707782 : AssertLockNotHeld(m_send_mutex);
# 847 : : // Determine whether a new message can be set.
# 848 : 707782 : LOCK(m_send_mutex);
# 849 [ + + ][ + + ]: 707782 : if (m_sending_header || m_bytes_sent < m_message_to_send.data.size()) return false;
# 850 : :
# 851 : : // create dbl-sha256 checksum
# 852 : 158446 : uint256 hash = Hash(msg.data);
# 853 : :
# 854 : : // create header
# 855 : 158446 : CMessageHeader hdr(m_magic_bytes, msg.m_type.c_str(), msg.data.size());
# 856 : 158446 : memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
# 857 : :
# 858 : : // serialize header
# 859 : 158446 : m_header_to_send.clear();
# 860 : 158446 : CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, m_header_to_send, 0, hdr};
# 861 : :
# 862 : : // update state
# 863 : 158446 : m_message_to_send = std::move(msg);
# 864 : 158446 : m_sending_header = true;
# 865 : 158446 : m_bytes_sent = 0;
# 866 : 158446 : return true;
# 867 : 707782 : }
# 868 : :
# 869 : : Transport::BytesToSend V1Transport::GetBytesToSend(bool have_next_message) const noexcept
# 870 : 3507860 : {
# 871 : 3507860 : AssertLockNotHeld(m_send_mutex);
# 872 : 3507860 : LOCK(m_send_mutex);
# 873 [ + + ]: 3507860 : if (m_sending_header) {
# 874 : 1548525 : return {Span{m_header_to_send}.subspan(m_bytes_sent),
# 875 : : // We have more to send after the header if the message has payload, or if there
# 876 : : // is a next message after that.
# 877 [ + + ][ + + ]: 1548525 : have_next_message || !m_message_to_send.data.empty(),
# 878 : 1548525 : m_message_to_send.m_type
# 879 : 1548525 : };
# 880 : 1959335 : } else {
# 881 : 1959335 : return {Span{m_message_to_send.data}.subspan(m_bytes_sent),
# 882 : : // We only have more to send after this message's payload if there is another
# 883 : : // message.
# 884 : 1959335 : have_next_message,
# 885 : 1959335 : m_message_to_send.m_type
# 886 : 1959335 : };
# 887 : 1959335 : }
# 888 : 3507860 : }
# 889 : :
# 890 : : void V1Transport::MarkBytesSent(size_t bytes_sent) noexcept
# 891 : 416017 : {
# 892 : 416017 : AssertLockNotHeld(m_send_mutex);
# 893 : 416017 : LOCK(m_send_mutex);
# 894 : 416017 : m_bytes_sent += bytes_sent;
# 895 [ + + ][ + + ]: 416017 : if (m_sending_header && m_bytes_sent == m_header_to_send.size()) {
# 896 : : // We're done sending a message's header. Switch to sending its data bytes.
# 897 : 158410 : m_sending_header = false;
# 898 : 158410 : m_bytes_sent = 0;
# 899 [ + + ][ + + ]: 257607 : } else if (!m_sending_header && m_bytes_sent == m_message_to_send.data.size()) {
# 900 : : // We're done sending a message's data. Wipe the data vector to reduce memory consumption.
# 901 : 151612 : m_message_to_send.data.clear();
# 902 : 151612 : m_message_to_send.data.shrink_to_fit();
# 903 : 151612 : m_bytes_sent = 0;
# 904 : 151612 : }
# 905 : 416017 : }
# 906 : :
# 907 : : size_t V1Transport::GetSendMemoryUsage() const noexcept
# 908 : 261720 : {
# 909 : 261720 : AssertLockNotHeld(m_send_mutex);
# 910 : 261720 : LOCK(m_send_mutex);
# 911 : : // Don't count sending-side fields besides m_message_to_send, as they're all small and bounded.
# 912 : 261720 : return m_message_to_send.GetMemoryUsage();
# 913 : 261720 : }
# 914 : :
# 915 : : namespace {
# 916 : :
# 917 : : /** List of short messages as defined in BIP324, in order.
# 918 : : *
# 919 : : * Only message types that are actually implemented in this codebase need to be listed, as other
# 920 : : * messages get ignored anyway - whether we know how to decode them or not.
# 921 : : */
# 922 : : const std::string V2_MESSAGE_IDS[] = {
# 923 : : "", // 12 bytes follow encoding the message type like in V1
# 924 : : NetMsgType::ADDR,
# 925 : : NetMsgType::BLOCK,
# 926 : : NetMsgType::BLOCKTXN,
# 927 : : NetMsgType::CMPCTBLOCK,
# 928 : : NetMsgType::FEEFILTER,
# 929 : : NetMsgType::FILTERADD,
# 930 : : NetMsgType::FILTERCLEAR,
# 931 : : NetMsgType::FILTERLOAD,
# 932 : : NetMsgType::GETBLOCKS,
# 933 : : NetMsgType::GETBLOCKTXN,
# 934 : : NetMsgType::GETDATA,
# 935 : : NetMsgType::GETHEADERS,
# 936 : : NetMsgType::HEADERS,
# 937 : : NetMsgType::INV,
# 938 : : NetMsgType::MEMPOOL,
# 939 : : NetMsgType::MERKLEBLOCK,
# 940 : : NetMsgType::NOTFOUND,
# 941 : : NetMsgType::PING,
# 942 : : NetMsgType::PONG,
# 943 : : NetMsgType::SENDCMPCT,
# 944 : : NetMsgType::TX,
# 945 : : NetMsgType::GETCFILTERS,
# 946 : : NetMsgType::CFILTER,
# 947 : : NetMsgType::GETCFHEADERS,
# 948 : : NetMsgType::CFHEADERS,
# 949 : : NetMsgType::GETCFCHECKPT,
# 950 : : NetMsgType::CFCHECKPT,
# 951 : : NetMsgType::ADDRV2,
# 952 : : // Unimplemented message types that are assigned in BIP324:
# 953 : : "",
# 954 : : "",
# 955 : : "",
# 956 : : ""
# 957 : : };
# 958 : :
# 959 : : static_assert(std::size(V2_MESSAGE_IDS) == 33);
# 960 : :
# 961 : : class V2MessageMap
# 962 : : {
# 963 : : std::unordered_map<std::string, uint8_t> m_map;
# 964 : :
# 965 : : public:
# 966 : : V2MessageMap() noexcept
# 967 : 800 : {
# 968 [ + + ]: 26400 : for (size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
# 969 : 25600 : m_map.emplace(V2_MESSAGE_IDS[i], i);
# 970 : 25600 : }
# 971 : 800 : }
# 972 : :
# 973 : : std::optional<uint8_t> operator()(const std::string& message_name) const noexcept
# 974 : 5593 : {
# 975 : 5593 : auto it = m_map.find(message_name);
# 976 [ + + ]: 5593 : if (it == m_map.end()) return std::nullopt;
# 977 : 99 : return it->second;
# 978 : 5593 : }
# 979 : : };
# 980 : :
# 981 : : const V2MessageMap V2_MESSAGE_MAP;
# 982 : :
# 983 : : } // namespace
# 984 : :
# 985 : : V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int version_in) noexcept :
# 986 : : m_cipher{}, m_initiating{initiating}, m_nodeid{nodeid},
# 987 : : m_v1_fallback{nodeid, type_in, version_in}, m_recv_type{type_in}, m_recv_version{version_in},
# 988 : : m_recv_state{initiating ? RecvState::KEY : RecvState::KEY_MAYBE_V1},
# 989 : : m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
# 990 : 150 : {
# 991 : : // Construct garbage (including its length) using a FastRandomContext.
# 992 : 150 : FastRandomContext rng;
# 993 : 150 : size_t garbage_len = rng.randrange(MAX_GARBAGE_LEN + 1);
# 994 : : // Initialize the send buffer with ellswift pubkey + garbage.
# 995 : 150 : m_send_buffer.resize(EllSwiftPubKey::size() + garbage_len);
# 996 : 150 : std::copy(std::begin(m_cipher.GetOurPubKey()), std::end(m_cipher.GetOurPubKey()), MakeWritableByteSpan(m_send_buffer).begin());
# 997 : 150 : rng.fillrand(MakeWritableByteSpan(m_send_buffer).subspan(EllSwiftPubKey::size()));
# 998 : 150 : }
# 999 : :
# 1000 : : V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int version_in, const CKey& key, Span<const std::byte> ent32, Span<const uint8_t> garbage) noexcept :
# 1001 : : m_cipher{key, ent32}, m_initiating{initiating}, m_nodeid{nodeid},
# 1002 : : m_v1_fallback{nodeid, type_in, version_in}, m_recv_type{type_in}, m_recv_version{version_in},
# 1003 : : m_recv_state{initiating ? RecvState::KEY : RecvState::KEY_MAYBE_V1},
# 1004 : : m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1}
# 1005 : 340050 : {
# 1006 : 340050 : assert(garbage.size() <= MAX_GARBAGE_LEN);
# 1007 : : // Initialize the send buffer with ellswift pubkey + provided garbage.
# 1008 : 340050 : m_send_buffer.resize(EllSwiftPubKey::size() + garbage.size());
# 1009 : 340050 : std::copy(std::begin(m_cipher.GetOurPubKey()), std::end(m_cipher.GetOurPubKey()), MakeWritableByteSpan(m_send_buffer).begin());
# 1010 : 340050 : std::copy(garbage.begin(), garbage.end(), m_send_buffer.begin() + EllSwiftPubKey::size());
# 1011 : 340050 : }
# 1012 : :
# 1013 : : void V2Transport::SetReceiveState(RecvState recv_state) noexcept
# 1014 : 1139624 : {
# 1015 : 1139624 : AssertLockHeld(m_recv_mutex);
# 1016 : : // Enforce allowed state transitions.
# 1017 [ - + ]: 1139624 : switch (m_recv_state) {
# 1018 [ + + ]: 141918 : case RecvState::KEY_MAYBE_V1:
# 1019 [ + + ][ + - ]: 141918 : Assume(recv_state == RecvState::KEY || recv_state == RecvState::V1);
# 1020 : 141918 : break;
# 1021 [ + + ]: 246432 : case RecvState::KEY:
# 1022 : 246432 : Assume(recv_state == RecvState::GARB_GARBTERM);
# 1023 : 246432 : break;
# 1024 [ + + ]: 246428 : case RecvState::GARB_GARBTERM:
# 1025 : 246428 : Assume(recv_state == RecvState::GARBAUTH);
# 1026 : 246428 : break;
# 1027 [ + + ]: 246428 : case RecvState::GARBAUTH:
# 1028 : 246428 : Assume(recv_state == RecvState::VERSION);
# 1029 : 246428 : break;
# 1030 [ + + ]: 246428 : case RecvState::VERSION:
# 1031 : 246428 : Assume(recv_state == RecvState::APP);
# 1032 : 246428 : break;
# 1033 [ + + ]: 5995 : case RecvState::APP:
# 1034 : 5995 : Assume(recv_state == RecvState::APP_READY);
# 1035 : 5995 : break;
# 1036 [ + + ]: 5995 : case RecvState::APP_READY:
# 1037 : 5995 : Assume(recv_state == RecvState::APP);
# 1038 : 5995 : break;
# 1039 [ - + ]: 0 : case RecvState::V1:
# 1040 : 0 : Assume(false); // V1 state cannot be left
# 1041 : 0 : break;
# 1042 : 1139624 : }
# 1043 : : // Change state.
# 1044 : 1139624 : m_recv_state = recv_state;
# 1045 : 1139624 : }
# 1046 : :
# 1047 : : void V2Transport::SetSendState(SendState send_state) noexcept
# 1048 : 388350 : {
# 1049 : 388350 : AssertLockHeld(m_send_mutex);
# 1050 : : // Enforce allowed state transitions.
# 1051 [ - + ]: 388350 : switch (m_send_state) {
# 1052 [ + + ]: 141918 : case SendState::MAYBE_V1:
# 1053 [ + + ][ + - ]: 141918 : Assume(send_state == SendState::V1 || send_state == SendState::AWAITING_KEY);
# 1054 : 141918 : break;
# 1055 [ + + ]: 246432 : case SendState::AWAITING_KEY:
# 1056 : 246432 : Assume(send_state == SendState::READY);
# 1057 : 246432 : break;
# 1058 [ - + ]: 0 : case SendState::READY:
# 1059 [ - + ]: 0 : case SendState::V1:
# 1060 : 0 : Assume(false); // Final states
# 1061 : 0 : break;
# 1062 : 388350 : }
# 1063 : : // Change state.
# 1064 : 388350 : m_send_state = send_state;
# 1065 : 388350 : }
# 1066 : :
# 1067 : : bool V2Transport::ReceivedMessageComplete() const noexcept
# 1068 : 563892 : {
# 1069 : 563892 : AssertLockNotHeld(m_recv_mutex);
# 1070 : 563892 : LOCK(m_recv_mutex);
# 1071 [ + + ]: 563892 : if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedMessageComplete();
# 1072 : :
# 1073 : 476221 : return m_recv_state == RecvState::APP_READY;
# 1074 : 563892 : }
# 1075 : :
# 1076 : : void V2Transport::ProcessReceivedMaybeV1Bytes() noexcept
# 1077 : 151654 : {
# 1078 : 151654 : AssertLockHeld(m_recv_mutex);
# 1079 : 151654 : AssertLockNotHeld(m_send_mutex);
# 1080 : 151654 : Assume(m_recv_state == RecvState::KEY_MAYBE_V1);
# 1081 : : // We still have to determine if this is a v1 or v2 connection. The bytes being received could
# 1082 : : // be the beginning of either a v1 packet (network magic + "version\x00"), or of a v2 public
# 1083 : : // key. BIP324 specifies that a mismatch with this 12-byte string should trigger sending of the
# 1084 : : // key.
# 1085 : 151654 : std::array<uint8_t, V1_PREFIX_LEN> v1_prefix = {0, 0, 0, 0, 'v', 'e', 'r', 's', 'i', 'o', 'n', 0};
# 1086 : 151654 : std::copy(std::begin(Params().MessageStart()), std::end(Params().MessageStart()), v1_prefix.begin());
# 1087 : 151654 : Assume(m_recv_buffer.size() <= v1_prefix.size());
# 1088 [ + + ]: 151654 : if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), v1_prefix.begin())) {
# 1089 : : // Mismatch with v1 prefix, so we can assume a v2 connection.
# 1090 : 123229 : SetReceiveState(RecvState::KEY); // Convert to KEY state, leaving received bytes around.
# 1091 : : // Transition the sender to AWAITING_KEY state (if not already).
# 1092 : 123229 : LOCK(m_send_mutex);
# 1093 : 123229 : SetSendState(SendState::AWAITING_KEY);
# 1094 [ + + ]: 123229 : } else if (m_recv_buffer.size() == v1_prefix.size()) {
# 1095 : : // Full match with the v1 prefix, so fall back to v1 behavior.
# 1096 : 18689 : LOCK(m_send_mutex);
# 1097 : 18689 : Span<const uint8_t> feedback{m_recv_buffer};
# 1098 : : // Feed already received bytes to v1 transport. It should always accept these, because it's
# 1099 : : // less than the size of a v1 header, and these are the first bytes fed to m_v1_fallback.
# 1100 : 18689 : bool ret = m_v1_fallback.ReceivedBytes(feedback);
# 1101 : 18689 : Assume(feedback.empty());
# 1102 : 18689 : Assume(ret);
# 1103 : 18689 : SetReceiveState(RecvState::V1);
# 1104 : 18689 : SetSendState(SendState::V1);
# 1105 : : // Reset v2 transport buffers to save memory.
# 1106 : 18689 : m_recv_buffer = {};
# 1107 : 18689 : m_send_buffer = {};
# 1108 : 18689 : } else {
# 1109 : : // We have not received enough to distinguish v1 from v2 yet. Wait until more bytes come.
# 1110 : 9736 : }
# 1111 : 151654 : }
# 1112 : :
# 1113 : : bool V2Transport::ProcessReceivedKeyBytes() noexcept
# 1114 : 310631 : {
# 1115 : 310631 : AssertLockHeld(m_recv_mutex);
# 1116 : 310631 : AssertLockNotHeld(m_send_mutex);
# 1117 : 310631 : Assume(m_recv_state == RecvState::KEY);
# 1118 : 310631 : Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());
# 1119 : :
# 1120 : : // As a special exception, if bytes 4-16 of the key on a responder connection match the
# 1121 : : // corresponding bytes of a V1 version message, but bytes 0-4 don't match the network magic
# 1122 : : // (if they did, we'd have switched to V1 state already), assume this is a peer from
# 1123 : : // another network, and disconnect them. They will almost certainly disconnect us too when
# 1124 : : // they receive our uniformly random key and garbage, but detecting this case specially
# 1125 : : // means we can log it.
# 1126 : 310631 : static constexpr std::array<uint8_t, 12> MATCH = {'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 0, 0, 0, 0};
# 1127 : 310631 : static constexpr size_t OFFSET = sizeof(CMessageHeader::MessageStartChars);
# 1128 [ + + ][ + + ]: 310631 : if (!m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
# 1129 [ + + ]: 164985 : if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
# 1130 [ + - ]: 2 : LogPrint(BCLog::NET, "V2 transport error: V1 peer with wrong MessageStart %s\n",
# 1131 : 2 : HexStr(Span(m_recv_buffer).first(OFFSET)));
# 1132 : 2 : return false;
# 1133 : 2 : }
# 1134 : 164985 : }
# 1135 : :
# 1136 [ + + ]: 310629 : if (m_recv_buffer.size() == EllSwiftPubKey::size()) {
# 1137 : : // Other side's key has been fully received, and can now be Diffie-Hellman combined with
# 1138 : : // our key to initialize the encryption ciphers.
# 1139 : :
# 1140 : : // Initialize the ciphers.
# 1141 : 246432 : EllSwiftPubKey ellswift(MakeByteSpan(m_recv_buffer));
# 1142 : 246432 : LOCK(m_send_mutex);
# 1143 : 246432 : m_cipher.Initialize(ellswift, m_initiating);
# 1144 : :
# 1145 : : // Switch receiver state to GARB_GARBTERM.
# 1146 : 246432 : SetReceiveState(RecvState::GARB_GARBTERM);
# 1147 : 246432 : m_recv_buffer.clear();
# 1148 : :
# 1149 : : // Switch sender state to READY.
# 1150 : 246432 : SetSendState(SendState::READY);
# 1151 : :
# 1152 : : // Append the garbage terminator to the send buffer.
# 1153 : 246432 : size_t garbage_len = m_send_buffer.size() - EllSwiftPubKey::size();
# 1154 : 246432 : m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
# 1155 : 246432 : std::copy(m_cipher.GetSendGarbageTerminator().begin(),
# 1156 : 246432 : m_cipher.GetSendGarbageTerminator().end(),
# 1157 : 246432 : MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN).begin());
# 1158 : :
# 1159 : : // Construct garbage authentication packet in the send buffer (using the garbage data which
# 1160 : : // is still there).
# 1161 : 246432 : m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::EXPANSION);
# 1162 : 246432 : m_cipher.Encrypt(
# 1163 : 246432 : /*contents=*/{},
# 1164 : 246432 : /*aad=*/MakeByteSpan(m_send_buffer).subspan(EllSwiftPubKey::size(), garbage_len),
# 1165 : 246432 : /*ignore=*/false,
# 1166 : 246432 : /*output=*/MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::EXPANSION));
# 1167 : :
# 1168 : : // Construct version packet in the send buffer.
# 1169 : 246432 : m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::EXPANSION + VERSION_CONTENTS.size());
# 1170 : 246432 : m_cipher.Encrypt(
# 1171 : 246432 : /*contents=*/VERSION_CONTENTS,
# 1172 : 246432 : /*aad=*/{},
# 1173 : 246432 : /*ignore=*/false,
# 1174 : 246432 : /*output=*/MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::EXPANSION + VERSION_CONTENTS.size()));
# 1175 : 246432 : } else {
# 1176 : : // We still have to receive more key bytes.
# 1177 : 64197 : }
# 1178 : 310629 : return true;
# 1179 : 310631 : }
# 1180 : :
# 1181 : : bool V2Transport::ProcessReceivedGarbageBytes() noexcept
# 1182 : 4607695 : {
# 1183 : 4607695 : AssertLockHeld(m_recv_mutex);
# 1184 : 4607695 : Assume(m_recv_state == RecvState::GARB_GARBTERM);
# 1185 : 4607695 : Assume(m_recv_buffer.size() <= MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
# 1186 [ + + ]: 4607695 : if (m_recv_buffer.size() >= BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
# 1187 [ + + ]: 911215 : if (MakeByteSpan(m_recv_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN) == m_cipher.GetReceiveGarbageTerminator()) {
# 1188 : : // Garbage terminator received. Switch to receiving garbage authentication packet.
# 1189 : 246428 : m_recv_garbage = std::move(m_recv_buffer);
# 1190 : 246428 : m_recv_garbage.resize(m_recv_garbage.size() - BIP324Cipher::GARBAGE_TERMINATOR_LEN);
# 1191 : 246428 : m_recv_buffer.clear();
# 1192 : 246428 : SetReceiveState(RecvState::GARBAUTH);
# 1193 [ + + ]: 664787 : } 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 [ + - ]: 4 : LogPrint(BCLog::NET, "V2 transport error: missing garbage terminator, peer=%d\n", m_nodeid);
# 1197 : 4 : return false;
# 1198 : 664783 : } else {
# 1199 : : // We still need to receive more garbage and/or garbage terminator bytes.
# 1200 : 664783 : }
# 1201 : 3696480 : } else {
# 1202 : : // We have less than GARBAGE_TERMINATOR_LEN (16) bytes, so we certainly need to receive
# 1203 : : // more first.
# 1204 : 3696480 : }
# 1205 : 4607691 : return true;
# 1206 : 4607695 : }
# 1207 : :
# 1208 : : bool V2Transport::ProcessReceivedPacketBytes() noexcept
# 1209 : 1210688 : {
# 1210 : 1210688 : AssertLockHeld(m_recv_mutex);
# 1211 [ + - ][ + + ]: 1210688 : Assume(m_recv_state == RecvState::GARBAUTH || m_recv_state == RecvState::VERSION ||
# [ + + ]
# 1212 : 1210688 : m_recv_state == RecvState::APP);
# 1213 : :
# 1214 : : // The maximum permitted contents length for a packet, consisting of:
# 1215 : : // - 0x00 byte: indicating long message type encoding
# 1216 : : // - 12 bytes of message type
# 1217 : : // - payload
# 1218 : 1210688 : static constexpr size_t MAX_CONTENTS_LEN =
# 1219 : 1210688 : 1 + CMessageHeader::COMMAND_SIZE +
# 1220 : 1210688 : std::min<size_t>(MAX_SIZE, MAX_PROTOCOL_MESSAGE_LENGTH);
# 1221 : :
# 1222 [ + + ]: 1210688 : if (m_recv_buffer.size() == BIP324Cipher::LENGTH_LEN) {
# 1223 : : // Length descriptor received.
# 1224 : 601073 : m_recv_len = m_cipher.DecryptLength(MakeByteSpan(m_recv_buffer));
# 1225 [ + + ]: 601073 : if (m_recv_len > MAX_CONTENTS_LEN) {
# 1226 [ + - ]: 20 : LogPrint(BCLog::NET, "V2 transport error: packet too large (%u bytes), peer=%d\n", m_recv_len, m_nodeid);
# 1227 : 20 : return false;
# 1228 : 20 : }
# 1229 [ + + ][ + + ]: 609615 : } else if (m_recv_buffer.size() > BIP324Cipher::LENGTH_LEN && m_recv_buffer.size() == m_recv_len + BIP324Cipher::EXPANSION) {
# 1230 : : // Ciphertext received, decrypt it into m_recv_decode_buffer.
# 1231 : : // Note that it is impossible to reach this branch without hitting the branch above first,
# 1232 : : // as GetMaxBytesToProcess only allows up to LENGTH_LEN into the buffer before that point.
# 1233 : 601053 : m_recv_decode_buffer.resize(m_recv_len);
# 1234 : 601053 : bool ignore{false};
# 1235 : 601053 : Span<const std::byte> aad;
# 1236 [ + + ]: 601053 : if (m_recv_state == RecvState::GARBAUTH) aad = MakeByteSpan(m_recv_garbage);
# 1237 : 601053 : bool ret = m_cipher.Decrypt(
# 1238 : 601053 : /*input=*/MakeByteSpan(m_recv_buffer).subspan(BIP324Cipher::LENGTH_LEN),
# 1239 : 601053 : /*aad=*/aad,
# 1240 : 601053 : /*ignore=*/ignore,
# 1241 : 601053 : /*contents=*/MakeWritableByteSpan(m_recv_decode_buffer));
# 1242 [ + + ]: 601053 : if (!ret) {
# 1243 [ + - ]: 20 : LogPrint(BCLog::NET, "V2 transport error: packet decryption failure (%u bytes), peer=%d\n", m_recv_len, m_nodeid);
# 1244 : 20 : return false;
# 1245 : 20 : }
# 1246 : : // Feed the last 4 bytes of the Poly1305 authentication tag (and its timing) into our RNG.
# 1247 : 601033 : RandAddEvent(ReadLE32(m_recv_buffer.data() + m_recv_buffer.size() - 4));
# 1248 : :
# 1249 : : // At this point we have a valid packet decrypted into m_recv_decode_buffer. Depending on
# 1250 : : // the current state, decide what to do with it.
# 1251 : 601033 : switch (m_recv_state) {
# 1252 [ + + ]: 246428 : case RecvState::GARBAUTH:
# 1253 : : // Ignore flag does not matter for garbage authentication. Any valid packet functions
# 1254 : : // as authentication. Receive and process the version packet next.
# 1255 : 246428 : SetReceiveState(RecvState::VERSION);
# 1256 : 246428 : m_recv_garbage = {};
# 1257 : 246428 : break;
# 1258 [ + + ]: 246918 : case RecvState::VERSION:
# 1259 [ + + ]: 246918 : if (!ignore) {
# 1260 : : // Version message received; transition to application phase. The contents is
# 1261 : : // ignored, but can be used for future extensions.
# 1262 : 246428 : SetReceiveState(RecvState::APP);
# 1263 : 246428 : }
# 1264 : 246918 : break;
# 1265 [ + + ]: 107687 : case RecvState::APP:
# 1266 [ + + ]: 107687 : if (!ignore) {
# 1267 : : // Application message decrypted correctly. It can be extracted using GetMessage().
# 1268 : 5995 : SetReceiveState(RecvState::APP_READY);
# 1269 : 5995 : }
# 1270 : 107687 : break;
# 1271 [ - + ]: 0 : default:
# 1272 : : // Any other state is invalid (this function should not have been called).
# 1273 : 0 : Assume(false);
# 1274 : 601033 : }
# 1275 : : // Wipe the receive buffer where the next packet will be received into.
# 1276 : 601033 : m_recv_buffer = {};
# 1277 : : // In all but APP_READY state, we can wipe the decoded contents.
# 1278 [ + + ]: 601033 : if (m_recv_state != RecvState::APP_READY) m_recv_decode_buffer = {};
# 1279 : 601033 : } else {
# 1280 : : // We either have less than 3 bytes, so we don't know the packet's length yet, or more
# 1281 : : // than 3 bytes but less than the packet's full ciphertext. Wait until those arrive.
# 1282 : 8562 : }
# 1283 : 1210648 : return true;
# 1284 : 1210688 : }
# 1285 : :
# 1286 : : size_t V2Transport::GetMaxBytesToProcess() noexcept
# 1287 : 6281322 : {
# 1288 : 6281322 : AssertLockHeld(m_recv_mutex);
# 1289 [ - + ]: 6281322 : switch (m_recv_state) {
# 1290 [ + + ]: 151654 : case RecvState::KEY_MAYBE_V1:
# 1291 : : // During the KEY_MAYBE_V1 state we do not allow more than the length of v1 prefix into the
# 1292 : : // receive buffer.
# 1293 : 151654 : Assume(m_recv_buffer.size() <= V1_PREFIX_LEN);
# 1294 : : // As long as we're not sure if this is a v1 or v2 connection, don't receive more than what
# 1295 : : // is strictly necessary to distinguish the two (12 bytes). If we permitted more than
# 1296 : : // the v1 header size (24 bytes), we may not be able to feed the already-received bytes
# 1297 : : // back into the m_v1_fallback V1 transport.
# 1298 : 151654 : return V1_PREFIX_LEN - m_recv_buffer.size();
# 1299 [ + + ]: 310631 : case RecvState::KEY:
# 1300 : : // During the KEY state, we only allow the 64-byte key into the receive buffer.
# 1301 : 310631 : Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());
# 1302 : : // As long as we have not received the other side's public key, don't receive more than
# 1303 : : // that (64 bytes), as garbage follows, and locating the garbage terminator requires the
# 1304 : : // key exchange first.
# 1305 : 310631 : return EllSwiftPubKey::size() - m_recv_buffer.size();
# 1306 [ + + ]: 4607695 : case RecvState::GARB_GARBTERM:
# 1307 : : // Process garbage bytes one by one (because terminator may appear anywhere).
# 1308 : 4607695 : return 1;
# 1309 [ + + ]: 494902 : case RecvState::GARBAUTH:
# 1310 [ + + ]: 991451 : case RecvState::VERSION:
# 1311 [ + + ]: 1210688 : case RecvState::APP:
# 1312 : : // These three states all involve decoding a packet. Process the length descriptor first,
# 1313 : : // so that we know where the current packet ends (and we don't process bytes from the next
# 1314 : : // packet or decoy yet). Then, process the ciphertext bytes of the current packet.
# 1315 [ + + ]: 1210688 : if (m_recv_buffer.size() < BIP324Cipher::LENGTH_LEN) {
# 1316 : 601544 : return BIP324Cipher::LENGTH_LEN - m_recv_buffer.size();
# 1317 : 609144 : } else {
# 1318 : : // Note that BIP324Cipher::EXPANSION is the total difference between contents size
# 1319 : : // and encoded packet size, which includes the 3 bytes due to the packet length.
# 1320 : : // When transitioning from receiving the packet length to receiving its ciphertext,
# 1321 : : // the encrypted packet length is left in the receive buffer.
# 1322 : 609144 : return BIP324Cipher::EXPANSION + m_recv_len - m_recv_buffer.size();
# 1323 : 609144 : }
# 1324 [ + + ]: 654 : case RecvState::APP_READY:
# 1325 : : // No bytes can be processed until GetMessage() is called.
# 1326 : 654 : return 0;
# 1327 [ - + ]: 0 : case RecvState::V1:
# 1328 : : // Not allowed (must be dealt with by the caller).
# 1329 : 0 : Assume(false);
# 1330 : 0 : return 0;
# 1331 : 6281322 : }
# 1332 : 0 : Assume(false); // unreachable
# 1333 : 0 : return 0;
# 1334 : 6281322 : }
# 1335 : :
# 1336 : : bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
# 1337 : 562456 : {
# 1338 : 562456 : AssertLockNotHeld(m_recv_mutex);
# 1339 : : /** How many bytes to allocate in the receive buffer at most above what is received so far. */
# 1340 : 562456 : static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024;
# 1341 : :
# 1342 : 562456 : LOCK(m_recv_mutex);
# 1343 [ + + ]: 562456 : if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes(msg_bytes);
# 1344 : :
# 1345 : : // Process the provided bytes in msg_bytes in a loop. In each iteration a nonzero number of
# 1346 : : // bytes (decided by GetMaxBytesToProcess) are taken from the beginning om msg_bytes, and
# 1347 : : // appended to m_recv_buffer. Then, depending on the receiver state, one of the
# 1348 : : // ProcessReceived*Bytes functions is called to process the bytes in that buffer.
# 1349 [ + + ]: 6755409 : while (!msg_bytes.empty()) {
# 1350 : : // Decide how many bytes to copy from msg_bytes to m_recv_buffer.
# 1351 : 6281322 : size_t max_read = GetMaxBytesToProcess();
# 1352 : :
# 1353 : : // Reserve space in the buffer if there is not enough.
# 1354 [ + + ]: 6281322 : if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {
# 1355 [ - + ]: 763888 : switch (m_recv_state) {
# 1356 [ + + ]: 141918 : case RecvState::KEY_MAYBE_V1:
# 1357 [ + + ]: 265123 : case RecvState::KEY:
# 1358 [ - + ]: 265123 : case RecvState::GARB_GARBTERM:
# 1359 : : // During the initial states (key/garbage), allocate once to fit the maximum (4111
# 1360 : : // bytes).
# 1361 : 265123 : m_recv_buffer.reserve(MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
# 1362 : 265123 : break;
# 1363 [ + + ]: 492856 : case RecvState::GARBAUTH:
# 1364 [ + + ]: 492918 : case RecvState::VERSION:
# 1365 [ + + ]: 498765 : case RecvState::APP: {
# 1366 : : // During states where a packet is being received, as much as is expected but never
# 1367 : : // more than MAX_RESERVE_AHEAD bytes in addition to what is received so far.
# 1368 : : // This means attackers that want to cause us to waste allocated memory are limited
# 1369 : : // to MAX_RESERVE_AHEAD above the largest allowed message contents size, and to
# 1370 : : // MAX_RESERVE_AHEAD more than they've actually sent us.
# 1371 : 498765 : size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);
# 1372 : 498765 : m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);
# 1373 : 498765 : break;
# 1374 : 492918 : }
# 1375 [ - + ]: 0 : case RecvState::APP_READY:
# 1376 : : // The buffer is empty in this state.
# 1377 : 0 : Assume(m_recv_buffer.empty());
# 1378 : 0 : break;
# 1379 [ - + ]: 0 : case RecvState::V1:
# 1380 : : // Should have bailed out above.
# 1381 : 0 : Assume(false);
# 1382 : 0 : break;
# 1383 : 763888 : }
# 1384 : 763888 : }
# 1385 : :
# 1386 : : // Can't read more than provided input.
# 1387 : 6281322 : max_read = std::min(msg_bytes.size(), max_read);
# 1388 : : // Copy data to buffer.
# 1389 : 6281322 : m_recv_buffer.insert(m_recv_buffer.end(), UCharCast(msg_bytes.data()), UCharCast(msg_bytes.data() + max_read));
# 1390 : 6281322 : msg_bytes = msg_bytes.subspan(max_read);
# 1391 : :
# 1392 : : // Process data in the buffer.
# 1393 [ - + ]: 6281322 : switch (m_recv_state) {
# 1394 [ + + ]: 151654 : case RecvState::KEY_MAYBE_V1:
# 1395 : 151654 : ProcessReceivedMaybeV1Bytes();
# 1396 [ + + ]: 151654 : if (m_recv_state == RecvState::V1) return true;
# 1397 : 132965 : break;
# 1398 : :
# 1399 [ + + ]: 310631 : case RecvState::KEY:
# 1400 [ + + ]: 310631 : if (!ProcessReceivedKeyBytes()) return false;
# 1401 : 310629 : break;
# 1402 : :
# 1403 [ + + ]: 4607695 : case RecvState::GARB_GARBTERM:
# 1404 [ + + ]: 4607695 : if (!ProcessReceivedGarbageBytes()) return false;
# 1405 : 4607691 : break;
# 1406 : :
# 1407 [ + + ]: 4607691 : case RecvState::GARBAUTH:
# 1408 [ + + ]: 991451 : case RecvState::VERSION:
# 1409 [ + + ]: 1210688 : case RecvState::APP:
# 1410 [ + + ]: 1210688 : if (!ProcessReceivedPacketBytes()) return false;
# 1411 : 1210648 : break;
# 1412 : :
# 1413 [ + + ]: 1210648 : case RecvState::APP_READY:
# 1414 : 654 : return true;
# 1415 : :
# 1416 [ - + ]: 0 : case RecvState::V1:
# 1417 : : // We should have bailed out before.
# 1418 : 0 : Assume(false);
# 1419 : 0 : break;
# 1420 : 6281322 : }
# 1421 : : // Make sure we have made progress before continuing.
# 1422 : 6261933 : Assume(max_read > 0);
# 1423 : 6261933 : }
# 1424 : :
# 1425 : 474087 : return true;
# 1426 : 493476 : }
# 1427 : :
# 1428 : : std::optional<std::string> V2Transport::GetMessageType(Span<const uint8_t>& contents) noexcept
# 1429 : 5995 : {
# 1430 [ - + ]: 5995 : if (contents.size() == 0) return std::nullopt; // Empty contents
# 1431 : 5995 : uint8_t first_byte = contents[0];
# 1432 : 5995 : contents = contents.subspan(1); // Strip first byte.
# 1433 : :
# 1434 [ + + ]: 5995 : if (first_byte != 0) {
# 1435 : : // Short (1 byte) encoding.
# 1436 [ + + ]: 361 : if (first_byte < std::size(V2_MESSAGE_IDS)) {
# 1437 : : // Valid short message id.
# 1438 : 359 : return V2_MESSAGE_IDS[first_byte];
# 1439 : 359 : } else {
# 1440 : : // Unknown short message id.
# 1441 : 2 : return std::nullopt;
# 1442 : 2 : }
# 1443 : 361 : }
# 1444 : :
# 1445 [ + + ]: 5634 : if (contents.size() < CMessageHeader::COMMAND_SIZE) {
# 1446 : 20 : return std::nullopt; // Long encoding needs 12 message type bytes.
# 1447 : 20 : }
# 1448 : :
# 1449 : 5614 : size_t msg_type_len{0};
# 1450 [ + - ][ + + ]: 44812 : while (msg_type_len < CMessageHeader::COMMAND_SIZE && contents[msg_type_len] != 0) {
# 1451 : : // Verify that message type bytes before the first 0x00 are in range.
# 1452 [ - + ][ - + ]: 39198 : if (contents[msg_type_len] < ' ' || contents[msg_type_len] > 0x7F) {
# 1453 : 0 : return {};
# 1454 : 0 : }
# 1455 : 39198 : ++msg_type_len;
# 1456 : 39198 : }
# 1457 : 5614 : std::string ret{reinterpret_cast<const char*>(contents.data()), msg_type_len};
# 1458 [ + + ]: 33584 : while (msg_type_len < CMessageHeader::COMMAND_SIZE) {
# 1459 : : // Verify that message type bytes after the first 0x00 are also 0x00.
# 1460 [ + + ]: 28070 : if (contents[msg_type_len] != 0) return {};
# 1461 : 27970 : ++msg_type_len;
# 1462 : 27970 : }
# 1463 : : // Strip message type bytes of contents.
# 1464 : 5514 : contents = contents.subspan(CMessageHeader::COMMAND_SIZE);
# 1465 : 5514 : return {std::move(ret)};
# 1466 : 5614 : }
# 1467 : :
# 1468 : : CNetMessage V2Transport::GetReceivedMessage(std::chrono::microseconds time, bool& reject_message) noexcept
# 1469 : 26409 : {
# 1470 : 26409 : AssertLockNotHeld(m_recv_mutex);
# 1471 : 26409 : LOCK(m_recv_mutex);
# 1472 [ + + ]: 26409 : if (m_recv_state == RecvState::V1) return m_v1_fallback.GetReceivedMessage(time, reject_message);
# 1473 : :
# 1474 : 5995 : Assume(m_recv_state == RecvState::APP_READY);
# 1475 : 5995 : Span<const uint8_t> contents{m_recv_decode_buffer};
# 1476 : 5995 : auto msg_type = GetMessageType(contents);
# 1477 : 5995 : CDataStream ret(m_recv_type, m_recv_version);
# 1478 : 5995 : CNetMessage msg{std::move(ret)};
# 1479 : : // Note that BIP324Cipher::EXPANSION also includes the length descriptor size.
# 1480 : 5995 : msg.m_raw_message_size = m_recv_decode_buffer.size() + BIP324Cipher::EXPANSION;
# 1481 [ + + ]: 5995 : if (msg_type) {
# 1482 : 5873 : reject_message = false;
# 1483 : 5873 : msg.m_type = std::move(*msg_type);
# 1484 : 5873 : msg.m_time = time;
# 1485 : 5873 : msg.m_message_size = contents.size();
# 1486 : 5873 : msg.m_recv.resize(contents.size());
# 1487 : 5873 : std::copy(contents.begin(), contents.end(), UCharCast(msg.m_recv.data()));
# 1488 : 5873 : } else {
# 1489 [ + - ]: 122 : LogPrint(BCLog::NET, "V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(), m_nodeid);
# 1490 : 122 : reject_message = true;
# 1491 : 122 : }
# 1492 : 5995 : m_recv_decode_buffer = {};
# 1493 : 5995 : SetReceiveState(RecvState::APP);
# 1494 : :
# 1495 : 5995 : return msg;
# 1496 : 26409 : }
# 1497 : :
# 1498 : : bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
# 1499 : 940289 : {
# 1500 : 940289 : AssertLockNotHeld(m_send_mutex);
# 1501 : 940289 : LOCK(m_send_mutex);
# 1502 [ + + ]: 940289 : if (m_send_state == SendState::V1) return m_v1_fallback.SetMessageToSend(msg);
# 1503 : : // We only allow adding a new message to be sent when in the READY state (so the packet cipher
# 1504 : : // is available) and the send buffer is empty. This limits the number of messages in the send
# 1505 : : // buffer to just one, and leaves the responsibility for queueing them up to the caller.
# 1506 [ + + ][ + + ]: 890310 : if (!(m_send_state == SendState::READY && m_send_buffer.empty())) return false;
# 1507 : : // Construct contents (encoding message type + payload).
# 1508 : 5593 : std::vector<uint8_t> contents;
# 1509 : 5593 : auto short_message_id = V2_MESSAGE_MAP(msg.m_type);
# 1510 [ + + ]: 5593 : if (short_message_id) {
# 1511 : 99 : contents.resize(1 + msg.data.size());
# 1512 : 99 : contents[0] = *short_message_id;
# 1513 : 99 : std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1);
# 1514 : 5494 : } else {
# 1515 : : // Initialize with zeroes, and then write the message type string starting at offset 1.
# 1516 : : // This means contents[0] and the unused positions in contents[1..13] remain 0x00.
# 1517 : 5494 : contents.resize(1 + CMessageHeader::COMMAND_SIZE + msg.data.size(), 0);
# 1518 : 5494 : std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
# 1519 : 5494 : std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1 + CMessageHeader::COMMAND_SIZE);
# 1520 : 5494 : }
# 1521 : : // Construct ciphertext in send buffer.
# 1522 : 5593 : m_send_buffer.resize(contents.size() + BIP324Cipher::EXPANSION);
# 1523 : 5593 : m_cipher.Encrypt(MakeByteSpan(contents), {}, false, MakeWritableByteSpan(m_send_buffer));
# 1524 : 5593 : m_send_type = msg.m_type;
# 1525 : : // Release memory
# 1526 : 5593 : msg.data = {};
# 1527 : 5593 : return true;
# 1528 : 890310 : }
# 1529 : :
# 1530 : : Transport::BytesToSend V2Transport::GetBytesToSend(bool have_next_message) const noexcept
# 1531 : 8952644 : {
# 1532 : 8952644 : AssertLockNotHeld(m_send_mutex);
# 1533 : 8952644 : LOCK(m_send_mutex);
# 1534 [ + + ]: 8952644 : if (m_send_state == SendState::V1) return m_v1_fallback.GetBytesToSend(have_next_message);
# 1535 : :
# 1536 : : // We do not send anything in MAYBE_V1 state (as we don't know if the peer is v1 or v2),
# 1537 : : // despite there being data in the send buffer in that state.
# 1538 [ + + ]: 8254280 : if (m_send_state == SendState::MAYBE_V1) return {{}, false, m_send_type};
# 1539 : 5846456 : Assume(m_send_pos <= m_send_buffer.size());
# 1540 : 5846456 : return {
# 1541 : 5846456 : Span{m_send_buffer}.subspan(m_send_pos),
# 1542 : : // We only have more to send after the current m_send_buffer if there is a (next)
# 1543 : : // message to be sent, and we're capable of sending packets. */
# 1544 [ + + ][ + + ]: 5846456 : have_next_message && m_send_state == SendState::READY,
# 1545 : 5846456 : m_send_type
# 1546 : 5846456 : };
# 1547 : 8254280 : }
# 1548 : :
# 1549 : : void V2Transport::MarkBytesSent(size_t bytes_sent) noexcept
# 1550 : 565293 : {
# 1551 : 565293 : AssertLockNotHeld(m_send_mutex);
# 1552 : 565293 : LOCK(m_send_mutex);
# 1553 [ + + ]: 565293 : if (m_send_state == SendState::V1) return m_v1_fallback.MarkBytesSent(bytes_sent);
# 1554 : :
# 1555 : 518160 : m_send_pos += bytes_sent;
# 1556 : 518160 : Assume(m_send_pos <= m_send_buffer.size());
# 1557 : : // Only wipe the buffer when everything is sent in the READY state. In the AWAITING_KEY state
# 1558 : : // we still need the garbage that's in the send buffer to construct the garbage authentication
# 1559 : : // packet.
# 1560 [ + + ][ + + ]: 518160 : if (m_send_state == SendState::READY && m_send_pos == m_send_buffer.size()) {
# 1561 : 252023 : m_send_pos = 0;
# 1562 : 252023 : m_send_buffer = {};
# 1563 : 252023 : }
# 1564 : 518160 : }
# 1565 : :
# 1566 : : size_t V2Transport::GetSendMemoryUsage() const noexcept
# 1567 : 0 : {
# 1568 : 0 : AssertLockNotHeld(m_send_mutex);
# 1569 : 0 : LOCK(m_send_mutex);
# 1570 [ # # ]: 0 : if (m_send_state == SendState::V1) return m_v1_fallback.GetSendMemoryUsage();
# 1571 : :
# 1572 : 0 : return sizeof(m_send_buffer) + memusage::DynamicUsage(m_send_buffer);
# 1573 : 0 : }
# 1574 : :
# 1575 : : std::pair<size_t, bool> CConnman::SocketSendData(CNode& node) const
# 1576 : 130955 : {
# 1577 : 130955 : auto it = node.vSendMsg.begin();
# 1578 : 130955 : size_t nSentSize = 0;
# 1579 : 130955 : bool data_left{false}; //!< second return value (whether unsent data remains)
# 1580 : 130955 : std::optional<bool> expected_more;
# 1581 : :
# 1582 : 388319 : while (true) {
# 1583 [ + + ]: 388319 : if (it != node.vSendMsg.end()) {
# 1584 : : // If possible, move one message from the send queue to the transport. This fails when
# 1585 : : // there is an existing message still being sent, or (for v2 transports) when the
# 1586 : : // handshake has not yet completed.
# 1587 : 130776 : size_t memusage = it->GetMemoryUsage();
# 1588 [ + + ]: 130776 : if (node.m_transport->SetMessageToSend(*it)) {
# 1589 : : // Update memory usage of send buffer (as *it will be deleted).
# 1590 : 130733 : node.m_send_memusage -= memusage;
# 1591 : 130733 : ++it;
# 1592 : 130733 : }
# 1593 : 130776 : }
# 1594 : 388319 : const auto& [data, more, msg_type] = node.m_transport->GetBytesToSend(it != node.vSendMsg.end());
# 1595 : : // We rely on the 'more' value returned by GetBytesToSend to correctly predict whether more
# 1596 : : // bytes are still to be sent, to correctly set the MSG_MORE flag. As a sanity check,
# 1597 : : // verify that the previously returned 'more' was correct.
# 1598 [ + + ]: 388319 : if (expected_more.has_value()) Assume(!data.empty() == *expected_more);
# 1599 : 388319 : expected_more = more;
# 1600 : 388319 : data_left = !data.empty(); // will be overwritten on next loop if all of data gets sent
# 1601 : 388319 : int nBytes = 0;
# 1602 [ + + ]: 388319 : if (!data.empty()) {
# 1603 : 257652 : LOCK(node.m_sock_mutex);
# 1604 : : // There is no socket in case we've already disconnected, or in test cases without
# 1605 : : // real connections. In these cases, we bail out immediately and just leave things
# 1606 : : // in the send queue and transport.
# 1607 [ + + ]: 257652 : if (!node.m_sock) {
# 1608 : 42 : break;
# 1609 : 42 : }
# 1610 : 257610 : int flags = MSG_NOSIGNAL | MSG_DONTWAIT;
# 1611 : : #ifdef MSG_MORE
# 1612 : : if (more) {
# 1613 : : flags |= MSG_MORE;
# 1614 : : }
# 1615 : : #endif
# 1616 : 257610 : nBytes = node.m_sock->Send(reinterpret_cast<const char*>(data.data()), data.size(), flags);
# 1617 : 257610 : }
# 1618 [ + + ]: 388277 : if (nBytes > 0) {
# 1619 : 257589 : node.m_last_send = GetTime<std::chrono::seconds>();
# 1620 : 257589 : node.nSendBytes += nBytes;
# 1621 : : // Notify transport that bytes have been processed.
# 1622 : 257589 : node.m_transport->MarkBytesSent(nBytes);
# 1623 : : // Update statistics per message type.
# 1624 : 257589 : node.AccountForSentBytes(msg_type, nBytes);
# 1625 : 257589 : nSentSize += nBytes;
# 1626 [ + + ]: 257589 : if ((size_t)nBytes != data.size()) {
# 1627 : : // could not send full message; stop sending more
# 1628 : 225 : break;
# 1629 : 225 : }
# 1630 : 257589 : } else {
# 1631 [ + + ]: 130688 : if (nBytes < 0) {
# 1632 : : // error
# 1633 : 21 : int nErr = WSAGetLastError();
# 1634 [ + - ][ + - ]: 21 : if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) {
# [ + - ][ + - ]
# 1635 [ + - ]: 21 : LogPrint(BCLog::NET, "socket send error for peer=%d: %s\n", node.GetId(), NetworkErrorString(nErr));
# 1636 : 21 : node.CloseSocketDisconnect();
# 1637 : 21 : }
# 1638 : 21 : }
# 1639 : 130688 : break;
# 1640 : 130688 : }
# 1641 : 388277 : }
# 1642 : :
# 1643 : 130955 : node.fPauseSend = node.m_send_memusage + node.m_transport->GetSendMemoryUsage() > nSendBufferMaxSize;
# 1644 : :
# 1645 [ + + ]: 130955 : if (it == node.vSendMsg.end()) {
# 1646 : 130914 : assert(node.m_send_memusage == 0);
# 1647 : 130914 : }
# 1648 : 130955 : node.vSendMsg.erase(node.vSendMsg.begin(), it);
# 1649 : 130955 : return {nSentSize, data_left};
# 1650 : 130955 : }
# 1651 : :
# 1652 : : /** Try to find a connection to evict when the node is full.
# 1653 : : * Extreme care must be taken to avoid opening the node to attacker
# 1654 : : * triggered network partitioning.
# 1655 : : * The strategy used here is to protect a small number of peers
# 1656 : : * for each of several distinct characteristics which are difficult
# 1657 : : * to forge. In order to partition a node the attacker must be
# 1658 : : * simultaneously better at all of them than honest peers.
# 1659 : : */
# 1660 : : bool CConnman::AttemptToEvictConnection()
# 1661 : 1 : {
# 1662 : 1 : std::vector<NodeEvictionCandidate> vEvictionCandidates;
# 1663 : 1 : {
# 1664 : :
# 1665 : 1 : LOCK(m_nodes_mutex);
# 1666 [ + + ]: 21 : for (const CNode* node : m_nodes) {
# 1667 [ - + ]: 21 : if (node->fDisconnect)
# 1668 : 0 : continue;
# 1669 : 21 : NodeEvictionCandidate candidate{
# 1670 : 21 : .id = node->GetId(),
# 1671 : 21 : .m_connected = node->m_connected,
# 1672 : 21 : .m_min_ping_time = node->m_min_ping_time,
# 1673 : 21 : .m_last_block_time = node->m_last_block_time,
# 1674 : 21 : .m_last_tx_time = node->m_last_tx_time,
# 1675 : 21 : .fRelevantServices = node->m_has_all_wanted_services,
# 1676 : 21 : .m_relay_txs = node->m_relays_txs.load(),
# 1677 : 21 : .fBloomFilter = node->m_bloom_filter_loaded.load(),
# 1678 : 21 : .nKeyedNetGroup = node->nKeyedNetGroup,
# 1679 : 21 : .prefer_evict = node->m_prefer_evict,
# 1680 : 21 : .m_is_local = node->addr.IsLocal(),
# 1681 : 21 : .m_network = node->ConnectedThroughNetwork(),
# 1682 : 21 : .m_noban = node->HasPermission(NetPermissionFlags::NoBan),
# 1683 : 21 : .m_conn_type = node->m_conn_type,
# 1684 : 21 : };
# 1685 : 21 : vEvictionCandidates.push_back(candidate);
# 1686 : 21 : }
# 1687 : 1 : }
# 1688 : 1 : const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
# 1689 [ - + ]: 1 : if (!node_id_to_evict) {
# 1690 : 0 : return false;
# 1691 : 0 : }
# 1692 : 1 : LOCK(m_nodes_mutex);
# 1693 [ + - ]: 5 : for (CNode* pnode : m_nodes) {
# 1694 [ + + ]: 5 : if (pnode->GetId() == *node_id_to_evict) {
# 1695 [ + - ]: 1 : LogPrint(BCLog::NET, "selected %s connection for eviction peer=%d; disconnecting\n", pnode->ConnectionTypeAsString(), pnode->GetId());
# 1696 : 1 : pnode->fDisconnect = true;
# 1697 : 1 : return true;
# 1698 : 1 : }
# 1699 : 5 : }
# 1700 : 0 : return false;
# 1701 : 1 : }
# 1702 : :
# 1703 : 707 : void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
# 1704 : 707 : struct sockaddr_storage sockaddr;
# 1705 : 707 : socklen_t len = sizeof(sockaddr);
# 1706 : 707 : auto sock = hListenSocket.sock->Accept((struct sockaddr*)&sockaddr, &len);
# 1707 : 707 : CAddress addr;
# 1708 : :
# 1709 [ - + ]: 707 : if (!sock) {
# 1710 : 0 : const int nErr = WSAGetLastError();
# 1711 [ # # ]: 0 : if (nErr != WSAEWOULDBLOCK) {
# 1712 : 0 : LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
# 1713 : 0 : }
# 1714 : 0 : return;
# 1715 : 0 : }
# 1716 : :
# 1717 [ - + ]: 707 : if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
# 1718 [ # # ]: 0 : LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n");
# 1719 : 707 : } else {
# 1720 : 707 : addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
# 1721 : 707 : }
# 1722 : :
# 1723 : 707 : const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock)), NODE_NONE};
# 1724 : :
# 1725 : 707 : NetPermissionFlags permission_flags = NetPermissionFlags::None;
# 1726 : 707 : hListenSocket.AddSocketPermissionFlags(permission_flags);
# 1727 : :
# 1728 : 707 : CreateNodeFromAcceptedSocket(std::move(sock), permission_flags, addr_bind, addr);
# 1729 : 707 : }
# 1730 : :
# 1731 : : void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
# 1732 : : NetPermissionFlags permission_flags,
# 1733 : : const CAddress& addr_bind,
# 1734 : : const CAddress& addr)
# 1735 : 707 : {
# 1736 : 707 : int nInbound = 0;
# 1737 : 707 : int nMaxInbound = nMaxConnections - m_max_outbound;
# 1738 : :
# 1739 : 707 : AddWhitelistPermissionFlags(permission_flags, addr);
# 1740 [ + + ]: 707 : if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::Implicit)) {
# 1741 : 5 : NetPermissions::ClearFlag(permission_flags, NetPermissionFlags::Implicit);
# 1742 [ + + ]: 5 : if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::ForceRelay);
# 1743 [ + + ]: 5 : if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Relay);
# 1744 : 5 : NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Mempool);
# 1745 : 5 : NetPermissions::AddFlag(permission_flags, NetPermissionFlags::NoBan);
# 1746 : 5 : }
# 1747 : :
# 1748 : 707 : {
# 1749 : 707 : LOCK(m_nodes_mutex);
# 1750 [ + + ]: 1491 : for (const CNode* pnode : m_nodes) {
# 1751 [ + + ]: 1491 : if (pnode->IsInboundConn()) nInbound++;
# 1752 : 1491 : }
# 1753 : 707 : }
# 1754 : :
# 1755 [ - + ]: 707 : if (!fNetworkActive) {
# 1756 [ # # ]: 0 : LogPrint(BCLog::NET, "connection from %s dropped: not accepting new connections\n", addr.ToStringAddrPort());
# 1757 : 0 : return;
# 1758 : 0 : }
# 1759 : :
# 1760 [ - + ]: 707 : if (!sock->IsSelectable()) {
# 1761 : 0 : LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToStringAddrPort());
# 1762 : 0 : return;
# 1763 : 0 : }
# 1764 : :
# 1765 : : // According to the internet TCP_NODELAY is not carried into accepted sockets
# 1766 : : // on all platforms. Set it again here just to be sure.
# 1767 : 707 : const int on{1};
# 1768 [ - + ]: 707 : if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
# 1769 [ # # ]: 0 : LogPrint(BCLog::NET, "connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
# 1770 : 0 : addr.ToStringAddrPort());
# 1771 : 0 : }
# 1772 : :
# 1773 : : // Don't accept connections from banned peers.
# 1774 [ + - ][ + + ]: 707 : bool banned = m_banman && m_banman->IsBanned(addr);
# 1775 [ + + ][ + + ]: 707 : if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && banned)
# 1776 : 1 : {
# 1777 [ + - ]: 1 : LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToStringAddrPort());
# 1778 : 1 : return;
# 1779 : 1 : }
# 1780 : :
# 1781 : : // Only accept connections from discouraged peers if our inbound slots aren't (almost) full.
# 1782 [ + - ][ - + ]: 706 : bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
# 1783 [ + + ][ + + ]: 706 : if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged)
# [ - + ]
# 1784 : 0 : {
# 1785 [ # # ]: 0 : LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToStringAddrPort());
# 1786 : 0 : return;
# 1787 : 0 : }
# 1788 : :
# 1789 [ + + ]: 706 : if (nInbound >= nMaxInbound)
# 1790 : 1 : {
# 1791 [ - + ]: 1 : if (!AttemptToEvictConnection()) {
# 1792 : : // No connection to evict, disconnect the new connection
# 1793 [ # # ]: 0 : LogPrint(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
# 1794 : 0 : return;
# 1795 : 0 : }
# 1796 : 1 : }
# 1797 : :
# 1798 : 706 : NodeId id = GetNewNodeId();
# 1799 : 706 : uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
# 1800 : :
# 1801 : 706 : ServiceFlags nodeServices = nLocalServices;
# 1802 [ + + ]: 706 : if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::BloomFilter)) {
# 1803 : 2 : nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
# 1804 : 2 : }
# 1805 : :
# 1806 : 706 : const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
# 1807 : 706 : CNode* pnode = new CNode(id,
# 1808 : 706 : std::move(sock),
# 1809 : 706 : addr,
# 1810 : 706 : CalculateKeyedNetGroup(addr),
# 1811 : 706 : nonce,
# 1812 : 706 : addr_bind,
# 1813 : 706 : /*addrNameIn=*/"",
# 1814 : 706 : ConnectionType::INBOUND,
# 1815 : 706 : inbound_onion,
# 1816 : 706 : CNodeOptions{
# 1817 : 706 : .permission_flags = permission_flags,
# 1818 : 706 : .prefer_evict = discouraged,
# 1819 : 706 : .recv_flood_size = nReceiveFloodSize,
# 1820 : 706 : });
# 1821 : 706 : pnode->AddRef();
# 1822 : 706 : m_msgproc->InitializeNode(*pnode, nodeServices);
# 1823 : :
# 1824 [ + - ]: 706 : LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToStringAddrPort());
# 1825 : :
# 1826 : 706 : {
# 1827 : 706 : LOCK(m_nodes_mutex);
# 1828 : 706 : m_nodes.push_back(pnode);
# 1829 : 706 : }
# 1830 : :
# 1831 : : // We received a new connection, harvest entropy from the time (and our peer count)
# 1832 : 706 : RandAddEvent((uint32_t)id);
# 1833 : 706 : }
# 1834 : :
# 1835 : : bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type)
# 1836 : 67 : {
# 1837 : 67 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
# 1838 : 67 : std::optional<int> max_connections;
# 1839 [ - + ]: 67 : switch (conn_type) {
# 1840 [ - + ]: 0 : case ConnectionType::INBOUND:
# 1841 [ - + ]: 0 : case ConnectionType::MANUAL:
# 1842 : 0 : return false;
# 1843 [ + + ]: 40 : case ConnectionType::OUTBOUND_FULL_RELAY:
# 1844 : 40 : max_connections = m_max_outbound_full_relay;
# 1845 : 40 : break;
# 1846 [ + + ]: 22 : case ConnectionType::BLOCK_RELAY:
# 1847 : 22 : max_connections = m_max_outbound_block_relay;
# 1848 : 22 : break;
# 1849 : : // no limit for ADDR_FETCH because -seednode has no limit either
# 1850 [ + + ]: 3 : case ConnectionType::ADDR_FETCH:
# 1851 : 3 : break;
# 1852 : : // no limit for FEELER connections since they're short-lived
# 1853 [ + + ]: 2 : case ConnectionType::FEELER:
# 1854 : 2 : break;
# 1855 : 67 : } // no default case, so the compiler can warn about missing cases
# 1856 : :
# 1857 : : // Count existing connections
# 1858 : 67 : int existing_connections = WITH_LOCK(m_nodes_mutex,
# 1859 : 67 : return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](CNode* node) { return node->m_conn_type == conn_type; }););
# 1860 : :
# 1861 : : // Max connections of specified type already exist
# 1862 [ + + ][ - + ]: 67 : if (max_connections != std::nullopt && existing_connections >= max_connections) return false;
# 1863 : :
# 1864 : : // Max total outbound connections already exist
# 1865 : 67 : CSemaphoreGrant grant(*semOutbound, true);
# 1866 [ - + ]: 67 : if (!grant) return false;
# 1867 : :
# 1868 : 67 : OpenNetworkConnection(CAddress(), false, &grant, address.c_str(), conn_type);
# 1869 : 67 : return true;
# 1870 : 67 : }
# 1871 : :
# 1872 : : void CConnman::DisconnectNodes()
# 1873 : 217390 : {
# 1874 : 217390 : {
# 1875 : 217390 : LOCK(m_nodes_mutex);
# 1876 : :
# 1877 [ + + ]: 217390 : if (!fNetworkActive) {
# 1878 : : // Disconnect any connected nodes
# 1879 [ + + ]: 12 : for (CNode* pnode : m_nodes) {
# 1880 [ + - ]: 3 : if (!pnode->fDisconnect) {
# 1881 [ + - ]: 3 : LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
# 1882 : 3 : pnode->fDisconnect = true;
# 1883 : 3 : }
# 1884 : 3 : }
# 1885 : 12 : }
# 1886 : :
# 1887 : : // Disconnect unused nodes
# 1888 : 217390 : std::vector<CNode*> nodes_copy = m_nodes;
# 1889 [ + + ]: 217390 : for (CNode* pnode : nodes_copy)
# 1890 : 382578 : {
# 1891 [ + + ]: 382578 : if (pnode->fDisconnect)
# 1892 : 492 : {
# 1893 : : // remove from m_nodes
# 1894 : 492 : m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());
# 1895 : :
# 1896 : : // release outbound grant (if any)
# 1897 : 492 : pnode->grantOutbound.Release();
# 1898 : :
# 1899 : : // close socket and cleanup
# 1900 : 492 : pnode->CloseSocketDisconnect();
# 1901 : :
# 1902 : : // update connection count by network
# 1903 [ + + ]: 492 : if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];
# 1904 : :
# 1905 : : // hold in disconnected pool until all refs are released
# 1906 : 492 : pnode->Release();
# 1907 : 492 : m_nodes_disconnected.push_back(pnode);
# 1908 : 492 : }
# 1909 : 382578 : }
# 1910 : 217390 : }
# 1911 : 217390 : {
# 1912 : : // Delete disconnected nodes
# 1913 : 217390 : std::list<CNode*> nodes_disconnected_copy = m_nodes_disconnected;
# 1914 [ + + ]: 217390 : for (CNode* pnode : nodes_disconnected_copy)
# 1915 : 495 : {
# 1916 : : // Destroy the object only after other threads have stopped using it.
# 1917 [ + + ]: 495 : if (pnode->GetRefCount() <= 0) {
# 1918 : 492 : m_nodes_disconnected.remove(pnode);
# 1919 : 492 : DeleteNode(pnode);
# 1920 : 492 : }
# 1921 : 495 : }
# 1922 : 217390 : }
# 1923 : 217390 : }
# 1924 : :
# 1925 : : void CConnman::NotifyNumConnectionsChanged()
# 1926 : 217390 : {
# 1927 : 217390 : size_t nodes_size;
# 1928 : 217390 : {
# 1929 : 217390 : LOCK(m_nodes_mutex);
# 1930 : 217390 : nodes_size = m_nodes.size();
# 1931 : 217390 : }
# 1932 [ + + ]: 217390 : if(nodes_size != nPrevNodeCount) {
# 1933 : 1455 : nPrevNodeCount = nodes_size;
# 1934 [ + - ]: 1455 : if (m_client_interface) {
# 1935 : 1455 : m_client_interface->NotifyNumConnectionsChanged(nodes_size);
# 1936 : 1455 : }
# 1937 : 1455 : }
# 1938 : 217390 : }
# 1939 : :
# 1940 : : bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const
# 1941 : 643500 : {
# 1942 : 643500 : return node.m_connected + m_peer_connect_timeout < now;
# 1943 : 643500 : }
# 1944 : :
# 1945 : : bool CConnman::InactivityCheck(const CNode& node) const
# 1946 : 381507 : {
# 1947 : : // Tests that see disconnects after using mocktime can start nodes with a
# 1948 : : // large timeout. For example, -peertimeout=999999999.
# 1949 : 381507 : const auto now{GetTime<std::chrono::seconds>()};
# 1950 : 381507 : const auto last_send{node.m_last_send.load()};
# 1951 : 381507 : const auto last_recv{node.m_last_recv.load()};
# 1952 : :
# 1953 [ + + ]: 381507 : if (!ShouldRunInactivityChecks(node, now)) return false;
# 1954 : :
# 1955 [ + + ][ + + ]: 29 : if (last_recv.count() == 0 || last_send.count() == 0) {
# 1956 [ + - ]: 3 : LogPrint(BCLog::NET, "socket no message in first %i seconds, %d %d peer=%d\n", count_seconds(m_peer_connect_timeout), last_recv.count() != 0, last_send.count() != 0, node.GetId());
# 1957 : 3 : return true;
# 1958 : 3 : }
# 1959 : :
# 1960 [ - + ]: 26 : if (now > last_send + TIMEOUT_INTERVAL) {
# 1961 [ # # ]: 0 : LogPrint(BCLog::NET, "socket sending timeout: %is peer=%d\n", count_seconds(now - last_send), node.GetId());
# 1962 : 0 : return true;
# 1963 : 0 : }
# 1964 : :
# 1965 [ - + ]: 26 : if (now > last_recv + TIMEOUT_INTERVAL) {
# 1966 [ # # ]: 0 : LogPrint(BCLog::NET, "socket receive timeout: %is peer=%d\n", count_seconds(now - last_recv), node.GetId());
# 1967 : 0 : return true;
# 1968 : 0 : }
# 1969 : :
# 1970 [ + + ]: 26 : if (!node.fSuccessfullyConnected) {
# 1971 [ + - ]: 3 : LogPrint(BCLog::NET, "version handshake timeout peer=%d\n", node.GetId());
# 1972 : 3 : return true;
# 1973 : 3 : }
# 1974 : :
# 1975 : 23 : return false;
# 1976 : 26 : }
# 1977 : :
# 1978 : : Sock::EventsPerSock CConnman::GenerateWaitSockets(Span<CNode* const> nodes)
# 1979 : 217390 : {
# 1980 : 217390 : Sock::EventsPerSock events_per_sock;
# 1981 : :
# 1982 [ + + ]: 249400 : for (const ListenSocket& hListenSocket : vhListenSocket) {
# 1983 : 249400 : events_per_sock.emplace(hListenSocket.sock, Sock::Events{Sock::RECV});
# 1984 : 249400 : }
# 1985 : :
# 1986 [ + + ]: 382086 : for (CNode* pnode : nodes) {
# 1987 : 382086 : bool select_recv = !pnode->fPauseRecv;
# 1988 : 382086 : bool select_send;
# 1989 : 382086 : {
# 1990 : 382086 : LOCK(pnode->cs_vSend);
# 1991 : : // Sending is possible if either there are bytes to send right now, or if there will be
# 1992 : : // once a potential message from vSendMsg is handed to the transport. GetBytesToSend
# 1993 : : // determines both of these in a single call.
# 1994 : 382086 : const auto& [to_send, more, _msg_type] = pnode->m_transport->GetBytesToSend(!pnode->vSendMsg.empty());
# 1995 [ + + ][ - + ]: 382086 : select_send = !to_send.empty() || more;
# 1996 : 382086 : }
# 1997 [ + + ][ + - ]: 382086 : if (!select_recv && !select_send) continue;
# 1998 : :
# 1999 : 382085 : LOCK(pnode->m_sock_mutex);
# 2000 [ + - ]: 382085 : if (pnode->m_sock) {
# 2001 [ + + ][ + - ]: 382085 : Sock::Event event = (select_send ? Sock::SEND : 0) | (select_recv ? Sock::RECV : 0);
# 2002 : 382085 : events_per_sock.emplace(pnode->m_sock, Sock::Events{event});
# 2003 : 382085 : }
# 2004 : 382085 : }
# 2005 : :
# 2006 : 217390 : return events_per_sock;
# 2007 : 217390 : }
# 2008 : :
# 2009 : : void CConnman::SocketHandler()
# 2010 : 217390 : {
# 2011 : 217390 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 2012 : :
# 2013 : 217390 : Sock::EventsPerSock events_per_sock;
# 2014 : :
# 2015 : 217390 : {
# 2016 : 217390 : const NodesSnapshot snap{*this, /*shuffle=*/false};
# 2017 : :
# 2018 : 217390 : const auto timeout = std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS);
# 2019 : :
# 2020 : : // Check for the readiness of the already connected sockets and the
# 2021 : : // listening sockets in one call ("readiness" as in poll(2) or
# 2022 : : // select(2)). If none are ready, wait for a short while and return
# 2023 : : // empty sets.
# 2024 : 217390 : events_per_sock = GenerateWaitSockets(snap.Nodes());
# 2025 [ + + ][ + + ]: 217390 : if (events_per_sock.empty() || !events_per_sock.begin()->first->WaitMany(timeout, events_per_sock)) {
# [ - + ]
# 2026 : 16 : interruptNet.sleep_for(timeout);
# 2027 : 16 : }
# 2028 : :
# 2029 : : // Service (send/receive) each of the already connected nodes.
# 2030 : 217390 : SocketHandlerConnected(snap.Nodes(), events_per_sock);
# 2031 : 217390 : }
# 2032 : :
# 2033 : : // Accept new connections from listening sockets.
# 2034 : 217390 : SocketHandlerListening(events_per_sock);
# 2035 : 217390 : }
# 2036 : :
# 2037 : : void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
# 2038 : : const Sock::EventsPerSock& events_per_sock)
# 2039 : 217390 : {
# 2040 : 217390 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 2041 : :
# 2042 [ + + ]: 381816 : for (CNode* pnode : nodes) {
# 2043 [ + + ]: 381816 : if (interruptNet)
# 2044 : 309 : return;
# 2045 : :
# 2046 : : //
# 2047 : : // Receive
# 2048 : : //
# 2049 : 381507 : bool recvSet = false;
# 2050 : 381507 : bool sendSet = false;
# 2051 : 381507 : bool errorSet = false;
# 2052 : 381507 : {
# 2053 : 381507 : LOCK(pnode->m_sock_mutex);
# 2054 [ - + ]: 381507 : if (!pnode->m_sock) {
# 2055 : 0 : continue;
# 2056 : 0 : }
# 2057 : 381507 : const auto it = events_per_sock.find(pnode->m_sock);
# 2058 [ + + ]: 381507 : if (it != events_per_sock.end()) {
# 2059 : 381506 : recvSet = it->second.occurred & Sock::RECV;
# 2060 : 381506 : sendSet = it->second.occurred & Sock::SEND;
# 2061 : 381506 : errorSet = it->second.occurred & Sock::ERR;
# 2062 : 381506 : }
# 2063 : 381507 : }
# 2064 : :
# 2065 [ + + ]: 381507 : if (sendSet) {
# 2066 : : // Send data
# 2067 : 224 : auto [bytes_sent, data_left] = WITH_LOCK(pnode->cs_vSend, return SocketSendData(*pnode));
# 2068 [ + - ]: 224 : if (bytes_sent) {
# 2069 : 224 : RecordBytesSent(bytes_sent);
# 2070 : :
# 2071 : : // If both receiving and (non-optimistic) sending were possible, we first attempt
# 2072 : : // sending. If that succeeds, but does not fully drain the send queue, do not
# 2073 : : // attempt to receive. This avoids needlessly queueing data if the remote peer
# 2074 : : // is slow at receiving data, by means of TCP flow control. We only do this when
# 2075 : : // sending actually succeeded to make sure progress is always made; otherwise a
# 2076 : : // deadlock would be possible when both sides have data to send, but neither is
# 2077 : : // receiving.
# 2078 [ + + ]: 224 : if (data_left) recvSet = false;
# 2079 : 224 : }
# 2080 : 224 : }
# 2081 : :
# 2082 [ + + ][ - + ]: 381507 : if (recvSet || errorSet)
# 2083 : 151101 : {
# 2084 : : // typical socket buffer is 8K-64K
# 2085 : 151101 : uint8_t pchBuf[0x10000];
# 2086 : 151101 : int nBytes = 0;
# 2087 : 151101 : {
# 2088 : 151101 : LOCK(pnode->m_sock_mutex);
# 2089 [ - + ]: 151101 : if (!pnode->m_sock) {
# 2090 : 0 : continue;
# 2091 : 0 : }
# 2092 : 151101 : nBytes = pnode->m_sock->Recv(pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
# 2093 : 151101 : }
# 2094 [ + + ]: 151101 : if (nBytes > 0)
# 2095 : 150824 : {
# 2096 : 150824 : bool notify = false;
# 2097 [ + + ]: 150824 : if (!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
# 2098 : 3 : pnode->CloseSocketDisconnect();
# 2099 : 3 : }
# 2100 : 150824 : RecordBytesRecv(nBytes);
# 2101 [ + + ]: 150824 : if (notify) {
# 2102 : 113761 : pnode->MarkReceivedMsgsForProcessing();
# 2103 : 113761 : WakeMessageHandler();
# 2104 : 113761 : }
# 2105 : 150824 : }
# 2106 [ + + ]: 277 : else if (nBytes == 0)
# 2107 : 276 : {
# 2108 : : // socket closed gracefully
# 2109 [ + - ]: 276 : if (!pnode->fDisconnect) {
# 2110 [ + - ]: 276 : LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId());
# 2111 : 276 : }
# 2112 : 276 : pnode->CloseSocketDisconnect();
# 2113 : 276 : }
# 2114 [ + - ]: 1 : else if (nBytes < 0)
# 2115 : 1 : {
# 2116 : : // error
# 2117 : 1 : int nErr = WSAGetLastError();
# 2118 [ + - ][ + - ]: 1 : if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
# [ + - ][ + - ]
# 2119 : 1 : {
# 2120 [ + - ]: 1 : if (!pnode->fDisconnect) {
# 2121 [ + - ]: 1 : LogPrint(BCLog::NET, "socket recv error for peer=%d: %s\n", pnode->GetId(), NetworkErrorString(nErr));
# 2122 : 1 : }
# 2123 : 1 : pnode->CloseSocketDisconnect();
# 2124 : 1 : }
# 2125 : 1 : }
# 2126 : 151101 : }
# 2127 : :
# 2128 [ + + ]: 381507 : if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
# 2129 : 381507 : }
# 2130 : 217390 : }
# 2131 : :
# 2132 : : void CConnman::SocketHandlerListening(const Sock::EventsPerSock& events_per_sock)
# 2133 : 217390 : {
# 2134 [ + + ]: 249245 : for (const ListenSocket& listen_socket : vhListenSocket) {
# 2135 [ + + ]: 249245 : if (interruptNet) {
# 2136 : 662 : return;
# 2137 : 662 : }
# 2138 : 248583 : const auto it = events_per_sock.find(listen_socket.sock);
# 2139 [ + - ][ + + ]: 248583 : if (it != events_per_sock.end() && it->second.occurred & Sock::RECV) {
# [ + + ]
# 2140 : 707 : AcceptConnection(listen_socket);
# 2141 : 707 : }
# 2142 : 248583 : }
# 2143 : 217390 : }
# 2144 : :
# 2145 : : void CConnman::ThreadSocketHandler()
# 2146 : 669 : {
# 2147 : 669 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 2148 : :
# 2149 [ + + ]: 218059 : while (!interruptNet)
# 2150 : 217390 : {
# 2151 : 217390 : DisconnectNodes();
# 2152 : 217390 : NotifyNumConnectionsChanged();
# 2153 : 217390 : SocketHandler();
# 2154 : 217390 : }
# 2155 : 669 : }
# 2156 : :
# 2157 : : void CConnman::WakeMessageHandler()
# 2158 : 166383 : {
# 2159 : 166383 : {
# 2160 : 166383 : LOCK(mutexMsgProc);
# 2161 : 166383 : fMsgProcWake = true;
# 2162 : 166383 : }
# 2163 : 166383 : condMsgProc.notify_one();
# 2164 : 166383 : }
# 2165 : :
# 2166 : : void CConnman::ThreadDNSAddressSeed()
# 2167 : 11 : {
# 2168 : 11 : FastRandomContext rng;
# 2169 : 11 : std::vector<std::string> seeds = Params().DNSSeeds();
# 2170 : 11 : Shuffle(seeds.begin(), seeds.end(), rng);
# 2171 : 11 : int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections
# 2172 : 11 : int found = 0;
# 2173 : :
# 2174 [ + + ]: 11 : if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
# 2175 : : // When -forcednsseed is provided, query all.
# 2176 : 1 : seeds_right_now = seeds.size();
# 2177 [ + + ]: 10 : } else if (addrman.Size() == 0) {
# 2178 : : // If we have no known peers, query all.
# 2179 : : // This will occur on the first run, or if peers.dat has been
# 2180 : : // deleted.
# 2181 : 5 : seeds_right_now = seeds.size();
# 2182 : 5 : }
# 2183 : :
# 2184 : : // goal: only query DNS seed if address need is acute
# 2185 : : // * If we have a reasonable number of peers in addrman, spend
# 2186 : : // some time trying them first. This improves user privacy by
# 2187 : : // creating fewer identifying DNS requests, reduces trust by
# 2188 : : // giving seeds less influence on the network topology, and
# 2189 : : // reduces traffic to the seeds.
# 2190 : : // * When querying DNS seeds query a few at once, this ensures
# 2191 : : // that we don't give DNS seeds the ability to eclipse nodes
# 2192 : : // that query them.
# 2193 : : // * If we continue having problems, eventually query all the
# 2194 : : // DNS seeds, and if that fails too, also try the fixed seeds.
# 2195 : : // (done in ThreadOpenConnections)
# 2196 [ + + ]: 11 : const std::chrono::seconds seeds_wait_time = (addrman.Size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
# 2197 : :
# 2198 [ + + ]: 11 : for (const std::string& seed : seeds) {
# 2199 [ + + ]: 11 : if (seeds_right_now == 0) {
# 2200 : 5 : seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
# 2201 : :
# 2202 [ + - ]: 5 : if (addrman.Size() > 0) {
# 2203 : 5 : LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
# 2204 : 5 : std::chrono::seconds to_wait = seeds_wait_time;
# 2205 [ + + ]: 6 : while (to_wait.count() > 0) {
# 2206 : : // if sleeping for the MANY_PEERS interval, wake up
# 2207 : : // early to see if we have enough peers and can stop
# 2208 : : // this thread entirely freeing up its resources
# 2209 : 5 : std::chrono::seconds w = std::min(DNSSEEDS_DELAY_FEW_PEERS, to_wait);
# 2210 [ + + ]: 5 : if (!interruptNet.sleep_for(w)) return;
# 2211 : 2 : to_wait -= w;
# 2212 : :
# 2213 : 2 : int nRelevant = 0;
# 2214 : 2 : {
# 2215 : 2 : LOCK(m_nodes_mutex);
# 2216 [ + + ]: 4 : for (const CNode* pnode : m_nodes) {
# 2217 [ + - ][ + + ]: 4 : if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
# 2218 : 4 : }
# 2219 : 2 : }
# 2220 [ + + ]: 2 : if (nRelevant >= 2) {
# 2221 [ - + ]: 1 : if (found > 0) {
# 2222 : 0 : LogPrintf("%d addresses found from DNS seeds\n", found);
# 2223 : 0 : LogPrintf("P2P peers available. Finished DNS seeding.\n");
# 2224 : 1 : } else {
# 2225 : 1 : LogPrintf("P2P peers available. Skipped DNS seeding.\n");
# 2226 : 1 : }
# 2227 : 1 : return;
# 2228 : 1 : }
# 2229 : 2 : }
# 2230 : 5 : }
# 2231 : 5 : }
# 2232 : :
# 2233 [ - + ]: 7 : if (interruptNet) return;
# 2234 : :
# 2235 : : // hold off on querying seeds if P2P network deactivated
# 2236 [ - + ]: 7 : if (!fNetworkActive) {
# 2237 : 0 : LogPrintf("Waiting for network to be reactivated before querying DNS seeds.\n");
# 2238 : 0 : do {
# 2239 [ # # ]: 0 : if (!interruptNet.sleep_for(std::chrono::seconds{1})) return;
# 2240 [ # # ]: 0 : } while (!fNetworkActive);
# 2241 : 0 : }
# 2242 : :
# 2243 : 7 : LogPrintf("Loading addresses from DNS seed %s\n", seed);
# 2244 : : // If -proxy is in use, we make an ADDR_FETCH connection to the DNS resolved peer address
# 2245 : : // for the base dns seed domain in chainparams
# 2246 [ + + ]: 7 : if (HaveNameProxy()) {
# 2247 : 1 : AddAddrFetch(seed);
# 2248 : 6 : } else {
# 2249 : 6 : std::vector<CAddress> vAdd;
# 2250 : 6 : ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE);
# 2251 : 6 : std::string host = strprintf("x%x.%s", requiredServiceBits, seed);
# 2252 : 6 : CNetAddr resolveSource;
# 2253 [ - + ]: 6 : if (!resolveSource.SetInternal(host)) {
# 2254 : 0 : continue;
# 2255 : 0 : }
# 2256 : 6 : unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed
# 2257 : 6 : const auto addresses{LookupHost(host, nMaxIPs, true)};
# 2258 [ - + ]: 6 : if (!addresses.empty()) {
# 2259 [ # # ]: 0 : for (const CNetAddr& ip : addresses) {
# 2260 : 0 : CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
# 2261 : 0 : addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
# 2262 : 0 : vAdd.push_back(addr);
# 2263 : 0 : found++;
# 2264 : 0 : }
# 2265 : 0 : addrman.Add(vAdd, resolveSource);
# 2266 : 6 : } else {
# 2267 : : // If the seed does not support a subdomain with our desired service bits,
# 2268 : : // we make an ADDR_FETCH connection to the DNS resolved peer address for the
# 2269 : : // base dns seed domain in chainparams
# 2270 : 6 : AddAddrFetch(seed);
# 2271 : 6 : }
# 2272 : 6 : }
# 2273 : 7 : --seeds_right_now;
# 2274 : 7 : }
# 2275 : 7 : LogPrintf("%d addresses found from DNS seeds\n", found);
# 2276 : 7 : }
# 2277 : :
# 2278 : : void CConnman::DumpAddresses()
# 2279 : 675 : {
# 2280 : 675 : const auto start{SteadyClock::now()};
# 2281 : :
# 2282 : 675 : DumpPeerAddresses(::gArgs, addrman);
# 2283 : :
# 2284 [ + - ]: 675 : LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n",
# 2285 : 675 : addrman.Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
# 2286 : 675 : }
# 2287 : :
# 2288 : : void CConnman::ProcessAddrFetch()
# 2289 : 26 : {
# 2290 : 26 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
# 2291 : 26 : std::string strDest;
# 2292 : 26 : {
# 2293 : 26 : LOCK(m_addr_fetches_mutex);
# 2294 [ + + ]: 26 : if (m_addr_fetches.empty())
# 2295 : 25 : return;
# 2296 : 1 : strDest = m_addr_fetches.front();
# 2297 : 1 : m_addr_fetches.pop_front();
# 2298 : 1 : }
# 2299 : 0 : CAddress addr;
# 2300 : 1 : CSemaphoreGrant grant(*semOutbound, true);
# 2301 [ + - ]: 1 : if (grant) {
# 2302 : 1 : OpenNetworkConnection(addr, false, &grant, strDest.c_str(), ConnectionType::ADDR_FETCH);
# 2303 : 1 : }
# 2304 : 1 : }
# 2305 : :
# 2306 : : bool CConnman::GetTryNewOutboundPeer() const
# 2307 : 33 : {
# 2308 : 33 : return m_try_another_outbound_peer;
# 2309 : 33 : }
# 2310 : :
# 2311 : : void CConnman::SetTryNewOutboundPeer(bool flag)
# 2312 : 967 : {
# 2313 : 967 : m_try_another_outbound_peer = flag;
# 2314 [ + - ][ + + ]: 967 : LogPrint(BCLog::NET, "setting try another outbound peer=%s\n", flag ? "true" : "false");
# 2315 : 967 : }
# 2316 : :
# 2317 : : void CConnman::StartExtraBlockRelayPeers()
# 2318 : 19 : {
# 2319 [ + - ]: 19 : LogPrint(BCLog::NET, "enabling extra block-relay-only peers\n");
# 2320 : 19 : m_start_extra_block_relay_peers = true;
# 2321 : 19 : }
# 2322 : :
# 2323 : : // Return the number of peers we have over our outbound connection limit
# 2324 : : // Exclude peers that are marked for disconnect, or are going to be
# 2325 : : // disconnected soon (eg ADDR_FETCH and FEELER)
# 2326 : : // Also exclude peers that haven't finished initial connection handshake yet
# 2327 : : // (so that we don't decide we're over our desired connection limit, and then
# 2328 : : // evict some peer that has finished the handshake)
# 2329 : : int CConnman::GetExtraFullOutboundCount() const
# 2330 : 52 : {
# 2331 : 52 : int full_outbound_peers = 0;
# 2332 : 52 : {
# 2333 : 52 : LOCK(m_nodes_mutex);
# 2334 [ + + ]: 174 : for (const CNode* pnode : m_nodes) {
# 2335 [ + - ][ + + ]: 174 : if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
# [ + + ]
# 2336 : 108 : ++full_outbound_peers;
# 2337 : 108 : }
# 2338 : 174 : }
# 2339 : 52 : }
# 2340 : 52 : return std::max(full_outbound_peers - m_max_outbound_full_relay, 0);
# 2341 : 52 : }
# 2342 : :
# 2343 : : int CConnman::GetExtraBlockRelayCount() const
# 2344 : 52 : {
# 2345 : 52 : int block_relay_peers = 0;
# 2346 : 52 : {
# 2347 : 52 : LOCK(m_nodes_mutex);
# 2348 [ + + ]: 174 : for (const CNode* pnode : m_nodes) {
# 2349 [ + - ][ + + ]: 174 : if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
# [ + + ]
# 2350 : 22 : ++block_relay_peers;
# 2351 : 22 : }
# 2352 : 174 : }
# 2353 : 52 : }
# 2354 : 52 : return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
# 2355 : 52 : }
# 2356 : :
# 2357 : : std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
# 2358 : 5 : {
# 2359 : 5 : std::unordered_set<Network> networks{};
# 2360 [ + + ]: 40 : for (int n = 0; n < NET_MAX; n++) {
# 2361 : 35 : enum Network net = (enum Network)n;
# 2362 [ + + ][ + + ]: 35 : if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
# 2363 [ + + ][ + - ]: 25 : if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
# 2364 : 11 : networks.insert(net);
# 2365 : 11 : }
# 2366 : 25 : }
# 2367 : 5 : return networks;
# 2368 : 5 : }
# 2369 : :
# 2370 : : bool CConnman::MultipleManualOrFullOutboundConns(Network net) const
# 2371 : 76 : {
# 2372 : 76 : AssertLockHeld(m_nodes_mutex);
# 2373 : 76 : return m_network_conn_counts[net] > 1;
# 2374 : 76 : }
# 2375 : :
# 2376 : : bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
# 2377 : 0 : {
# 2378 : 0 : std::array<Network, 5> nets{NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS};
# 2379 : 0 : Shuffle(nets.begin(), nets.end(), FastRandomContext());
# 2380 : :
# 2381 : 0 : LOCK(m_nodes_mutex);
# 2382 [ # # ]: 0 : for (const auto net : nets) {
# 2383 [ # # ][ # # ]: 0 : if (IsReachable(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
# [ # # ]
# 2384 : 0 : network = net;
# 2385 : 0 : return true;
# 2386 : 0 : }
# 2387 : 0 : }
# 2388 : :
# 2389 : 0 : return false;
# 2390 : 0 : }
# 2391 : :
# 2392 : : void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
# 2393 : 27 : {
# 2394 : 27 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
# 2395 : 27 : FastRandomContext rng;
# 2396 : : // Connect to specific addresses
# 2397 [ + + ]: 27 : if (!connect.empty())
# 2398 : 6 : {
# 2399 : 6 : for (int64_t nLoop = 0;; nLoop++)
# 2400 : 6 : {
# 2401 [ + + ]: 6 : for (const std::string& strAddr : connect)
# 2402 : 8 : {
# 2403 : 8 : CAddress addr(CService(), NODE_NONE);
# 2404 : 8 : OpenNetworkConnection(addr, false, nullptr, strAddr.c_str(), ConnectionType::MANUAL);
# 2405 [ + - ][ - + ]: 8 : for (int i = 0; i < 10 && i < nLoop; i++)
# 2406 : 0 : {
# 2407 [ # # ]: 0 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 2408 : 0 : return;
# 2409 : 0 : }
# 2410 : 8 : }
# 2411 [ + - ]: 6 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 2412 : 6 : return;
# 2413 : 6 : }
# 2414 : 6 : }
# 2415 : :
# 2416 : : // Initiate network connections
# 2417 : 21 : auto start = GetTime<std::chrono::microseconds>();
# 2418 : :
# 2419 : : // Minimum time before next feeler connection (in microseconds).
# 2420 : 21 : auto next_feeler = GetExponentialRand(start, FEELER_INTERVAL);
# 2421 : 21 : auto next_extra_block_relay = GetExponentialRand(start, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
# 2422 : 21 : auto next_extra_network_peer{GetExponentialRand(start, EXTRA_NETWORK_PEER_INTERVAL)};
# 2423 : 21 : const bool dnsseed = gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED);
# 2424 : 21 : bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
# 2425 : 21 : const bool use_seednodes{gArgs.IsArgSet("-seednode")};
# 2426 : :
# 2427 [ + + ]: 21 : if (!add_fixed_seeds) {
# 2428 : 18 : LogPrintf("Fixed seeds are disabled\n");
# 2429 : 18 : }
# 2430 : :
# 2431 [ + - ]: 26 : while (!interruptNet)
# 2432 : 26 : {
# 2433 : 26 : ProcessAddrFetch();
# 2434 : :
# 2435 [ + + ]: 26 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 2436 : 21 : return;
# 2437 : :
# 2438 : 5 : CSemaphoreGrant grant(*semOutbound);
# 2439 [ - + ]: 5 : if (interruptNet)
# 2440 : 0 : return;
# 2441 : :
# 2442 : 5 : const std::unordered_set<Network> fixed_seed_networks{GetReachableEmptyNetworks()};
# 2443 [ + + ][ + - ]: 5 : if (add_fixed_seeds && !fixed_seed_networks.empty()) {
# 2444 : : // When the node starts with an empty peers.dat, there are a few other sources of peers before
# 2445 : : // we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
# 2446 : : // If none of those are available, we fallback on to fixed seeds immediately, else we allow
# 2447 : : // 60 seconds for any of those sources to populate addrman.
# 2448 : 3 : bool add_fixed_seeds_now = false;
# 2449 : : // It is cheapest to check if enough time has passed first.
# 2450 [ + + ]: 3 : if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
# 2451 : 2 : add_fixed_seeds_now = true;
# 2452 : 2 : LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
# 2453 : 2 : }
# 2454 : :
# 2455 : : // Perform cheap checks before locking a mutex.
# 2456 [ + - ][ + - ]: 1 : else if (!dnsseed && !use_seednodes) {
# 2457 : 1 : LOCK(m_added_nodes_mutex);
# 2458 [ + - ]: 1 : if (m_added_nodes.empty()) {
# 2459 : 1 : add_fixed_seeds_now = true;
# 2460 : 1 : LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet) and neither -addnode nor -seednode are provided\n");
# 2461 : 1 : }
# 2462 : 1 : }
# 2463 : :
# 2464 [ + - ]: 3 : if (add_fixed_seeds_now) {
# 2465 : 3 : std::vector<CAddress> seed_addrs{ConvertSeeds(Params().FixedSeeds())};
# 2466 : : // We will not make outgoing connections to peers that are unreachable
# 2467 : : // (e.g. because of -onlynet configuration).
# 2468 : : // Therefore, we do not add them to addrman in the first place.
# 2469 : : // In case previously unreachable networks become reachable
# 2470 : : // (e.g. in case of -onlynet changes by the user), fixed seeds will
# 2471 : : // be loaded only for networks for which we have no addresses.
# 2472 : 3 : seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
# 2473 : 3 : [&fixed_seed_networks](const CAddress& addr) { return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
# 2474 : 3 : seed_addrs.end());
# 2475 : 3 : CNetAddr local;
# 2476 : 3 : local.SetInternal("fixedseeds");
# 2477 : 3 : addrman.Add(seed_addrs, local);
# 2478 : 3 : add_fixed_seeds = false;
# 2479 : 3 : LogPrintf("Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
# 2480 : 3 : }
# 2481 : 3 : }
# 2482 : :
# 2483 : : //
# 2484 : : // Choose an address to connect to based on most recently seen
# 2485 : : //
# 2486 : 5 : CAddress addrConnect;
# 2487 : :
# 2488 : : // Only connect out to one peer per ipv4/ipv6 network group (/16 for IPv4).
# 2489 : 5 : int nOutboundFullRelay = 0;
# 2490 : 5 : int nOutboundBlockRelay = 0;
# 2491 : 5 : int outbound_privacy_network_peers = 0;
# 2492 : 5 : std::set<std::vector<unsigned char>> outbound_ipv46_peer_netgroups;
# 2493 : :
# 2494 : 5 : {
# 2495 : 5 : LOCK(m_nodes_mutex);
# 2496 [ + + ]: 5 : for (const CNode* pnode : m_nodes) {
# 2497 [ - + ]: 4 : if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
# 2498 [ + + ]: 4 : if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
# 2499 : :
# 2500 : : // Make sure our persistent outbound slots to ipv4/ipv6 peers belong to different netgroups.
# 2501 [ - + ]: 4 : switch (pnode->m_conn_type) {
# 2502 : : // We currently don't take inbound connections into account. Since they are
# 2503 : : // free to make, an attacker could make them to prevent us from connecting to
# 2504 : : // certain peers.
# 2505 [ + + ]: 2 : case ConnectionType::INBOUND:
# 2506 : : // Short-lived outbound connections should not affect how we select outbound
# 2507 : : // peers from addrman.
# 2508 [ - + ]: 2 : case ConnectionType::ADDR_FETCH:
# 2509 [ - + ]: 2 : case ConnectionType::FEELER:
# 2510 : 2 : break;
# 2511 [ - + ]: 0 : case ConnectionType::MANUAL:
# 2512 [ - + ]: 0 : case ConnectionType::OUTBOUND_FULL_RELAY:
# 2513 [ + + ]: 2 : case ConnectionType::BLOCK_RELAY:
# 2514 : 2 : const CAddress address{pnode->addr};
# 2515 [ - + ][ - + ]: 2 : if (address.IsTor() || address.IsI2P() || address.IsCJDNS()) {
# [ - + ]
# 2516 : : // Since our addrman-groups for these networks are
# 2517 : : // random, without relation to the route we
# 2518 : : // take to connect to these peers or to the
# 2519 : : // difficulty in obtaining addresses with diverse
# 2520 : : // groups, we don't worry about diversity with
# 2521 : : // respect to our addrman groups when connecting to
# 2522 : : // these networks.
# 2523 : 0 : ++outbound_privacy_network_peers;
# 2524 : 2 : } else {
# 2525 : 2 : outbound_ipv46_peer_netgroups.insert(m_netgroupman.GetGroup(address));
# 2526 : 2 : }
# 2527 : 4 : } // no default case, so the compiler can warn about missing cases
# 2528 : 4 : }
# 2529 : 5 : }
# 2530 : :
# 2531 : 5 : ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
# 2532 : 5 : auto now = GetTime<std::chrono::microseconds>();
# 2533 : 5 : bool anchor = false;
# 2534 : 5 : bool fFeeler = false;
# 2535 : 5 : std::optional<Network> preferred_net;
# 2536 : :
# 2537 : : // Determine what type of connection to open. Opening
# 2538 : : // BLOCK_RELAY connections to addresses from anchors.dat gets the highest
# 2539 : : // priority. Then we open OUTBOUND_FULL_RELAY priority until we
# 2540 : : // meet our full-relay capacity. Then we open BLOCK_RELAY connection
# 2541 : : // until we hit our block-relay-only peer limit.
# 2542 : : // GetTryNewOutboundPeer() gets set when a stale tip is detected, so we
# 2543 : : // try opening an additional OUTBOUND_FULL_RELAY connection. If none of
# 2544 : : // these conditions are met, check to see if it's time to try an extra
# 2545 : : // block-relay-only peer (to confirm our tip is current, see below) or the next_feeler
# 2546 : : // timer to decide if we should open a FEELER.
# 2547 : :
# 2548 [ + + ][ + - ]: 5 : if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) {
# 2549 : 1 : conn_type = ConnectionType::BLOCK_RELAY;
# 2550 : 1 : anchor = true;
# 2551 [ + - ]: 4 : } else if (nOutboundFullRelay < m_max_outbound_full_relay) {
# 2552 : : // OUTBOUND_FULL_RELAY
# 2553 [ # # ]: 4 : } else if (nOutboundBlockRelay < m_max_outbound_block_relay) {
# 2554 : 0 : conn_type = ConnectionType::BLOCK_RELAY;
# 2555 [ # # ]: 0 : } else if (GetTryNewOutboundPeer()) {
# 2556 : : // OUTBOUND_FULL_RELAY
# 2557 [ # # ][ # # ]: 0 : } else if (now > next_extra_block_relay && m_start_extra_block_relay_peers) {
# 2558 : : // Periodically connect to a peer (using regular outbound selection
# 2559 : : // methodology from addrman) and stay connected long enough to sync
# 2560 : : // headers, but not much else.
# 2561 : : //
# 2562 : : // Then disconnect the peer, if we haven't learned anything new.
# 2563 : : //
# 2564 : : // The idea is to make eclipse attacks very difficult to pull off,
# 2565 : : // because every few minutes we're finding a new peer to learn headers
# 2566 : : // from.
# 2567 : : //
# 2568 : : // This is similar to the logic for trying extra outbound (full-relay)
# 2569 : : // peers, except:
# 2570 : : // - we do this all the time on an exponential timer, rather than just when
# 2571 : : // our tip is stale
# 2572 : : // - we potentially disconnect our next-youngest block-relay-only peer, if our
# 2573 : : // newest block-relay-only peer delivers a block more recently.
# 2574 : : // See the eviction logic in net_processing.cpp.
# 2575 : : //
# 2576 : : // Because we can promote these connections to block-relay-only
# 2577 : : // connections, they do not get their own ConnectionType enum
# 2578 : : // (similar to how we deal with extra outbound peers).
# 2579 : 0 : next_extra_block_relay = GetExponentialRand(now, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
# 2580 : 0 : conn_type = ConnectionType::BLOCK_RELAY;
# 2581 [ # # ]: 0 : } else if (now > next_feeler) {
# 2582 : 0 : next_feeler = GetExponentialRand(now, FEELER_INTERVAL);
# 2583 : 0 : conn_type = ConnectionType::FEELER;
# 2584 : 0 : fFeeler = true;
# 2585 [ # # ]: 0 : } else if (nOutboundFullRelay == m_max_outbound_full_relay &&
# 2586 [ # # ]: 0 : m_max_outbound_full_relay == MAX_OUTBOUND_FULL_RELAY_CONNECTIONS &&
# 2587 [ # # ]: 0 : now > next_extra_network_peer &&
# 2588 [ # # ]: 0 : MaybePickPreferredNetwork(preferred_net)) {
# 2589 : : // Full outbound connection management: Attempt to get at least one
# 2590 : : // outbound peer from each reachable network by making extra connections
# 2591 : : // and then protecting "only" peers from a network during outbound eviction.
# 2592 : : // This is not attempted if the user changed -maxconnections to a value
# 2593 : : // so low that less than MAX_OUTBOUND_FULL_RELAY_CONNECTIONS are made,
# 2594 : : // to prevent interactions with otherwise protected outbound peers.
# 2595 : 0 : next_extra_network_peer = GetExponentialRand(now, EXTRA_NETWORK_PEER_INTERVAL);
# 2596 : 0 : } else {
# 2597 : : // skip to next iteration of while loop
# 2598 : 0 : continue;
# 2599 : 0 : }
# 2600 : :
# 2601 : 5 : addrman.ResolveCollisions();
# 2602 : :
# 2603 : 5 : const auto current_time{NodeClock::now()};
# 2604 : 5 : int nTries = 0;
# 2605 [ + - ]: 105 : while (!interruptNet)
# 2606 : 105 : {
# 2607 [ + + ][ + - ]: 105 : if (anchor && !m_anchors.empty()) {
# 2608 : 1 : const CAddress addr = m_anchors.back();
# 2609 : 1 : m_anchors.pop_back();
# 2610 [ - + ][ - + ]: 1 : if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) ||
# [ - + ][ - + ]
# 2611 [ - + ]: 1 : !HasAllDesirableServiceFlags(addr.nServices) ||
# 2612 [ - + ]: 1 : outbound_ipv46_peer_netgroups.count(m_netgroupman.GetGroup(addr))) continue;
# 2613 : 1 : addrConnect = addr;
# 2614 [ + - ]: 1 : LogPrint(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToStringAddrPort());
# 2615 : 1 : break;
# 2616 : 1 : }
# 2617 : :
# 2618 : : // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
# 2619 : : // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
# 2620 : : // already-connected network ranges, ...) before trying new addrman addresses.
# 2621 : 104 : nTries++;
# 2622 [ + + ]: 104 : if (nTries > 100)
# 2623 : 1 : break;
# 2624 : :
# 2625 : 103 : CAddress addr;
# 2626 : 103 : NodeSeconds addr_last_try{0s};
# 2627 : :
# 2628 [ - + ]: 103 : if (fFeeler) {
# 2629 : : // First, try to get a tried table collision address. This returns
# 2630 : : // an empty (invalid) address if there are no collisions to try.
# 2631 : 0 : std::tie(addr, addr_last_try) = addrman.SelectTriedCollision();
# 2632 : :
# 2633 [ # # ]: 0 : if (!addr.IsValid()) {
# 2634 : : // No tried table collisions. Select a new table address
# 2635 : : // for our feeler.
# 2636 : 0 : std::tie(addr, addr_last_try) = addrman.Select(true);
# 2637 [ # # ]: 0 : } else if (AlreadyConnectedToAddress(addr)) {
# 2638 : : // If test-before-evict logic would have us connect to a
# 2639 : : // peer that we're already connected to, just mark that
# 2640 : : // address as Good(). We won't be able to initiate the
# 2641 : : // connection anyway, so this avoids inadvertently evicting
# 2642 : : // a currently-connected peer.
# 2643 : 0 : addrman.Good(addr);
# 2644 : : // Select a new table address for our feeler instead.
# 2645 : 0 : std::tie(addr, addr_last_try) = addrman.Select(true);
# 2646 : 0 : }
# 2647 : 103 : } else {
# 2648 : : // Not a feeler
# 2649 : : // If preferred_net has a value set, pick an extra outbound
# 2650 : : // peer from that network. The eviction logic in net_processing
# 2651 : : // ensures that a peer from another network will be evicted.
# 2652 : 103 : std::tie(addr, addr_last_try) = addrman.Select(false, preferred_net);
# 2653 : 103 : }
# 2654 : :
# 2655 : : // Require outbound IPv4/IPv6 connections, other than feelers, to be to distinct network groups
# 2656 [ + + ][ + - ]: 103 : if (!fFeeler && outbound_ipv46_peer_netgroups.count(m_netgroupman.GetGroup(addr))) {
# [ + + ]
# 2657 : 100 : continue;
# 2658 : 100 : }
# 2659 : :
# 2660 : : // if we selected an invalid or local address, restart
# 2661 [ + - ][ # # ]: 3 : if (!addr.IsValid() || IsLocal(addr)) {
# 2662 : 3 : break;
# 2663 : 3 : }
# 2664 : :
# 2665 [ # # ]: 0 : if (!IsReachable(addr))
# 2666 : 0 : continue;
# 2667 : :
# 2668 : : // only consider very recently tried nodes after 30 failed attempts
# 2669 [ # # ][ # # ]: 0 : if (current_time - addr_last_try < 10min && nTries < 30) {
# [ # # ]
# 2670 : 0 : continue;
# 2671 : 0 : }
# 2672 : :
# 2673 : : // for non-feelers, require all the services we'll want,
# 2674 : : // for feelers, only require they be a full node (only because most
# 2675 : : // SPV clients don't have a good address DB available)
# 2676 [ # # ][ # # ]: 0 : if (!fFeeler && !HasAllDesirableServiceFlags(addr.nServices)) {
# 2677 : 0 : continue;
# 2678 [ # # ][ # # ]: 0 : } else if (fFeeler && !MayHaveUsefulAddressDB(addr.nServices)) {
# 2679 : 0 : continue;
# 2680 : 0 : }
# 2681 : :
# 2682 : : // Do not connect to bad ports, unless 50 invalid addresses have been selected already.
# 2683 [ # # ][ # # ]: 0 : if (nTries < 50 && (addr.IsIPv4() || addr.IsIPv6()) && IsBadPort(addr.GetPort())) {
# [ # # ][ # # ]
# 2684 : 0 : continue;
# 2685 : 0 : }
# 2686 : :
# 2687 : 0 : addrConnect = addr;
# 2688 : 0 : break;
# 2689 : 0 : }
# 2690 : :
# 2691 [ + + ]: 5 : if (addrConnect.IsValid()) {
# 2692 [ - + ]: 1 : if (fFeeler) {
# 2693 : : // Add small amount of random noise before connection to avoid synchronization.
# 2694 [ # # ]: 0 : if (!interruptNet.sleep_for(rng.rand_uniform_duration<CThreadInterrupt::Clock>(FEELER_SLEEP_WINDOW))) {
# 2695 : 0 : return;
# 2696 : 0 : }
# 2697 [ # # ]: 0 : LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToStringAddrPort());
# 2698 : 0 : }
# 2699 : :
# 2700 [ # # ][ - + ]: 1 : if (preferred_net != std::nullopt) LogPrint(BCLog::NET, "Making network specific connection to %s on %s.\n", addrConnect.ToStringAddrPort(), GetNetworkName(preferred_net.value()));
# 2701 : :
# 2702 : : // Record addrman failure attempts when node has at least 2 persistent outbound connections to peers with
# 2703 : : // different netgroups in ipv4/ipv6 networks + all peers in Tor/I2P/CJDNS networks.
# 2704 : : // Don't record addrman failure attempts when node is offline. This can be identified since all local
# 2705 : : // network connections (if any) belong in the same netgroup, and the size of `outbound_ipv46_peer_netgroups` would only be 1.
# 2706 : 1 : const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(nMaxConnections - 1, 2)};
# 2707 : 1 : OpenNetworkConnection(addrConnect, count_failures, &grant, /*strDest=*/nullptr, conn_type);
# 2708 : 1 : }
# 2709 : 5 : }
# 2710 : 21 : }
# 2711 : :
# 2712 : : std::vector<CAddress> CConnman::GetCurrentBlockRelayOnlyConns() const
# 2713 : 21 : {
# 2714 : 21 : std::vector<CAddress> ret;
# 2715 : 21 : LOCK(m_nodes_mutex);
# 2716 [ + + ]: 21 : for (const CNode* pnode : m_nodes) {
# 2717 [ + + ]: 8 : if (pnode->IsBlockOnlyConn()) {
# 2718 : 3 : ret.push_back(pnode->addr);
# 2719 : 3 : }
# 2720 : 8 : }
# 2721 : :
# 2722 : 21 : return ret;
# 2723 : 21 : }
# 2724 : :
# 2725 : : std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
# 2726 : 2445 : {
# 2727 : 2445 : std::vector<AddedNodeInfo> ret;
# 2728 : :
# 2729 : 2445 : std::list<std::string> lAddresses(0);
# 2730 : 2445 : {
# 2731 : 2445 : LOCK(m_added_nodes_mutex);
# 2732 : 2445 : ret.reserve(m_added_nodes.size());
# 2733 : 2445 : std::copy(m_added_nodes.cbegin(), m_added_nodes.cend(), std::back_inserter(lAddresses));
# 2734 : 2445 : }
# 2735 : :
# 2736 : :
# 2737 : : // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
# 2738 : 2445 : std::map<CService, bool> mapConnected;
# 2739 : 2445 : std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
# 2740 : 2445 : {
# 2741 : 2445 : LOCK(m_nodes_mutex);
# 2742 [ + + ]: 2715 : for (const CNode* pnode : m_nodes) {
# 2743 [ + - ]: 2715 : if (pnode->addr.IsValid()) {
# 2744 : 2715 : mapConnected[pnode->addr] = pnode->IsInboundConn();
# 2745 : 2715 : }
# 2746 : 2715 : std::string addrName{pnode->m_addr_name};
# 2747 [ + - ]: 2715 : if (!addrName.empty()) {
# 2748 : 2715 : mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(), static_cast<const CService&>(pnode->addr));
# 2749 : 2715 : }
# 2750 : 2715 : }
# 2751 : 2445 : }
# 2752 : :
# 2753 [ + + ]: 2445 : for (const std::string& strAddNode : lAddresses) {
# 2754 : 3 : CService service(LookupNumeric(strAddNode, Params().GetDefaultPort(strAddNode)));
# 2755 : 3 : AddedNodeInfo addedNode{strAddNode, CService(), false, false};
# 2756 [ + + ]: 3 : if (service.IsValid()) {
# 2757 : : // strAddNode is an IP:port
# 2758 : 1 : auto it = mapConnected.find(service);
# 2759 [ - + ]: 1 : if (it != mapConnected.end()) {
# 2760 : 0 : addedNode.resolvedAddress = service;
# 2761 : 0 : addedNode.fConnected = true;
# 2762 : 0 : addedNode.fInbound = it->second;
# 2763 : 0 : }
# 2764 : 2 : } else {
# 2765 : : // strAddNode is a name
# 2766 : 2 : auto it = mapConnectedByName.find(strAddNode);
# 2767 [ - + ]: 2 : if (it != mapConnectedByName.end()) {
# 2768 : 0 : addedNode.resolvedAddress = it->second.second;
# 2769 : 0 : addedNode.fConnected = true;
# 2770 : 0 : addedNode.fInbound = it->second.first;
# 2771 : 0 : }
# 2772 : 2 : }
# 2773 : 3 : ret.emplace_back(std::move(addedNode));
# 2774 : 3 : }
# 2775 : :
# 2776 : 2445 : return ret;
# 2777 : 2445 : }
# 2778 : :
# 2779 : : void CConnman::ThreadOpenAddedConnections()
# 2780 : 669 : {
# 2781 : 669 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
# 2782 : 2441 : while (true)
# 2783 : 2441 : {
# 2784 : 2441 : CSemaphoreGrant grant(*semAddnode);
# 2785 : 2441 : std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
# 2786 : 2441 : bool tried = false;
# 2787 [ + + ]: 2441 : for (const AddedNodeInfo& info : vInfo) {
# 2788 [ + - ]: 2 : if (!info.fConnected) {
# 2789 [ - + ]: 2 : if (!grant.TryAcquire()) {
# 2790 : : // If we've used up our semaphore and need a new one, let's not wait here since while we are waiting
# 2791 : : // the addednodeinfo state might change.
# 2792 : 0 : break;
# 2793 : 0 : }
# 2794 : 2 : tried = true;
# 2795 : 2 : CAddress addr(CService(), NODE_NONE);
# 2796 : 2 : OpenNetworkConnection(addr, false, &grant, info.strAddedNode.c_str(), ConnectionType::MANUAL);
# 2797 [ + + ]: 2 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 2798 : 1 : return;
# 2799 : 2 : }
# 2800 : 2 : }
# 2801 : : // Retry every 60 seconds if a connection was attempted, otherwise two seconds
# 2802 [ + + ][ + + ]: 2440 : if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)))
# 2803 : 668 : return;
# 2804 : 2440 : }
# 2805 : 669 : }
# 2806 : :
# 2807 : : // if successful, this moves the passed grant to the constructed node
# 2808 : : void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, ConnectionType conn_type)
# 2809 : 382 : {
# 2810 : 382 : AssertLockNotHeld(m_unused_i2p_sessions_mutex);
# 2811 : 382 : assert(conn_type != ConnectionType::INBOUND);
# 2812 : :
# 2813 : : //
# 2814 : : // Initiate outbound network connection
# 2815 : : //
# 2816 [ - + ]: 382 : if (interruptNet) {
# 2817 : 0 : return;
# 2818 : 0 : }
# 2819 [ - + ]: 382 : if (!fNetworkActive) {
# 2820 : 0 : return;
# 2821 : 0 : }
# 2822 [ + + ]: 382 : if (!pszDest) {
# 2823 [ + - ][ - + ]: 1 : bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect));
# [ - + ]
# 2824 [ - + ][ - + ]: 1 : if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) {
# [ - + ]
# 2825 : 0 : return;
# 2826 : 0 : }
# 2827 [ - + ]: 381 : } else if (FindNode(std::string(pszDest)))
# 2828 : 0 : return;
# 2829 : :
# 2830 : 382 : CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
# 2831 : :
# 2832 [ + + ]: 382 : if (!pnode)
# 2833 : 16 : return;
# 2834 [ + + ]: 366 : if (grantOutbound)
# 2835 : 67 : grantOutbound->MoveTo(pnode->grantOutbound);
# 2836 : :
# 2837 : 366 : m_msgproc->InitializeNode(*pnode, nLocalServices);
# 2838 : 366 : {
# 2839 : 366 : LOCK(m_nodes_mutex);
# 2840 : 366 : m_nodes.push_back(pnode);
# 2841 : :
# 2842 : : // update connection count by network
# 2843 [ + + ]: 366 : if (pnode->IsManualOrFullOutboundConn()) ++m_network_conn_counts[pnode->addr.GetNetwork()];
# 2844 : 366 : }
# 2845 : 366 : }
# 2846 : :
# 2847 : : Mutex NetEventsInterface::g_msgproc_mutex;
# 2848 : :
# 2849 : : void CConnman::ThreadMessageHandler()
# 2850 : 669 : {
# 2851 : 669 : LOCK(NetEventsInterface::g_msgproc_mutex);
# 2852 : :
# 2853 [ + + ]: 166196 : while (!flagInterruptMsgProc)
# 2854 : 165528 : {
# 2855 : 165528 : bool fMoreWork = false;
# 2856 : :
# 2857 : 165528 : {
# 2858 : : // Randomize the order in which we process messages from/to our peers.
# 2859 : : // This prevents attacks in which an attacker exploits having multiple
# 2860 : : // consecutive connections in the m_nodes list.
# 2861 : 165528 : const NodesSnapshot snap{*this, /*shuffle=*/true};
# 2862 : :
# 2863 [ + + ]: 264957 : for (CNode* pnode : snap.Nodes()) {
# 2864 [ + + ]: 264957 : if (pnode->fDisconnect)
# 2865 : 28 : continue;
# 2866 : :
# 2867 : : // Receive messages
# 2868 : 264929 : bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
# 2869 [ + + ][ + + ]: 264929 : fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
# 2870 [ + + ]: 264929 : if (flagInterruptMsgProc)
# 2871 : 1 : return;
# 2872 : : // Send messages
# 2873 : 264928 : m_msgproc->SendMessages(pnode);
# 2874 : :
# 2875 [ - + ]: 264928 : if (flagInterruptMsgProc)
# 2876 : 0 : return;
# 2877 : 264928 : }
# 2878 : 165528 : }
# 2879 : :
# 2880 : 165527 : WAIT_LOCK(mutexMsgProc, lock);
# 2881 [ + + ]: 165527 : if (!fMoreWork) {
# 2882 : 201639 : condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this]() EXCLUSIVE_LOCKS_REQUIRED(mutexMsgProc) { return fMsgProcWake; });
# 2883 : 109657 : }
# 2884 : 165527 : fMsgProcWake = false;
# 2885 : 165527 : }
# 2886 : 669 : }
# 2887 : :
# 2888 : : void CConnman::ThreadI2PAcceptIncoming()
# 2889 : 4 : {
# 2890 : 4 : static constexpr auto err_wait_begin = 1s;
# 2891 : 4 : static constexpr auto err_wait_cap = 5min;
# 2892 : 4 : auto err_wait = err_wait_begin;
# 2893 : :
# 2894 : 4 : bool advertising_listen_addr = false;
# 2895 : 4 : i2p::Connection conn;
# 2896 : :
# 2897 [ + + ]: 9 : while (!interruptNet) {
# 2898 : :
# 2899 [ + - ]: 5 : if (!m_i2p_sam_session->Listen(conn)) {
# 2900 [ - + ][ # # ]: 5 : if (advertising_listen_addr && conn.me.IsValid()) {
# 2901 : 0 : RemoveLocal(conn.me);
# 2902 : 0 : advertising_listen_addr = false;
# 2903 : 0 : }
# 2904 : :
# 2905 : 5 : interruptNet.sleep_for(err_wait);
# 2906 [ + - ]: 5 : if (err_wait < err_wait_cap) {
# 2907 : 5 : err_wait *= 2;
# 2908 : 5 : }
# 2909 : :
# 2910 : 5 : continue;
# 2911 : 5 : }
# 2912 : :
# 2913 [ # # ]: 0 : if (!advertising_listen_addr) {
# 2914 : 0 : AddLocal(conn.me, LOCAL_MANUAL);
# 2915 : 0 : advertising_listen_addr = true;
# 2916 : 0 : }
# 2917 : :
# 2918 [ # # ]: 0 : if (!m_i2p_sam_session->Accept(conn)) {
# 2919 : 0 : continue;
# 2920 : 0 : }
# 2921 : :
# 2922 : 0 : CreateNodeFromAcceptedSocket(std::move(conn.sock), NetPermissionFlags::None,
# 2923 : 0 : CAddress{conn.me, NODE_NONE}, CAddress{conn.peer, NODE_NONE});
# 2924 : 0 : }
# 2925 : 4 : }
# 2926 : :
# 2927 : : bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError, NetPermissionFlags permissions)
# 2928 : 1327 : {
# 2929 : 1327 : int nOne = 1;
# 2930 : :
# 2931 : : // Create socket for listening for incoming connections
# 2932 : 1327 : struct sockaddr_storage sockaddr;
# 2933 : 1327 : socklen_t len = sizeof(sockaddr);
# 2934 [ - + ]: 1327 : if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
# 2935 : 0 : {
# 2936 : 0 : strError = strprintf(Untranslated("Bind address family for %s not supported"), addrBind.ToStringAddrPort());
# 2937 [ # # ]: 0 : LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
# 2938 : 0 : return false;
# 2939 : 0 : }
# 2940 : :
# 2941 : 1327 : std::unique_ptr<Sock> sock = CreateSock(addrBind);
# 2942 [ - + ]: 1327 : if (!sock) {
# 2943 : 0 : strError = strprintf(Untranslated("Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
# 2944 [ # # ]: 0 : LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
# 2945 : 0 : return false;
# 2946 : 0 : }
# 2947 : :
# 2948 : : // Allow binding if the port is still in TIME_WAIT state after
# 2949 : : // the program was closed and restarted.
# 2950 [ - + ]: 1327 : if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, sizeof(int)) == SOCKET_ERROR) {
# 2951 : 0 : strError = strprintf(Untranslated("Error setting SO_REUSEADDR on socket: %s, continuing anyway"), NetworkErrorString(WSAGetLastError()));
# 2952 : 0 : LogPrintf("%s\n", strError.original);
# 2953 : 0 : }
# 2954 : :
# 2955 : : // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
# 2956 : : // and enable it by default or not. Try to enable it, if possible.
# 2957 [ + + ]: 1327 : if (addrBind.IsIPv6()) {
# 2958 : 2 : #ifdef IPV6_V6ONLY
# 2959 [ - + ]: 2 : if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_arg_type)&nOne, sizeof(int)) == SOCKET_ERROR) {
# 2960 : 0 : strError = strprintf(Untranslated("Error setting IPV6_V6ONLY on socket: %s, continuing anyway"), NetworkErrorString(WSAGetLastError()));
# 2961 : 0 : LogPrintf("%s\n", strError.original);
# 2962 : 0 : }
# 2963 : 2 : #endif
# 2964 : : #ifdef WIN32
# 2965 : : int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
# 2966 : : if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR) {
# 2967 : : strError = strprintf(Untranslated("Error setting IPV6_PROTECTION_LEVEL on socket: %s, continuing anyway"), NetworkErrorString(WSAGetLastError()));
# 2968 : : LogPrintf("%s\n", strError.original);
# 2969 : : }
# 2970 : : #endif
# 2971 : 2 : }
# 2972 : :
# 2973 [ + + ]: 1327 : if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
# 2974 : 510 : int nErr = WSAGetLastError();
# 2975 [ + - ]: 510 : if (nErr == WSAEADDRINUSE)
# 2976 : 510 : strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToStringAddrPort(), PACKAGE_NAME);
# 2977 : 0 : else
# 2978 : 0 : strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToStringAddrPort(), NetworkErrorString(nErr));
# 2979 [ + - ]: 510 : LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
# 2980 : 510 : return false;
# 2981 : 510 : }
# 2982 : 817 : LogPrintf("Bound to %s\n", addrBind.ToStringAddrPort());
# 2983 : :
# 2984 : : // Listen for incoming connections
# 2985 [ - + ]: 817 : if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)
# 2986 : 0 : {
# 2987 : 0 : strError = strprintf(_("Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
# 2988 [ # # ]: 0 : LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
# 2989 : 0 : return false;
# 2990 : 0 : }
# 2991 : :
# 2992 : 817 : vhListenSocket.emplace_back(std::move(sock), permissions);
# 2993 : 817 : return true;
# 2994 : 817 : }
# 2995 : :
# 2996 : : void Discover()
# 2997 : 9 : {
# 2998 [ + + ]: 9 : if (!fDiscover)
# 2999 : 7 : return;
# 3000 : :
# 3001 : : #ifdef WIN32
# 3002 : : // Get local host IP
# 3003 : : char pszHostName[256] = "";
# 3004 : : if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
# 3005 : : {
# 3006 : : const std::vector<CNetAddr> addresses{LookupHost(pszHostName, 0, true)};
# 3007 : : for (const CNetAddr& addr : addresses)
# 3008 : : {
# 3009 : : if (AddLocal(addr, LOCAL_IF))
# 3010 : : LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToStringAddr());
# 3011 : : }
# 3012 : : }
# 3013 : : #elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
# 3014 : : // Get local host ip
# 3015 : 2 : struct ifaddrs* myaddrs;
# 3016 [ + - ]: 2 : if (getifaddrs(&myaddrs) == 0)
# 3017 : 2 : {
# 3018 [ + + ]: 24 : for (struct ifaddrs* ifa = myaddrs; ifa != nullptr; ifa = ifa->ifa_next)
# 3019 : 22 : {
# 3020 [ - + ]: 22 : if (ifa->ifa_addr == nullptr) continue;
# 3021 [ + + ]: 22 : if ((ifa->ifa_flags & IFF_UP) == 0) continue;
# 3022 [ - + ]: 20 : if (strcmp(ifa->ifa_name, "lo") == 0) continue;
# 3023 [ + + ]: 20 : if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
# 3024 [ + + ]: 12 : if (ifa->ifa_addr->sa_family == AF_INET)
# 3025 : 6 : {
# 3026 : 6 : struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
# 3027 : 6 : CNetAddr addr(s4->sin_addr);
# 3028 [ - + ]: 6 : if (AddLocal(addr, LOCAL_IF))
# 3029 : 6 : LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToStringAddr());
# 3030 : 6 : }
# 3031 [ - + ]: 6 : else if (ifa->ifa_addr->sa_family == AF_INET6)
# 3032 : 0 : {
# 3033 : 0 : struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
# 3034 : 0 : CNetAddr addr(s6->sin6_addr);
# 3035 [ # # ]: 0 : if (AddLocal(addr, LOCAL_IF))
# 3036 : 0 : LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToStringAddr());
# 3037 : 0 : }
# 3038 : 12 : }
# 3039 : 2 : freeifaddrs(myaddrs);
# 3040 : 2 : }
# 3041 : 2 : #endif
# 3042 : 2 : }
# 3043 : :
# 3044 : : void CConnman::SetNetworkActive(bool active)
# 3045 : 964 : {
# 3046 : 964 : LogPrintf("%s: %s\n", __func__, active);
# 3047 : :
# 3048 [ + + ]: 964 : if (fNetworkActive == active) {
# 3049 : 954 : return;
# 3050 : 954 : }
# 3051 : :
# 3052 : 10 : fNetworkActive = active;
# 3053 : :
# 3054 [ + + ]: 10 : if (m_client_interface) {
# 3055 : 3 : m_client_interface->NotifyNetworkActiveChanged(fNetworkActive);
# 3056 : 3 : }
# 3057 : 10 : }
# 3058 : :
# 3059 : : CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In, AddrMan& addrman_in,
# 3060 : : const NetGroupManager& netgroupman, bool network_active)
# 3061 : : : addrman(addrman_in)
# 3062 : : , m_netgroupman{netgroupman}
# 3063 : : , nSeed0(nSeed0In)
# 3064 : : , nSeed1(nSeed1In)
# 3065 : 957 : {
# 3066 : 957 : SetTryNewOutboundPeer(false);
# 3067 : :
# 3068 : 957 : Options connOptions;
# 3069 : 957 : Init(connOptions);
# 3070 : 957 : SetNetworkActive(network_active);
# 3071 : 957 : }
# 3072 : :
# 3073 : : NodeId CConnman::GetNewNodeId()
# 3074 : 1072 : {
# 3075 : 1072 : return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
# 3076 : 1072 : }
# 3077 : :
# 3078 : :
# 3079 : : bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlags permissions)
# 3080 : 1327 : {
# 3081 : 1327 : const CService addr{MaybeFlipIPv6toCJDNS(addr_)};
# 3082 : :
# 3083 : 1327 : bilingual_str strError;
# 3084 [ + + ]: 1327 : if (!BindListenPort(addr, strError, permissions)) {
# 3085 [ - + ][ # # ]: 510 : if ((flags & BF_REPORT_ERROR) && m_client_interface) {
# 3086 : 0 : m_client_interface->ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR);
# 3087 : 0 : }
# 3088 : 510 : return false;
# 3089 : 510 : }
# 3090 : :
# 3091 [ - + ][ # # ]: 817 : if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !NetPermissions::HasFlag(permissions, NetPermissionFlags::NoBan)) {
# [ # # ][ # # ]
# 3092 : 0 : AddLocal(addr, LOCAL_BIND);
# 3093 : 0 : }
# 3094 : :
# 3095 : 817 : return true;
# 3096 : 1327 : }
# 3097 : :
# 3098 : : bool CConnman::InitBinds(const Options& options)
# 3099 : 662 : {
# 3100 : 662 : bool fBound = false;
# 3101 [ + + ]: 662 : for (const auto& addrBind : options.vBinds) {
# 3102 : 659 : fBound |= Bind(addrBind, BF_REPORT_ERROR, NetPermissionFlags::None);
# 3103 : 659 : }
# 3104 [ + + ]: 662 : for (const auto& addrBind : options.vWhiteBinds) {
# 3105 : 1 : fBound |= Bind(addrBind.m_service, BF_REPORT_ERROR, addrBind.m_flags);
# 3106 : 1 : }
# 3107 [ + + ]: 663 : for (const auto& addr_bind : options.onion_binds) {
# 3108 : 663 : fBound |= Bind(addr_bind, BF_DONT_ADVERTISE, NetPermissionFlags::None);
# 3109 : 663 : }
# 3110 [ + + ]: 662 : if (options.bind_on_any) {
# 3111 : 2 : struct in_addr inaddr_any;
# 3112 : 2 : inaddr_any.s_addr = htonl(INADDR_ANY);
# 3113 : 2 : struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
# 3114 : 2 : fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::None);
# 3115 [ - + ]: 2 : fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::None);
# 3116 : 2 : }
# 3117 : 662 : return fBound;
# 3118 : 662 : }
# 3119 : :
# 3120 : : bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
# 3121 : 669 : {
# 3122 : 669 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3123 : 669 : Init(connOptions);
# 3124 : :
# 3125 [ + + ][ - + ]: 669 : if (fListen && !InitBinds(connOptions)) {
# 3126 [ # # ]: 0 : if (m_client_interface) {
# 3127 : 0 : m_client_interface->ThreadSafeMessageBox(
# 3128 : 0 : _("Failed to listen on any port. Use -listen=0 if you want this."),
# 3129 : 0 : "", CClientUIInterface::MSG_ERROR);
# 3130 : 0 : }
# 3131 : 0 : return false;
# 3132 : 0 : }
# 3133 : :
# 3134 : 669 : Proxy i2p_sam;
# 3135 [ + + ][ + + ]: 669 : if (GetProxy(NET_I2P, i2p_sam) && connOptions.m_i2p_accept_incoming) {
# 3136 : 4 : m_i2p_sam_session = std::make_unique<i2p::sam::Session>(gArgs.GetDataDirNet() / "i2p_private_key",
# 3137 : 4 : i2p_sam.proxy, &interruptNet);
# 3138 : 4 : }
# 3139 : :
# 3140 [ + + ]: 669 : for (const auto& strDest : connOptions.vSeedNodes) {
# 3141 : 3 : AddAddrFetch(strDest);
# 3142 : 3 : }
# 3143 : :
# 3144 [ + + ]: 669 : if (m_use_addrman_outgoing) {
# 3145 : : // Load addresses from anchors.dat
# 3146 : 21 : m_anchors = ReadAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME);
# 3147 [ - + ]: 21 : if (m_anchors.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
# 3148 : 0 : m_anchors.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
# 3149 : 0 : }
# 3150 : 21 : LogPrintf("%i block-relay-only anchors will be tried for connections.\n", m_anchors.size());
# 3151 : 21 : }
# 3152 : :
# 3153 [ + - ]: 669 : if (m_client_interface) {
# 3154 : 669 : m_client_interface->InitMessage(_("Starting network threads…").translated);
# 3155 : 669 : }
# 3156 : :
# 3157 : 669 : fAddressesInitialized = true;
# 3158 : :
# 3159 [ + - ]: 669 : if (semOutbound == nullptr) {
# 3160 : : // initialize semaphore
# 3161 : 669 : semOutbound = std::make_unique<CSemaphore>(std::min(m_max_outbound, nMaxConnections));
# 3162 : 669 : }
# 3163 [ + - ]: 669 : if (semAddnode == nullptr) {
# 3164 : : // initialize semaphore
# 3165 : 669 : semAddnode = std::make_unique<CSemaphore>(nMaxAddnode);
# 3166 : 669 : }
# 3167 : :
# 3168 : : //
# 3169 : : // Start threads
# 3170 : : //
# 3171 : 669 : assert(m_msgproc);
# 3172 : 669 : InterruptSocks5(false);
# 3173 : 669 : interruptNet.reset();
# 3174 : 669 : flagInterruptMsgProc = false;
# 3175 : :
# 3176 : 669 : {
# 3177 : 669 : LOCK(mutexMsgProc);
# 3178 : 669 : fMsgProcWake = false;
# 3179 : 669 : }
# 3180 : :
# 3181 : : // Send and receive from sockets, accept connections
# 3182 : 669 : threadSocketHandler = std::thread(&util::TraceThread, "net", [this] { ThreadSocketHandler(); });
# 3183 : :
# 3184 [ + + ]: 669 : if (!gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED))
# 3185 : 669 : LogPrintf("DNS seeding disabled\n");
# 3186 : 11 : else
# 3187 : 11 : threadDNSAddressSeed = std::thread(&util::TraceThread, "dnsseed", [this] { ThreadDNSAddressSeed(); });
# 3188 : :
# 3189 : : // Initiate manual connections
# 3190 : 669 : threadOpenAddedConnections = std::thread(&util::TraceThread, "addcon", [this] { ThreadOpenAddedConnections(); });
# 3191 : :
# 3192 [ + + ][ - + ]: 669 : if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
# 3193 [ # # ]: 0 : if (m_client_interface) {
# 3194 : 0 : m_client_interface->ThreadSafeMessageBox(
# 3195 : 0 : _("Cannot provide specific connections and have addrman find outgoing connections at the same time."),
# 3196 : 0 : "", CClientUIInterface::MSG_ERROR);
# 3197 : 0 : }
# 3198 : 0 : return false;
# 3199 : 0 : }
# 3200 [ + + ][ + + ]: 669 : if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
# 3201 : 27 : threadOpenConnections = std::thread(
# 3202 : 27 : &util::TraceThread, "opencon",
# 3203 : 27 : [this, connect = connOptions.m_specified_outgoing] { ThreadOpenConnections(connect); });
# 3204 : 27 : }
# 3205 : :
# 3206 : : // Process messages
# 3207 : 669 : threadMessageHandler = std::thread(&util::TraceThread, "msghand", [this] { ThreadMessageHandler(); });
# 3208 : :
# 3209 [ + + ]: 669 : if (m_i2p_sam_session) {
# 3210 : 4 : threadI2PAcceptIncoming =
# 3211 : 4 : std::thread(&util::TraceThread, "i2paccept", [this] { ThreadI2PAcceptIncoming(); });
# 3212 : 4 : }
# 3213 : :
# 3214 : : // Dump network addresses
# 3215 : 669 : scheduler.scheduleEvery([this] { DumpAddresses(); }, DUMP_PEERS_INTERVAL);
# 3216 : :
# 3217 : 669 : return true;
# 3218 : 669 : }
# 3219 : :
# 3220 : : class CNetCleanup
# 3221 : : {
# 3222 : : public:
# 3223 : : CNetCleanup() = default;
# 3224 : :
# 3225 : : ~CNetCleanup()
# 3226 : 0 : {
# 3227 : : #ifdef WIN32
# 3228 : : // Shutdown Windows Sockets
# 3229 : : WSACleanup();
# 3230 : : #endif
# 3231 : 0 : }
# 3232 : : };
# 3233 : : static CNetCleanup instance_of_cnetcleanup;
# 3234 : :
# 3235 : : void CConnman::Interrupt()
# 3236 : 1673 : {
# 3237 : 1673 : {
# 3238 : 1673 : LOCK(mutexMsgProc);
# 3239 : 1673 : flagInterruptMsgProc = true;
# 3240 : 1673 : }
# 3241 : 1673 : condMsgProc.notify_all();
# 3242 : :
# 3243 : 1673 : interruptNet();
# 3244 : 1673 : InterruptSocks5(true);
# 3245 : :
# 3246 [ + + ]: 1673 : if (semOutbound) {
# 3247 [ + + ]: 8018 : for (int i=0; i<m_max_outbound; i++) {
# 3248 : 7349 : semOutbound->post();
# 3249 : 7349 : }
# 3250 : 669 : }
# 3251 : :
# 3252 [ + + ]: 1673 : if (semAddnode) {
# 3253 [ + + ]: 6021 : for (int i=0; i<nMaxAddnode; i++) {
# 3254 : 5352 : semAddnode->post();
# 3255 : 5352 : }
# 3256 : 669 : }
# 3257 : 1673 : }
# 3258 : :
# 3259 : : void CConnman::StopThreads()
# 3260 : 1673 : {
# 3261 [ + + ]: 1673 : if (threadI2PAcceptIncoming.joinable()) {
# 3262 : 4 : threadI2PAcceptIncoming.join();
# 3263 : 4 : }
# 3264 [ + + ]: 1673 : if (threadMessageHandler.joinable())
# 3265 : 669 : threadMessageHandler.join();
# 3266 [ + + ]: 1673 : if (threadOpenConnections.joinable())
# 3267 : 27 : threadOpenConnections.join();
# 3268 [ + + ]: 1673 : if (threadOpenAddedConnections.joinable())
# 3269 : 669 : threadOpenAddedConnections.join();
# 3270 [ + + ]: 1673 : if (threadDNSAddressSeed.joinable())
# 3271 : 11 : threadDNSAddressSeed.join();
# 3272 [ + + ]: 1673 : if (threadSocketHandler.joinable())
# 3273 : 669 : threadSocketHandler.join();
# 3274 : 1673 : }
# 3275 : :
# 3276 : : void CConnman::StopNodes()
# 3277 : 1673 : {
# 3278 [ + + ]: 1673 : if (fAddressesInitialized) {
# 3279 : 669 : DumpAddresses();
# 3280 : 669 : fAddressesInitialized = false;
# 3281 : :
# 3282 [ + + ]: 669 : if (m_use_addrman_outgoing) {
# 3283 : : // Anchor connections are only dumped during clean shutdown.
# 3284 : 21 : std::vector<CAddress> anchors_to_dump = GetCurrentBlockRelayOnlyConns();
# 3285 [ - + ]: 21 : if (anchors_to_dump.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
# 3286 : 0 : anchors_to_dump.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
# 3287 : 0 : }
# 3288 : 21 : DumpAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME, anchors_to_dump);
# 3289 : 21 : }
# 3290 : 669 : }
# 3291 : :
# 3292 : : // Delete peer connections.
# 3293 : 1673 : std::vector<CNode*> nodes;
# 3294 : 1673 : WITH_LOCK(m_nodes_mutex, nodes.swap(m_nodes));
# 3295 [ + + ]: 1673 : for (CNode* pnode : nodes) {
# 3296 : 580 : pnode->CloseSocketDisconnect();
# 3297 : 580 : DeleteNode(pnode);
# 3298 : 580 : }
# 3299 : :
# 3300 [ - + ]: 1673 : for (CNode* pnode : m_nodes_disconnected) {
# 3301 : 0 : DeleteNode(pnode);
# 3302 : 0 : }
# 3303 : 1673 : m_nodes_disconnected.clear();
# 3304 : 1673 : vhListenSocket.clear();
# 3305 : 1673 : semOutbound.reset();
# 3306 : 1673 : semAddnode.reset();
# 3307 : 1673 : }
# 3308 : :
# 3309 : : void CConnman::DeleteNode(CNode* pnode)
# 3310 : 1072 : {
# 3311 : 1072 : assert(pnode);
# 3312 : 1072 : m_msgproc->FinalizeNode(*pnode);
# 3313 : 1072 : delete pnode;
# 3314 : 1072 : }
# 3315 : :
# 3316 : : CConnman::~CConnman()
# 3317 : 957 : {
# 3318 : 957 : Interrupt();
# 3319 : 957 : Stop();
# 3320 : 957 : }
# 3321 : :
# 3322 : : std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
# 3323 : 338 : {
# 3324 : 338 : std::vector<CAddress> addresses = addrman.GetAddr(max_addresses, max_pct, network);
# 3325 [ + - ]: 338 : if (m_banman) {
# 3326 : 338 : addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
# 3327 [ - + ][ - + ]: 25466 : [this](const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
# 3328 : 338 : addresses.end());
# 3329 : 338 : }
# 3330 : 338 : return addresses;
# 3331 : 338 : }
# 3332 : :
# 3333 : : std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct)
# 3334 : 656 : {
# 3335 : 656 : auto local_socket_bytes = requestor.addrBind.GetAddrBytes();
# 3336 : 656 : uint64_t cache_id = GetDeterministicRandomizer(RANDOMIZER_ID_ADDRCACHE)
# 3337 : 656 : .Write(requestor.ConnectedThroughNetwork())
# 3338 : 656 : .Write(local_socket_bytes)
# 3339 : : // For outbound connections, the port of the bound address is randomly
# 3340 : : // assigned by the OS and would therefore not be useful for seeding.
# 3341 [ + - ]: 656 : .Write(requestor.IsInboundConn() ? requestor.addrBind.GetPort() : 0)
# 3342 : 656 : .Finalize();
# 3343 : 656 : const auto current_time = GetTime<std::chrono::microseconds>();
# 3344 : 656 : auto r = m_addr_response_caches.emplace(cache_id, CachedAddrResponse{});
# 3345 : 656 : CachedAddrResponse& cache_entry = r.first->second;
# 3346 [ + + ]: 656 : if (cache_entry.m_cache_entry_expiration < current_time) { // If emplace() added new one it has expiration 0.
# 3347 : 286 : cache_entry.m_addrs_response_cache = GetAddresses(max_addresses, max_pct, /*network=*/std::nullopt);
# 3348 : : // Choosing a proper cache lifetime is a trade-off between the privacy leak minimization
# 3349 : : // and the usefulness of ADDR responses to honest users.
# 3350 : : //
# 3351 : : // Longer cache lifetime makes it more difficult for an attacker to scrape
# 3352 : : // enough AddrMan data to maliciously infer something useful.
# 3353 : : // By the time an attacker scraped enough AddrMan records, most of
# 3354 : : // the records should be old enough to not leak topology info by
# 3355 : : // e.g. analyzing real-time changes in timestamps.
# 3356 : : //
# 3357 : : // It takes only several hundred requests to scrape everything from an AddrMan containing 100,000 nodes,
# 3358 : : // so ~24 hours of cache lifetime indeed makes the data less inferable by the time
# 3359 : : // most of it could be scraped (considering that timestamps are updated via
# 3360 : : // ADDR self-announcements and when nodes communicate).
# 3361 : : // We also should be robust to those attacks which may not require scraping *full* victim's AddrMan
# 3362 : : // (because even several timestamps of the same handful of nodes may leak privacy).
# 3363 : : //
# 3364 : : // On the other hand, longer cache lifetime makes ADDR responses
# 3365 : : // outdated and less useful for an honest requestor, e.g. if most nodes
# 3366 : : // in the ADDR response are no longer active.
# 3367 : : //
# 3368 : : // However, the churn in the network is known to be rather low. Since we consider
# 3369 : : // nodes to be "terrible" (see IsTerrible()) if the timestamps are older than 30 days,
# 3370 : : // max. 24 hours of "penalty" due to cache shouldn't make any meaningful difference
# 3371 : : // in terms of the freshness of the response.
# 3372 : 286 : cache_entry.m_cache_entry_expiration = current_time + std::chrono::hours(21) + GetRandMillis(std::chrono::hours(6));
# 3373 : 286 : }
# 3374 : 656 : return cache_entry.m_addrs_response_cache;
# 3375 : 656 : }
# 3376 : :
# 3377 : : bool CConnman::AddNode(const std::string& strNode)
# 3378 : 2 : {
# 3379 : 2 : LOCK(m_added_nodes_mutex);
# 3380 [ + + ]: 2 : for (const std::string& it : m_added_nodes) {
# 3381 [ + - ]: 1 : if (strNode == it) return false;
# 3382 : 1 : }
# 3383 : :
# 3384 : 1 : m_added_nodes.push_back(strNode);
# 3385 : 1 : return true;
# 3386 : 2 : }
# 3387 : :
# 3388 : : bool CConnman::RemoveAddedNode(const std::string& strNode)
# 3389 : 2 : {
# 3390 : 2 : LOCK(m_added_nodes_mutex);
# 3391 [ + + ]: 2 : for(std::vector<std::string>::iterator it = m_added_nodes.begin(); it != m_added_nodes.end(); ++it) {
# 3392 [ + - ]: 1 : if (strNode == *it) {
# 3393 : 1 : m_added_nodes.erase(it);
# 3394 : 1 : return true;
# 3395 : 1 : }
# 3396 : 1 : }
# 3397 : 1 : return false;
# 3398 : 2 : }
# 3399 : :
# 3400 : : size_t CConnman::GetNodeCount(ConnectionDirection flags) const
# 3401 : 227 : {
# 3402 : 227 : LOCK(m_nodes_mutex);
# 3403 [ + + ]: 227 : if (flags == ConnectionDirection::Both) // Shortcut if we want total
# 3404 : 79 : return m_nodes.size();
# 3405 : :
# 3406 : 148 : int nNum = 0;
# 3407 [ + + ]: 226 : for (const auto& pnode : m_nodes) {
# 3408 [ + + ][ + + ]: 226 : if (flags & (pnode->IsInboundConn() ? ConnectionDirection::In : ConnectionDirection::Out)) {
# 3409 : 113 : nNum++;
# 3410 : 113 : }
# 3411 : 226 : }
# 3412 : :
# 3413 : 148 : return nNum;
# 3414 : 227 : }
# 3415 : :
# 3416 : : uint32_t CConnman::GetMappedAS(const CNetAddr& addr) const
# 3417 : 10494 : {
# 3418 : 10494 : return m_netgroupman.GetMappedAS(addr);
# 3419 : 10494 : }
# 3420 : :
# 3421 : : void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats) const
# 3422 : 5413 : {
# 3423 : 5413 : vstats.clear();
# 3424 : 5413 : LOCK(m_nodes_mutex);
# 3425 : 5413 : vstats.reserve(m_nodes.size());
# 3426 [ + + ]: 9100 : for (CNode* pnode : m_nodes) {
# 3427 : 9100 : vstats.emplace_back();
# 3428 : 9100 : pnode->CopyStats(vstats.back());
# 3429 : 9100 : vstats.back().m_mapped_as = GetMappedAS(pnode->addr);
# 3430 : 9100 : }
# 3431 : 5413 : }
# 3432 : :
# 3433 : : bool CConnman::DisconnectNode(const std::string& strNode)
# 3434 : 2 : {
# 3435 : 2 : LOCK(m_nodes_mutex);
# 3436 [ + + ]: 2 : if (CNode* pnode = FindNode(strNode)) {
# 3437 [ + - ][ - + ]: 1 : LogPrint(BCLog::NET, "disconnect by address%s matched peer=%d; disconnecting\n", (fLogIPs ? strprintf("=%s", strNode) : ""), pnode->GetId());
# 3438 : 1 : pnode->fDisconnect = true;
# 3439 : 1 : return true;
# 3440 : 1 : }
# 3441 : 1 : return false;
# 3442 : 2 : }
# 3443 : :
# 3444 : : bool CConnman::DisconnectNode(const CSubNet& subnet)
# 3445 : 32 : {
# 3446 : 32 : bool disconnected = false;
# 3447 : 32 : LOCK(m_nodes_mutex);
# 3448 [ + + ]: 32 : for (CNode* pnode : m_nodes) {
# 3449 [ + + ]: 17 : if (subnet.Match(pnode->addr)) {
# 3450 [ + - ][ - + ]: 10 : LogPrint(BCLog::NET, "disconnect by subnet%s matched peer=%d; disconnecting\n", (fLogIPs ? strprintf("=%s", subnet.ToString()) : ""), pnode->GetId());
# 3451 : 10 : pnode->fDisconnect = true;
# 3452 : 10 : disconnected = true;
# 3453 : 10 : }
# 3454 : 17 : }
# 3455 : 32 : return disconnected;
# 3456 : 32 : }
# 3457 : :
# 3458 : : bool CConnman::DisconnectNode(const CNetAddr& addr)
# 3459 : 18 : {
# 3460 : 18 : return DisconnectNode(CSubNet(addr));
# 3461 : 18 : }
# 3462 : :
# 3463 : : bool CConnman::DisconnectNode(NodeId id)
# 3464 : 55 : {
# 3465 : 55 : LOCK(m_nodes_mutex);
# 3466 [ + - ]: 84 : for(CNode* pnode : m_nodes) {
# 3467 [ + + ]: 84 : if (id == pnode->GetId()) {
# 3468 [ + - ]: 55 : LogPrint(BCLog::NET, "disconnect by id peer=%d; disconnecting\n", pnode->GetId());
# 3469 : 55 : pnode->fDisconnect = true;
# 3470 : 55 : return true;
# 3471 : 55 : }
# 3472 : 84 : }
# 3473 : 0 : return false;
# 3474 : 55 : }
# 3475 : :
# 3476 : : void CConnman::RecordBytesRecv(uint64_t bytes)
# 3477 : 150824 : {
# 3478 : 150824 : nTotalBytesRecv += bytes;
# 3479 : 150824 : }
# 3480 : :
# 3481 : : void CConnman::RecordBytesSent(uint64_t bytes)
# 3482 : 130913 : {
# 3483 : 130913 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3484 : 130913 : LOCK(m_total_bytes_sent_mutex);
# 3485 : :
# 3486 : 130913 : nTotalBytesSent += bytes;
# 3487 : :
# 3488 : 130913 : const auto now = GetTime<std::chrono::seconds>();
# 3489 [ + + ]: 130913 : if (nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME < now)
# 3490 : 402 : {
# 3491 : : // timeframe expired, reset cycle
# 3492 : 402 : nMaxOutboundCycleStartTime = now;
# 3493 : 402 : nMaxOutboundTotalBytesSentInCycle = 0;
# 3494 : 402 : }
# 3495 : :
# 3496 : 130913 : nMaxOutboundTotalBytesSentInCycle += bytes;
# 3497 : 130913 : }
# 3498 : :
# 3499 : : uint64_t CConnman::GetMaxOutboundTarget() const
# 3500 : 7 : {
# 3501 : 7 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3502 : 7 : LOCK(m_total_bytes_sent_mutex);
# 3503 : 7 : return nMaxOutboundLimit;
# 3504 : 7 : }
# 3505 : :
# 3506 : : std::chrono::seconds CConnman::GetMaxOutboundTimeframe() const
# 3507 : 7 : {
# 3508 : 7 : return MAX_UPLOAD_TIMEFRAME;
# 3509 : 7 : }
# 3510 : :
# 3511 : : std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle() const
# 3512 : 7 : {
# 3513 : 7 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3514 : 7 : LOCK(m_total_bytes_sent_mutex);
# 3515 : 7 : return GetMaxOutboundTimeLeftInCycle_();
# 3516 : 7 : }
# 3517 : :
# 3518 : : std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle_() const
# 3519 : 1109 : {
# 3520 : 1109 : AssertLockHeld(m_total_bytes_sent_mutex);
# 3521 : :
# 3522 [ + + ]: 1109 : if (nMaxOutboundLimit == 0)
# 3523 : 7 : return 0s;
# 3524 : :
# 3525 [ - + ]: 1102 : if (nMaxOutboundCycleStartTime.count() == 0)
# 3526 : 0 : return MAX_UPLOAD_TIMEFRAME;
# 3527 : :
# 3528 : 1102 : const std::chrono::seconds cycleEndTime = nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME;
# 3529 : 1102 : const auto now = GetTime<std::chrono::seconds>();
# 3530 [ - + ]: 1102 : return (cycleEndTime < now) ? 0s : cycleEndTime - now;
# 3531 : 1102 : }
# 3532 : :
# 3533 : : bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit) const
# 3534 : 33730 : {
# 3535 : 33730 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3536 : 33730 : LOCK(m_total_bytes_sent_mutex);
# 3537 [ + + ]: 33730 : if (nMaxOutboundLimit == 0)
# 3538 : 32628 : return false;
# 3539 : :
# 3540 [ + - ]: 1102 : if (historicalBlockServingLimit)
# 3541 : 1102 : {
# 3542 : : // keep a large enough buffer to at least relay each block once
# 3543 : 1102 : const std::chrono::seconds timeLeftInCycle = GetMaxOutboundTimeLeftInCycle_();
# 3544 : 1102 : const uint64_t buffer = timeLeftInCycle / std::chrono::minutes{10} * MAX_BLOCK_SERIALIZED_SIZE;
# 3545 [ + + ][ + + ]: 1102 : if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
# 3546 : 823 : return true;
# 3547 : 1102 : }
# 3548 [ # # ]: 0 : else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
# 3549 : 0 : return true;
# 3550 : :
# 3551 : 279 : return false;
# 3552 : 1102 : }
# 3553 : :
# 3554 : : uint64_t CConnman::GetOutboundTargetBytesLeft() const
# 3555 : 7 : {
# 3556 : 7 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3557 : 7 : LOCK(m_total_bytes_sent_mutex);
# 3558 [ + - ]: 7 : if (nMaxOutboundLimit == 0)
# 3559 : 7 : return 0;
# 3560 : :
# 3561 [ # # ]: 0 : return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
# 3562 : 7 : }
# 3563 : :
# 3564 : : uint64_t CConnman::GetTotalBytesRecv() const
# 3565 : 7 : {
# 3566 : 7 : return nTotalBytesRecv;
# 3567 : 7 : }
# 3568 : :
# 3569 : : uint64_t CConnman::GetTotalBytesSent() const
# 3570 : 7 : {
# 3571 : 7 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3572 : 7 : LOCK(m_total_bytes_sent_mutex);
# 3573 : 7 : return nTotalBytesSent;
# 3574 : 7 : }
# 3575 : :
# 3576 : : ServiceFlags CConnman::GetLocalServices() const
# 3577 : 74 : {
# 3578 : 74 : return nLocalServices;
# 3579 : 74 : }
# 3580 : :
# 3581 : : CNode::CNode(NodeId idIn,
# 3582 : : std::shared_ptr<Sock> sock,
# 3583 : : const CAddress& addrIn,
# 3584 : : uint64_t nKeyedNetGroupIn,
# 3585 : : uint64_t nLocalHostNonceIn,
# 3586 : : const CAddress& addrBindIn,
# 3587 : : const std::string& addrNameIn,
# 3588 : : ConnectionType conn_type_in,
# 3589 : : bool inbound_onion,
# 3590 : : CNodeOptions&& node_opts)
# 3591 : : : m_transport{std::make_unique<V1Transport>(idIn, SER_NETWORK, INIT_PROTO_VERSION)},
# 3592 : : m_permission_flags{node_opts.permission_flags},
# 3593 : : m_sock{sock},
# 3594 : : m_connected{GetTime<std::chrono::seconds>()},
# 3595 : : addr{addrIn},
# 3596 : : addrBind{addrBindIn},
# 3597 : : m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
# 3598 : : m_inbound_onion{inbound_onion},
# 3599 : : m_prefer_evict{node_opts.prefer_evict},
# 3600 : : nKeyedNetGroup{nKeyedNetGroupIn},
# 3601 : : m_conn_type{conn_type_in},
# 3602 : : id{idIn},
# 3603 : : nLocalHostNonce{nLocalHostNonceIn},
# 3604 : : m_recv_flood_size{node_opts.recv_flood_size},
# 3605 : : m_i2p_sam_session{std::move(node_opts.i2p_sam_session)}
# 3606 : 1140 : {
# 3607 [ + + ]: 1140 : if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
# 3608 : :
# 3609 [ + + ]: 1140 : for (const std::string &msg : getAllNetMessageTypes())
# 3610 : 39900 : mapRecvBytesPerMsgType[msg] = 0;
# 3611 : 1140 : mapRecvBytesPerMsgType[NET_MESSAGE_TYPE_OTHER] = 0;
# 3612 : :
# 3613 [ + + ]: 1140 : if (fLogIPs) {
# 3614 [ + - ]: 2 : LogPrint(BCLog::NET, "Added connection to %s peer=%d\n", m_addr_name, id);
# 3615 : 1138 : } else {
# 3616 [ + - ]: 1138 : LogPrint(BCLog::NET, "Added connection peer=%d\n", id);
# 3617 : 1138 : }
# 3618 : 1140 : }
# 3619 : :
# 3620 : : void CNode::MarkReceivedMsgsForProcessing()
# 3621 : 113765 : {
# 3622 : 113765 : AssertLockNotHeld(m_msg_process_queue_mutex);
# 3623 : :
# 3624 : 113765 : size_t nSizeAdded = 0;
# 3625 [ + + ]: 126650 : for (const auto& msg : vRecvMsg) {
# 3626 : : // vRecvMsg contains only completed CNetMessage
# 3627 : : // the single possible partially deserialized message are held by TransportDeserializer
# 3628 : 126650 : nSizeAdded += msg.m_raw_message_size;
# 3629 : 126650 : }
# 3630 : :
# 3631 : 113765 : LOCK(m_msg_process_queue_mutex);
# 3632 : 113765 : m_msg_process_queue.splice(m_msg_process_queue.end(), vRecvMsg);
# 3633 : 113765 : m_msg_process_queue_size += nSizeAdded;
# 3634 : 113765 : fPauseRecv = m_msg_process_queue_size > m_recv_flood_size;
# 3635 : 113765 : }
# 3636 : :
# 3637 : : std::optional<std::pair<CNetMessage, bool>> CNode::PollMessage()
# 3638 : 264261 : {
# 3639 : 264261 : LOCK(m_msg_process_queue_mutex);
# 3640 [ + + ]: 264261 : if (m_msg_process_queue.empty()) return std::nullopt;
# 3641 : :
# 3642 : 122445 : std::list<CNetMessage> msgs;
# 3643 : : // Just take one message
# 3644 : 122445 : msgs.splice(msgs.begin(), m_msg_process_queue, m_msg_process_queue.begin());
# 3645 : 122445 : m_msg_process_queue_size -= msgs.front().m_raw_message_size;
# 3646 : 122445 : fPauseRecv = m_msg_process_queue_size > m_recv_flood_size;
# 3647 : :
# 3648 : 122445 : return std::make_pair(std::move(msgs.front()), !m_msg_process_queue.empty());
# 3649 : 264261 : }
# 3650 : :
# 3651 : : bool CConnman::NodeFullyConnected(const CNode* pnode)
# 3652 : 54527 : {
# 3653 [ + - ][ + + ]: 54527 : return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
# [ + + ]
# 3654 : 54527 : }
# 3655 : :
# 3656 : : void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
# 3657 : 130765 : {
# 3658 : 130765 : AssertLockNotHeld(m_total_bytes_sent_mutex);
# 3659 : 130765 : size_t nMessageSize = msg.data.size();
# 3660 [ + - ]: 130765 : LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", msg.m_type, nMessageSize, pnode->GetId());
# 3661 [ + + ]: 130765 : if (gArgs.GetBoolArg("-capturemessages", false)) {
# 3662 : 30 : CaptureMessage(pnode->addr, msg.m_type, msg.data, /*is_incoming=*/false);
# 3663 : 30 : }
# 3664 : :
# 3665 : 130765 : TRACE6(net, outbound_message,
# 3666 : 130765 : pnode->GetId(),
# 3667 : 130765 : pnode->m_addr_name.c_str(),
# 3668 : 130765 : pnode->ConnectionTypeAsString().c_str(),
# 3669 : 130765 : msg.m_type.c_str(),
# 3670 : 130765 : msg.data.size(),
# 3671 : 130765 : msg.data.data()
# 3672 : 130765 : );
# 3673 : :
# 3674 : 130765 : size_t nBytesSent = 0;
# 3675 : 130765 : {
# 3676 : 130765 : LOCK(pnode->cs_vSend);
# 3677 : : // Check if the transport still has unsent bytes, and indicate to it that we're about to
# 3678 : : // give it a message to send.
# 3679 : 130765 : const auto& [to_send, more, _msg_type] =
# 3680 : 130765 : pnode->m_transport->GetBytesToSend(/*have_next_message=*/true);
# 3681 [ + + ][ + - ]: 130765 : const bool queue_was_empty{to_send.empty() && pnode->vSendMsg.empty()};
# 3682 : :
# 3683 : : // Update memory usage of send buffer.
# 3684 : 130765 : pnode->m_send_memusage += msg.GetMemoryUsage();
# 3685 [ + + ]: 130765 : if (pnode->m_send_memusage + pnode->m_transport->GetSendMemoryUsage() > nSendBufferMaxSize) pnode->fPauseSend = true;
# 3686 : : // Move message to vSendMsg queue.
# 3687 : 130765 : pnode->vSendMsg.push_back(std::move(msg));
# 3688 : :
# 3689 : : // If there was nothing to send before, and there is now (predicted by the "more" value
# 3690 : : // returned by the GetBytesToSend call above), attempt "optimistic write":
# 3691 : : // because the poll/select loop may pause for SELECT_TIMEOUT_MILLISECONDS before actually
# 3692 : : // doing a send, try sending from the calling thread if the queue was empty before.
# 3693 : : // With a V1Transport, more will always be true here, because adding a message always
# 3694 : : // results in sendable bytes there, but with V2Transport this is not the case (it may
# 3695 : : // still be in the handshake).
# 3696 [ + + ][ + - ]: 130765 : if (queue_was_empty && more) {
# 3697 : 130731 : std::tie(nBytesSent, std::ignore) = SocketSendData(*pnode);
# 3698 : 130731 : }
# 3699 : 130765 : }
# 3700 [ + + ]: 130765 : if (nBytesSent) RecordBytesSent(nBytesSent);
# 3701 : 130765 : }
# 3702 : :
# 3703 : : bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
# 3704 : 269 : {
# 3705 : 269 : CNode* found = nullptr;
# 3706 : 269 : LOCK(m_nodes_mutex);
# 3707 [ + + ]: 464 : for (auto&& pnode : m_nodes) {
# 3708 [ + + ]: 464 : if(pnode->GetId() == id) {
# 3709 : 253 : found = pnode;
# 3710 : 253 : break;
# 3711 : 253 : }
# 3712 : 464 : }
# 3713 [ + + ][ + - ]: 269 : return found != nullptr && NodeFullyConnected(found) && func(found);
# [ + + ]
# 3714 : 269 : }
# 3715 : :
# 3716 : : CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const
# 3717 : 2853 : {
# 3718 : 2853 : return CSipHasher(nSeed0, nSeed1).Write(id);
# 3719 : 2853 : }
# 3720 : :
# 3721 : : uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& address) const
# 3722 : 1072 : {
# 3723 : 1072 : std::vector<unsigned char> vchNetGroup(m_netgroupman.GetGroup(address));
# 3724 : :
# 3725 : 1072 : return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup).Finalize();
# 3726 : 1072 : }
# 3727 : :
# 3728 : : void CaptureMessageToFile(const CAddress& addr,
# 3729 : : const std::string& msg_type,
# 3730 : : Span<const unsigned char> data,
# 3731 : : bool is_incoming)
# 3732 : 29 : {
# 3733 : : // Note: This function captures the message at the time of processing,
# 3734 : : // not at socket receive/send time.
# 3735 : : // This ensures that the messages are always in order from an application
# 3736 : : // layer (processing) perspective.
# 3737 : 29 : auto now = GetTime<std::chrono::microseconds>();
# 3738 : :
# 3739 : : // Windows folder names cannot include a colon
# 3740 : 29 : std::string clean_addr = addr.ToStringAddrPort();
# 3741 : 29 : std::replace(clean_addr.begin(), clean_addr.end(), ':', '_');
# 3742 : :
# 3743 : 29 : fs::path base_path = gArgs.GetDataDirNet() / "message_capture" / fs::u8path(clean_addr);
# 3744 : 29 : fs::create_directories(base_path);
# 3745 : :
# 3746 [ + + ]: 29 : fs::path path = base_path / (is_incoming ? "msgs_recv.dat" : "msgs_sent.dat");
# 3747 : 29 : AutoFile f{fsbridge::fopen(path, "ab")};
# 3748 : :
# 3749 : 29 : ser_writedata64(f, now.count());
# 3750 : 29 : f << Span{msg_type};
# 3751 [ + + ]: 164 : for (auto i = msg_type.length(); i < CMessageHeader::COMMAND_SIZE; ++i) {
# 3752 : 135 : f << uint8_t{'\0'};
# 3753 : 135 : }
# 3754 : 29 : uint32_t size = data.size();
# 3755 : 29 : ser_writedata32(f, size);
# 3756 : 29 : f << data;
# 3757 : 29 : }
# 3758 : :
# 3759 : : std::function<void(const CAddress& addr,
# 3760 : : const std::string& msg_type,
# 3761 : : Span<const unsigned char> data,
# 3762 : : bool is_incoming)>
# 3763 : : CaptureMessage = CaptureMessageToFile;
|