LCOV - code coverage report
Current view: top level - src - net.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 2152 2459 87.5 %
Date: 2023-09-07 14:00:19 Functions: 142 149 95.3 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 934 1318 70.9 %

           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;

Generated by: LCOV version 3.1-eol-3983-g6fec45e53af6