LCOV - code coverage report
Current view: top level - src - net.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 1687 2042 82.6 %
Date: 2021-06-29 14:35:33 Functions: 132 139 95.0 %
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: 704 1060 66.4 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2                 :            : // Copyright (c) 2009-2020 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 <banman.h>
#      13                 :            : #include <clientversion.h>
#      14                 :            : #include <compat.h>
#      15                 :            : #include <consensus/consensus.h>
#      16                 :            : #include <crypto/sha256.h>
#      17                 :            : #include <i2p.h>
#      18                 :            : #include <net_permissions.h>
#      19                 :            : #include <netaddress.h>
#      20                 :            : #include <netbase.h>
#      21                 :            : #include <node/ui_interface.h>
#      22                 :            : #include <protocol.h>
#      23                 :            : #include <random.h>
#      24                 :            : #include <scheduler.h>
#      25                 :            : #include <util/sock.h>
#      26                 :            : #include <util/strencodings.h>
#      27                 :            : #include <util/thread.h>
#      28                 :            : #include <util/translation.h>
#      29                 :            : 
#      30                 :            : #ifdef WIN32
#      31                 :            : #include <string.h>
#      32                 :            : #else
#      33                 :            : #include <fcntl.h>
#      34                 :            : #endif
#      35                 :            : 
#      36                 :            : #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
#      37                 :            : #include <ifaddrs.h>
#      38                 :            : #endif
#      39                 :            : 
#      40                 :            : #ifdef USE_POLL
#      41                 :            : #include <poll.h>
#      42                 :            : #endif
#      43                 :            : 
#      44                 :            : #include <algorithm>
#      45                 :            : #include <cstdint>
#      46                 :            : #include <functional>
#      47                 :            : #include <optional>
#      48                 :            : #include <unordered_map>
#      49                 :            : 
#      50                 :            : #include <math.h>
#      51                 :            : 
#      52                 :            : /** Maximum number of block-relay-only anchor connections */
#      53                 :            : static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS = 2;
#      54                 :            : 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.");
#      55                 :            : /** Anchor IP address database file name */
#      56                 :            : const char* const ANCHORS_DATABASE_FILENAME = "anchors.dat";
#      57                 :            : 
#      58                 :            : // How often to dump addresses to peers.dat
#      59                 :            : static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15};
#      60                 :            : 
#      61                 :            : /** Number of DNS seeds to query when the number of connections is low. */
#      62                 :            : static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
#      63                 :            : 
#      64                 :            : /** How long to delay before querying DNS seeds
#      65                 :            :  *
#      66                 :            :  * If we have more than THRESHOLD entries in addrman, then it's likely
#      67                 :            :  * that we got those addresses from having previously connected to the P2P
#      68                 :            :  * network, and that we'll be able to successfully reconnect to the P2P
#      69                 :            :  * network via contacting one of them. So if that's the case, spend a
#      70                 :            :  * little longer trying to connect to known peers before querying the
#      71                 :            :  * DNS seeds.
#      72                 :            :  */
#      73                 :            : static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11};
#      74                 :            : static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS{5};
#      75                 :            : static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers
#      76                 :            : 
#      77                 :            : /** The default timeframe for -maxuploadtarget. 1 day. */
#      78                 :            : static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME{60 * 60 * 24};
#      79                 :            : 
#      80                 :            : // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
#      81                 :          0 : #define FEELER_SLEEP_WINDOW 1
#      82                 :            : 
#      83                 :            : /** Used to pass flags to the Bind() function */
#      84                 :            : enum BindFlags {
#      85                 :            :     BF_NONE         = 0,
#      86                 :            :     BF_EXPLICIT     = (1U << 0),
#      87                 :            :     BF_REPORT_ERROR = (1U << 1),
#      88                 :            :     /**
#      89                 :            :      * Do not call AddLocal() for our special addresses, e.g., for incoming
#      90                 :            :      * Tor connections, to prevent gossiping them over the network.
#      91                 :            :      */
#      92                 :            :     BF_DONT_ADVERTISE = (1U << 2),
#      93                 :            : };
#      94                 :            : 
#      95                 :            : // The set of sockets cannot be modified while waiting
#      96                 :            : // The sleep time needs to be small to avoid new sockets stalling
#      97                 :            : static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
#      98                 :            : 
#      99                 :            : const std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
#     100                 :            : 
#     101                 :            : static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
#     102                 :            : static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
#     103                 :            : static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256("addrcache")[0:8]
#     104                 :            : //
#     105                 :            : // Global state variables
#     106                 :            : //
#     107                 :            : bool fDiscover = true;
#     108                 :            : bool fListen = true;
#     109                 :            : RecursiveMutex cs_mapLocalHost;
#     110                 :            : std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
#     111                 :            : static bool vfLimited[NET_MAX] GUARDED_BY(cs_mapLocalHost) = {};
#     112                 :            : std::string strSubVersion;
#     113                 :            : 
#     114                 :            : void CConnman::AddAddrFetch(const std::string& strDest)
#     115                 :          0 : {
#     116                 :          0 :     LOCK(m_addr_fetches_mutex);
#     117                 :          0 :     m_addr_fetches.push_back(strDest);
#     118                 :          0 : }
#     119                 :            : 
#     120                 :            : uint16_t GetListenPort()
#     121                 :       1729 : {
#     122                 :       1729 :     return static_cast<uint16_t>(gArgs.GetArg("-port", Params().GetDefaultPort()));
#     123                 :       1729 : }
#     124                 :            : 
#     125                 :            : // find 'best' local address for a particular peer
#     126                 :            : bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
#     127                 :       1099 : {
#     128         [ -  + ]:       1099 :     if (!fListen)
#     129                 :          0 :         return false;
#     130                 :            : 
#     131                 :       1099 :     int nBestScore = -1;
#     132                 :       1099 :     int nBestReachability = -1;
#     133                 :       1099 :     {
#     134                 :       1099 :         LOCK(cs_mapLocalHost);
#     135         [ +  + ]:       1099 :         for (const auto& entry : mapLocalHost)
#     136                 :          2 :         {
#     137                 :          2 :             int nScore = entry.second.nScore;
#     138                 :          2 :             int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
#     139 [ +  - ][ #  # ]:          2 :             if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
#                 [ #  # ]
#     140                 :          2 :             {
#     141                 :          2 :                 addr = CService(entry.first, entry.second.nPort);
#     142                 :          2 :                 nBestReachability = nReachability;
#     143                 :          2 :                 nBestScore = nScore;
#     144                 :          2 :             }
#     145                 :          2 :         }
#     146                 :       1099 :     }
#     147                 :       1099 :     return nBestScore >= 0;
#     148                 :       1099 : }
#     149                 :            : 
#     150                 :            : //! Convert the serialized seeds into usable address objects.
#     151                 :            : static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
#     152                 :          3 : {
#     153                 :            :     // It'll only connect to one or two seed nodes because once it connects,
#     154                 :            :     // it'll get a pile of addresses with newer timestamps.
#     155                 :            :     // Seed nodes are given a random 'last seen time' of between one and two
#     156                 :            :     // weeks ago.
#     157                 :          3 :     const int64_t nOneWeek = 7*24*60*60;
#     158                 :          3 :     std::vector<CAddress> vSeedsOut;
#     159                 :          3 :     FastRandomContext rng;
#     160                 :          3 :     CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
#     161         [ -  + ]:          3 :     while (!s.eof()) {
#     162                 :          0 :         CService endpoint;
#     163                 :          0 :         s >> endpoint;
#     164                 :          0 :         CAddress addr{endpoint, GetDesirableServiceFlags(NODE_NONE)};
#     165                 :          0 :         addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
#     166         [ #  # ]:          0 :         LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToString());
#     167                 :          0 :         vSeedsOut.push_back(addr);
#     168                 :          0 :     }
#     169                 :          3 :     return vSeedsOut;
#     170                 :          3 : }
#     171                 :            : 
#     172                 :            : // get best local address for a particular peer as a CAddress
#     173                 :            : // Otherwise, return the unroutable 0.0.0.0 but filled in with
#     174                 :            : // the normal parameters, since the IP may be changed to a useful
#     175                 :            : // one by discovery.
#     176                 :            : CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
#     177                 :       1099 : {
#     178                 :       1099 :     CAddress ret(CService(CNetAddr(),GetListenPort()), nLocalServices);
#     179                 :       1099 :     CService addr;
#     180         [ +  + ]:       1099 :     if (GetLocal(addr, paddrPeer))
#     181                 :          2 :     {
#     182                 :          2 :         ret = CAddress(addr, nLocalServices);
#     183                 :          2 :     }
#     184                 :       1099 :     ret.nTime = GetAdjustedTime();
#     185                 :       1099 :     return ret;
#     186                 :       1099 : }
#     187                 :            : 
#     188                 :            : static int GetnScore(const CService& addr)
#     189                 :          0 : {
#     190                 :          0 :     LOCK(cs_mapLocalHost);
#     191         [ #  # ]:          0 :     if (mapLocalHost.count(addr) == 0) return 0;
#     192                 :          0 :     return mapLocalHost[addr].nScore;
#     193                 :          0 : }
#     194                 :            : 
#     195                 :            : // Is our peer's addrLocal potentially useful as an external IP source?
#     196                 :            : bool IsPeerAddrLocalGood(CNode *pnode)
#     197                 :       1099 : {
#     198                 :       1099 :     CService addrLocal = pnode->GetAddrLocal();
#     199 [ +  + ][ +  - ]:       1099 :     return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
#                 [ +  - ]
#     200         [ +  - ]:       1099 :            IsReachable(addrLocal.GetNetwork());
#     201                 :       1099 : }
#     202                 :            : 
#     203                 :            : std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
#     204                 :        884 : {
#     205                 :        884 :     CAddress addrLocal = GetLocalAddress(&pnode->addr, pnode->GetLocalServices());
#     206         [ +  + ]:        884 :     if (gArgs.GetBoolArg("-addrmantest", false)) {
#     207                 :            :         // use IPv4 loopback during addrmantest
#     208                 :          5 :         addrLocal = CAddress(CService(LookupNumeric("127.0.0.1", GetListenPort())), pnode->GetLocalServices());
#     209                 :          5 :     }
#     210                 :            :     // If discovery is enabled, sometimes give our peer the address it
#     211                 :            :     // tells us that it sees us as in case it has a better idea of our
#     212                 :            :     // address than we do.
#     213                 :        884 :     FastRandomContext rng;
#     214 [ +  + ][ +  - ]:        884 :     if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
#     215 [ #  # ][ #  # ]:          2 :          rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0))
#     216                 :          2 :     {
#     217                 :          2 :         addrLocal.SetIP(pnode->GetAddrLocal());
#     218                 :          2 :     }
#     219 [ +  + ][ +  + ]:        884 :     if (addrLocal.IsRoutable() || gArgs.GetBoolArg("-addrmantest", false))
#                 [ +  + ]
#     220                 :          7 :     {
#     221         [ +  - ]:          7 :         LogPrint(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToString(), pnode->GetId());
#     222                 :          7 :         return addrLocal;
#     223                 :          7 :     }
#     224                 :            :     // Address is unroutable. Don't advertise.
#     225                 :        877 :     return std::nullopt;
#     226                 :        877 : }
#     227                 :            : 
#     228                 :            : // learn a new local address
#     229                 :            : bool AddLocal(const CService& addr, int nScore)
#     230                 :          2 : {
#     231         [ -  + ]:          2 :     if (!addr.IsRoutable())
#     232                 :          0 :         return false;
#     233                 :            : 
#     234 [ -  + ][ #  # ]:          2 :     if (!fDiscover && nScore < LOCAL_MANUAL)
#     235                 :          0 :         return false;
#     236                 :            : 
#     237         [ -  + ]:          2 :     if (!IsReachable(addr))
#     238                 :          0 :         return false;
#     239                 :            : 
#     240                 :          2 :     LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
#     241                 :            : 
#     242                 :          2 :     {
#     243                 :          2 :         LOCK(cs_mapLocalHost);
#     244                 :          2 :         bool fAlready = mapLocalHost.count(addr) > 0;
#     245                 :          2 :         LocalServiceInfo &info = mapLocalHost[addr];
#     246 [ +  - ][ #  # ]:          2 :         if (!fAlready || nScore >= info.nScore) {
#     247         [ -  + ]:          2 :             info.nScore = nScore + (fAlready ? 1 : 0);
#     248                 :          2 :             info.nPort = addr.GetPort();
#     249                 :          2 :         }
#     250                 :          2 :     }
#     251                 :            : 
#     252                 :          2 :     return true;
#     253                 :          2 : }
#     254                 :            : 
#     255                 :            : bool AddLocal(const CNetAddr &addr, int nScore)
#     256                 :          0 : {
#     257                 :          0 :     return AddLocal(CService(addr, GetListenPort()), nScore);
#     258                 :          0 : }
#     259                 :            : 
#     260                 :            : void RemoveLocal(const CService& addr)
#     261                 :          2 : {
#     262                 :          2 :     LOCK(cs_mapLocalHost);
#     263                 :          2 :     LogPrintf("RemoveLocal(%s)\n", addr.ToString());
#     264                 :          2 :     mapLocalHost.erase(addr);
#     265                 :          2 : }
#     266                 :            : 
#     267                 :            : void SetReachable(enum Network net, bool reachable)
#     268                 :       1276 : {
#     269 [ +  + ][ +  + ]:       1276 :     if (net == NET_UNROUTABLE || net == NET_INTERNAL)
#     270                 :          4 :         return;
#     271                 :       1272 :     LOCK(cs_mapLocalHost);
#     272                 :       1272 :     vfLimited[net] = !reachable;
#     273                 :       1272 : }
#     274                 :            : 
#     275                 :            : bool IsReachable(enum Network net)
#     276                 :      13196 : {
#     277                 :      13196 :     LOCK(cs_mapLocalHost);
#     278                 :      13196 :     return !vfLimited[net];
#     279                 :      13196 : }
#     280                 :            : 
#     281                 :            : bool IsReachable(const CNetAddr &addr)
#     282                 :      12696 : {
#     283                 :      12696 :     return IsReachable(addr.GetNetwork());
#     284                 :      12696 : }
#     285                 :            : 
#     286                 :            : /** vote for a local address */
#     287                 :            : bool SeenLocal(const CService& addr)
#     288                 :          0 : {
#     289                 :          0 :     {
#     290                 :          0 :         LOCK(cs_mapLocalHost);
#     291         [ #  # ]:          0 :         if (mapLocalHost.count(addr) == 0)
#     292                 :          0 :             return false;
#     293                 :          0 :         mapLocalHost[addr].nScore++;
#     294                 :          0 :     }
#     295                 :          0 :     return true;
#     296                 :          0 : }
#     297                 :            : 
#     298                 :            : 
#     299                 :            : /** check whether a given address is potentially local */
#     300                 :            : bool IsLocal(const CService& addr)
#     301                 :      13026 : {
#     302                 :      13026 :     LOCK(cs_mapLocalHost);
#     303                 :      13026 :     return mapLocalHost.count(addr) > 0;
#     304                 :      13026 : }
#     305                 :            : 
#     306                 :            : CNode* CConnman::FindNode(const CNetAddr& ip)
#     307                 :        182 : {
#     308                 :        182 :     LOCK(cs_vNodes);
#     309         [ +  + ]:        281 :     for (CNode* pnode : vNodes) {
#     310         [ -  + ]:        281 :       if (static_cast<CNetAddr>(pnode->addr) == ip) {
#     311                 :          0 :             return pnode;
#     312                 :          0 :         }
#     313                 :        281 :     }
#     314                 :        182 :     return nullptr;
#     315                 :        182 : }
#     316                 :            : 
#     317                 :            : CNode* CConnman::FindNode(const CSubNet& subNet)
#     318                 :          0 : {
#     319                 :          0 :     LOCK(cs_vNodes);
#     320         [ #  # ]:          0 :     for (CNode* pnode : vNodes) {
#     321         [ #  # ]:          0 :         if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
#     322                 :          0 :             return pnode;
#     323                 :          0 :         }
#     324                 :          0 :     }
#     325                 :          0 :     return nullptr;
#     326                 :          0 : }
#     327                 :            : 
#     328                 :            : CNode* CConnman::FindNode(const std::string& addrName)
#     329                 :        553 : {
#     330                 :        553 :     LOCK(cs_vNodes);
#     331         [ +  + ]:        649 :     for (CNode* pnode : vNodes) {
#     332         [ +  + ]:        649 :         if (pnode->GetAddrName() == addrName) {
#     333                 :          1 :             return pnode;
#     334                 :          1 :         }
#     335                 :        649 :     }
#     336                 :        553 :     return nullptr;
#     337                 :        553 : }
#     338                 :            : 
#     339                 :            : CNode* CConnman::FindNode(const CService& addr)
#     340                 :        545 : {
#     341                 :        545 :     LOCK(cs_vNodes);
#     342         [ +  + ]:        633 :     for (CNode* pnode : vNodes) {
#     343         [ -  + ]:        633 :         if (static_cast<CService>(pnode->addr) == addr) {
#     344                 :          0 :             return pnode;
#     345                 :          0 :         }
#     346                 :        633 :     }
#     347                 :        545 :     return nullptr;
#     348                 :        545 : }
#     349                 :            : 
#     350                 :            : bool CConnman::AlreadyConnectedToAddress(const CAddress& addr)
#     351                 :        182 : {
#     352 [ -  + ][ -  + ]:        182 :     return FindNode(static_cast<CNetAddr>(addr)) || FindNode(addr.ToStringIPPort());
#     353                 :        182 : }
#     354                 :            : 
#     355                 :            : bool CConnman::CheckIncomingNonce(uint64_t nonce)
#     356                 :        606 : {
#     357                 :        606 :     LOCK(cs_vNodes);
#     358         [ +  + ]:       1511 :     for (const CNode* pnode : vNodes) {
#     359 [ +  + ][ -  + ]:       1511 :         if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() == nonce)
#                 [ #  # ]
#     360                 :          0 :             return false;
#     361                 :       1511 :     }
#     362                 :        606 :     return true;
#     363                 :        606 : }
#     364                 :            : 
#     365                 :            : /** Get the bind address for a socket as CAddress */
#     366                 :            : static CAddress GetBindAddress(SOCKET sock)
#     367                 :        977 : {
#     368                 :        977 :     CAddress addr_bind;
#     369                 :        977 :     struct sockaddr_storage sockaddr_bind;
#     370                 :        977 :     socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
#     371         [ +  - ]:        977 :     if (sock != INVALID_SOCKET) {
#     372         [ +  - ]:        977 :         if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
#     373                 :        977 :             addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
#     374                 :        977 :         } else {
#     375         [ #  # ]:          0 :             LogPrint(BCLog::NET, "Warning: getsockname failed\n");
#     376                 :          0 :         }
#     377                 :        977 :     }
#     378                 :        977 :     return addr_bind;
#     379                 :        977 : }
#     380                 :            : 
#     381                 :            : CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type)
#     382                 :        551 : {
#     383                 :        551 :     assert(conn_type != ConnectionType::INBOUND);
#     384                 :            : 
#     385         [ +  + ]:        551 :     if (pszDest == nullptr) {
#     386         [ -  + ]:        182 :         if (IsLocal(addrConnect))
#     387                 :          0 :             return nullptr;
#     388                 :            : 
#     389                 :            :         // Look for an existing connection
#     390                 :        182 :         CNode* pnode = FindNode(static_cast<CService>(addrConnect));
#     391         [ -  + ]:        182 :         if (pnode)
#     392                 :          0 :         {
#     393                 :          0 :             LogPrintf("Failed to open new connection, already connected\n");
#     394                 :          0 :             return nullptr;
#     395                 :          0 :         }
#     396                 :        551 :     }
#     397                 :            : 
#     398                 :            :     /// debug print
#     399 [ +  - ][ +  + ]:        551 :     LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n",
#                 [ +  + ]
#     400                 :        551 :         pszDest ? pszDest : addrConnect.ToString(),
#     401                 :        551 :         pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
#     402                 :            : 
#     403                 :            :     // Resolve
#     404                 :        551 :     const uint16_t default_port{Params().GetDefaultPort()};
#     405         [ +  + ]:        551 :     if (pszDest) {
#     406                 :        369 :         std::vector<CService> resolved;
#     407 [ +  + ][ +  + ]:        369 :         if (Lookup(pszDest, resolved,  default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
#         [ +  - ][ +  + ]
#                 [ +  - ]
#     408                 :        363 :             addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
#     409         [ -  + ]:        363 :             if (!addrConnect.IsValid()) {
#     410         [ #  # ]:          0 :                 LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
#     411                 :          0 :                 return nullptr;
#     412                 :          0 :             }
#     413                 :            :             // It is possible that we already have a connection to the IP/port pszDest resolved to.
#     414                 :            :             // In that case, drop the connection that was just created, and return the existing CNode instead.
#     415                 :            :             // Also store the name we used to connect in that CNode, so that future FindNode() calls to that
#     416                 :            :             // name catch this early.
#     417                 :        363 :             LOCK(cs_vNodes);
#     418                 :        363 :             CNode* pnode = FindNode(static_cast<CService>(addrConnect));
#     419         [ -  + ]:        363 :             if (pnode)
#     420                 :          0 :             {
#     421                 :          0 :                 pnode->MaybeSetAddrName(std::string(pszDest));
#     422                 :          0 :                 LogPrintf("Failed to open new connection, already connected\n");
#     423                 :          0 :                 return nullptr;
#     424                 :          0 :             }
#     425                 :        551 :         }
#     426                 :        369 :     }
#     427                 :            : 
#     428                 :            :     // Connect
#     429                 :        551 :     bool connected = false;
#     430                 :        551 :     std::unique_ptr<Sock> sock;
#     431                 :        551 :     proxyType proxy;
#     432                 :        551 :     CAddress addr_bind;
#     433                 :        551 :     assert(!addr_bind.IsValid());
#     434                 :            : 
#     435         [ +  + ]:        551 :     if (addrConnect.IsValid()) {
#     436                 :        545 :         bool proxyConnectionFailed = false;
#     437                 :            : 
#     438 [ +  + ][ +  - ]:        545 :         if (addrConnect.GetNetwork() == NET_I2P && m_i2p_sam_session.get() != nullptr) {
#     439                 :          2 :             i2p::Connection conn;
#     440         [ -  + ]:          2 :             if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) {
#     441                 :          0 :                 connected = true;
#     442                 :          0 :                 sock = std::move(conn.sock);
#     443                 :          0 :                 addr_bind = CAddress{conn.me, NODE_NONE};
#     444                 :          0 :             }
#     445         [ +  + ]:        543 :         } else if (GetProxy(addrConnect.GetNetwork(), proxy)) {
#     446                 :         11 :             sock = CreateSock(proxy.proxy);
#     447         [ -  + ]:         11 :             if (!sock) {
#     448                 :          0 :                 return nullptr;
#     449                 :          0 :             }
#     450                 :         11 :             connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(),
#     451                 :         11 :                                             *sock, nConnectTimeout, proxyConnectionFailed);
#     452                 :        532 :         } else {
#     453                 :            :             // no proxy needed (none set for target network)
#     454                 :        532 :             sock = CreateSock(addrConnect);
#     455         [ -  + ]:        532 :             if (!sock) {
#     456                 :          0 :                 return nullptr;
#     457                 :          0 :             }
#     458                 :        532 :             connected = ConnectSocketDirectly(addrConnect, *sock, nConnectTimeout,
#     459                 :        532 :                                               conn_type == ConnectionType::MANUAL);
#     460                 :        532 :         }
#     461         [ +  + ]:        545 :         if (!proxyConnectionFailed) {
#     462                 :            :             // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
#     463                 :            :             // the proxy, mark this as an attempt.
#     464                 :        544 :             addrman.Attempt(addrConnect, fCountFailure);
#     465                 :        544 :         }
#     466 [ +  - ][ +  + ]:        545 :     } else if (pszDest && GetNameProxy(proxy)) {
#     467                 :          4 :         sock = CreateSock(proxy.proxy);
#     468         [ -  + ]:          4 :         if (!sock) {
#     469                 :          0 :             return nullptr;
#     470                 :          0 :         }
#     471                 :          4 :         std::string host;
#     472                 :          4 :         uint16_t port{default_port};
#     473                 :          4 :         SplitHostPort(std::string(pszDest), port, host);
#     474                 :          4 :         bool proxyConnectionFailed;
#     475                 :          4 :         connected = ConnectThroughProxy(proxy, host, port, *sock, nConnectTimeout,
#     476                 :          4 :                                         proxyConnectionFailed);
#     477                 :          4 :     }
#     478         [ +  + ]:        551 :     if (!connected) {
#     479                 :        187 :         return nullptr;
#     480                 :        187 :     }
#     481                 :            : 
#     482                 :            :     // Add node
#     483                 :        364 :     NodeId id = GetNewNodeId();
#     484                 :        364 :     uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
#     485         [ +  - ]:        364 :     if (!addr_bind.IsValid()) {
#     486                 :        364 :         addr_bind = GetBindAddress(sock->Get());
#     487                 :        364 :     }
#     488         [ +  - ]:        364 :     CNode* pnode = new CNode(id, nLocalServices, sock->Release(), addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type, /* inbound_onion */ false);
#     489                 :        364 :     pnode->AddRef();
#     490                 :            : 
#     491                 :            :     // We're making a new connection, harvest entropy from the time (and our peer count)
#     492                 :        364 :     RandAddEvent((uint32_t)id);
#     493                 :            : 
#     494                 :        364 :     return pnode;
#     495                 :        364 : }
#     496                 :            : 
#     497                 :            : void CNode::CloseSocketDisconnect()
#     498                 :       1167 : {
#     499                 :       1167 :     fDisconnect = true;
#     500                 :       1167 :     LOCK(cs_hSocket);
#     501         [ +  + ]:       1167 :     if (hSocket != INVALID_SOCKET)
#     502                 :       1167 :     {
#     503         [ +  - ]:        976 :         LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
#     504                 :        976 :         CloseSocket(hSocket);
#     505                 :        976 :     }
#     506                 :       1167 : }
#     507                 :            : 
#     508                 :        613 : void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const {
#     509         [ +  + ]:        613 :     for (const auto& subnet : vWhitelistedRange) {
#     510         [ +  - ]:        105 :         if (subnet.m_subnet.Match(addr)) NetPermissions::AddFlag(flags, subnet.m_flags);
#     511                 :        105 :     }
#     512                 :        613 : }
#     513                 :            : 
#     514                 :            : std::string ConnectionTypeAsString(ConnectionType conn_type)
#     515                 :      10007 : {
#     516         [ -  + ]:      10007 :     switch (conn_type) {
#     517         [ +  + ]:       4833 :     case ConnectionType::INBOUND:
#     518                 :       4833 :         return "inbound";
#     519         [ +  + ]:       5087 :     case ConnectionType::MANUAL:
#     520                 :       5087 :         return "manual";
#     521         [ -  + ]:          0 :     case ConnectionType::FEELER:
#     522                 :          0 :         return "feeler";
#     523         [ +  + ]:         43 :     case ConnectionType::OUTBOUND_FULL_RELAY:
#     524                 :         43 :         return "outbound-full-relay";
#     525         [ +  + ]:         44 :     case ConnectionType::BLOCK_RELAY:
#     526                 :         44 :         return "block-relay-only";
#     527         [ -  + ]:          0 :     case ConnectionType::ADDR_FETCH:
#     528                 :          0 :         return "addr-fetch";
#     529                 :          0 :     } // no default case, so the compiler can warn about missing cases
#     530                 :            : 
#     531                 :          0 :     assert(false);
#     532                 :          0 : }
#     533                 :            : 
#     534                 :      20355 : std::string CNode::GetAddrName() const {
#     535                 :      20355 :     LOCK(cs_addrName);
#     536                 :      20355 :     return addrName;
#     537                 :      20355 : }
#     538                 :            : 
#     539                 :          0 : void CNode::MaybeSetAddrName(const std::string& addrNameIn) {
#     540                 :          0 :     LOCK(cs_addrName);
#     541         [ #  # ]:          0 :     if (addrName.empty()) {
#     542                 :          0 :         addrName = addrNameIn;
#     543                 :          0 :     }
#     544                 :          0 : }
#     545                 :            : 
#     546                 :      10759 : CService CNode::GetAddrLocal() const {
#     547                 :      10759 :     LOCK(cs_addrLocal);
#     548                 :      10759 :     return addrLocal;
#     549                 :      10759 : }
#     550                 :            : 
#     551                 :        954 : void CNode::SetAddrLocal(const CService& addrLocalIn) {
#     552                 :        954 :     LOCK(cs_addrLocal);
#     553         [ -  + ]:        954 :     if (addrLocal.IsValid()) {
#     554                 :          0 :         error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToString(), addrLocalIn.ToString());
#     555                 :        954 :     } else {
#     556                 :        954 :         addrLocal = addrLocalIn;
#     557                 :        954 :     }
#     558                 :        954 : }
#     559                 :            : 
#     560                 :            : Network CNode::ConnectedThroughNetwork() const
#     561                 :       9666 : {
#     562         [ +  + ]:       9666 :     return m_inbound_onion ? NET_ONION : addr.GetNetClass();
#     563                 :       9666 : }
#     564                 :            : 
#     565                 :            : #undef X
#     566                 :     202818 : #define X(name) stats.name = name
#     567                 :            : void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
#     568                 :       9658 : {
#     569                 :       9658 :     stats.nodeid = this->GetId();
#     570                 :       9658 :     X(nServices);
#     571                 :       9658 :     X(addr);
#     572                 :       9658 :     X(addrBind);
#     573                 :       9658 :     stats.m_network = ConnectedThroughNetwork();
#     574                 :       9658 :     stats.m_mapped_as = addr.GetMappedAS(m_asmap);
#     575         [ +  + ]:       9658 :     if (m_tx_relay != nullptr) {
#     576                 :       9630 :         LOCK(m_tx_relay->cs_filter);
#     577                 :       9630 :         stats.fRelayTxes = m_tx_relay->fRelayTxes;
#     578                 :       9630 :     } else {
#     579                 :         28 :         stats.fRelayTxes = false;
#     580                 :         28 :     }
#     581                 :       9658 :     X(nLastSend);
#     582                 :       9658 :     X(nLastRecv);
#     583                 :       9658 :     X(nLastTXTime);
#     584                 :       9658 :     X(nLastBlockTime);
#     585                 :       9658 :     X(nTimeConnected);
#     586                 :       9658 :     X(nTimeOffset);
#     587                 :       9658 :     stats.addrName = GetAddrName();
#     588                 :       9658 :     X(nVersion);
#     589                 :       9658 :     {
#     590                 :       9658 :         LOCK(cs_SubVer);
#     591                 :       9658 :         X(cleanSubVer);
#     592                 :       9658 :     }
#     593                 :       9658 :     stats.fInbound = IsInboundConn();
#     594                 :       9658 :     X(m_bip152_highbandwidth_to);
#     595                 :       9658 :     X(m_bip152_highbandwidth_from);
#     596                 :       9658 :     {
#     597                 :       9658 :         LOCK(cs_vSend);
#     598                 :       9658 :         X(mapSendBytesPerMsgCmd);
#     599                 :       9658 :         X(nSendBytes);
#     600                 :       9658 :     }
#     601                 :       9658 :     {
#     602                 :       9658 :         LOCK(cs_vRecv);
#     603                 :       9658 :         X(mapRecvBytesPerMsgCmd);
#     604                 :       9658 :         X(nRecvBytes);
#     605                 :       9658 :     }
#     606                 :       9658 :     X(m_permissionFlags);
#     607         [ +  + ]:       9658 :     if (m_tx_relay != nullptr) {
#     608                 :       9630 :         stats.minFeeFilter = m_tx_relay->minFeeFilter;
#     609                 :       9630 :     } else {
#     610                 :         28 :         stats.minFeeFilter = 0;
#     611                 :         28 :     }
#     612                 :            : 
#     613                 :       9658 :     X(m_last_ping_time);
#     614                 :       9658 :     X(m_min_ping_time);
#     615                 :            : 
#     616                 :            :     // Leave string empty if addrLocal invalid (not filled in yet)
#     617                 :       9658 :     CService addrLocalUnlocked = GetAddrLocal();
#     618         [ +  + ]:       9658 :     stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
#     619                 :            : 
#     620                 :       9658 :     X(m_conn_type);
#     621                 :       9658 : }
#     622                 :            : #undef X
#     623                 :            : 
#     624                 :            : bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete)
#     625                 :     130090 : {
#     626                 :     130090 :     complete = false;
#     627                 :     130090 :     const auto time = GetTime<std::chrono::microseconds>();
#     628                 :     130090 :     LOCK(cs_vRecv);
#     629                 :     130090 :     nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count();
#     630                 :     130090 :     nRecvBytes += msg_bytes.size();
#     631         [ +  + ]:     372716 :     while (msg_bytes.size() > 0) {
#     632                 :            :         // absorb network data
#     633                 :     242630 :         int handled = m_deserializer->Read(msg_bytes);
#     634         [ +  + ]:     242630 :         if (handled < 0) {
#     635                 :            :             // Serious header problem, disconnect from the peer.
#     636                 :          4 :             return false;
#     637                 :          4 :         }
#     638                 :            : 
#     639         [ +  + ]:     242626 :         if (m_deserializer->Complete()) {
#     640                 :            :             // decompose a transport agnostic CNetMessage from the deserializer
#     641                 :     111987 :             uint32_t out_err_raw_size{0};
#     642                 :     111987 :             std::optional<CNetMessage> result{m_deserializer->GetMessage(time, out_err_raw_size)};
#     643         [ +  + ]:     111987 :             if (!result) {
#     644                 :            :                 // Message deserialization failed.  Drop the message but don't disconnect the peer.
#     645                 :            :                 // store the size of the corrupt message
#     646                 :         82 :                 mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER)->second += out_err_raw_size;
#     647                 :         82 :                 continue;
#     648                 :         82 :             }
#     649                 :            : 
#     650                 :            :             //store received bytes per message command
#     651                 :            :             //to prevent a memory DOS, only allow valid commands
#     652                 :     111905 :             mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(result->m_command);
#     653         [ -  + ]:     111905 :             if (i == mapRecvBytesPerMsgCmd.end())
#     654                 :          0 :                 i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER);
#     655                 :     111905 :             assert(i != mapRecvBytesPerMsgCmd.end());
#     656                 :     111905 :             i->second += result->m_raw_message_size;
#     657                 :            : 
#     658                 :            :             // push the message to the process queue,
#     659                 :     111905 :             vRecvMsg.push_back(std::move(*result));
#     660                 :            : 
#     661                 :     111905 :             complete = true;
#     662                 :     111905 :         }
#     663                 :     242626 :     }
#     664                 :            : 
#     665                 :     130090 :     return true;
#     666                 :     130090 : }
#     667                 :            : 
#     668                 :            : int V1TransportDeserializer::readHeader(Span<const uint8_t> msg_bytes)
#     669                 :     111992 : {
#     670                 :            :     // copy data to temporary parsing buffer
#     671                 :     111992 :     unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos;
#     672                 :     111992 :     unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
#     673                 :            : 
#     674                 :     111992 :     memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy);
#     675                 :     111992 :     nHdrPos += nCopy;
#     676                 :            : 
#     677                 :            :     // if header incomplete, exit
#     678         [ +  + ]:     111992 :     if (nHdrPos < CMessageHeader::HEADER_SIZE)
#     679                 :          1 :         return nCopy;
#     680                 :            : 
#     681                 :            :     // deserialize to CMessageHeader
#     682                 :     111991 :     try {
#     683                 :     111991 :         hdrbuf >> hdr;
#     684                 :     111991 :     }
#     685                 :     111991 :     catch (const std::exception&) {
#     686         [ #  # ]:          0 :         LogPrint(BCLog::NET, "Header error: Unable to deserialize, peer=%d\n", m_node_id);
#     687                 :          0 :         return -1;
#     688                 :          0 :     }
#     689                 :            : 
#     690                 :            :     // Check start string, network magic
#     691         [ +  + ]:     111991 :     if (memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) {
#     692         [ +  - ]:          3 :         LogPrint(BCLog::NET, "Header error: Wrong MessageStart %s received, peer=%d\n", HexStr(hdr.pchMessageStart), m_node_id);
#     693                 :          3 :         return -1;
#     694                 :          3 :     }
#     695                 :            : 
#     696                 :            :     // reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH
#     697 [ -  + ][ +  + ]:     111988 :     if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
#     698         [ +  - ]:          1 :         LogPrint(BCLog::NET, "Header error: Size too large (%s, %u bytes), peer=%d\n", SanitizeString(hdr.GetCommand()), hdr.nMessageSize, m_node_id);
#     699                 :          1 :         return -1;
#     700                 :          1 :     }
#     701                 :            : 
#     702                 :            :     // switch state to reading message data
#     703                 :     111987 :     in_data = true;
#     704                 :            : 
#     705                 :     111987 :     return nCopy;
#     706                 :     111987 : }
#     707                 :            : 
#     708                 :            : int V1TransportDeserializer::readData(Span<const uint8_t> msg_bytes)
#     709                 :     130638 : {
#     710                 :     130638 :     unsigned int nRemaining = hdr.nMessageSize - nDataPos;
#     711                 :     130638 :     unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
#     712                 :            : 
#     713         [ +  + ]:     130638 :     if (vRecv.size() < nDataPos + nCopy) {
#     714                 :            :         // Allocate up to 256 KiB ahead, but never more than the total message size.
#     715                 :     112885 :         vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
#     716                 :     112885 :     }
#     717                 :            : 
#     718                 :     130638 :     hasher.Write(msg_bytes.first(nCopy));
#     719                 :     130638 :     memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy);
#     720                 :     130638 :     nDataPos += nCopy;
#     721                 :            : 
#     722                 :     130638 :     return nCopy;
#     723                 :     130638 : }
#     724                 :            : 
#     725                 :            : const uint256& V1TransportDeserializer::GetMessageHash() const
#     726                 :     111987 : {
#     727                 :     111987 :     assert(Complete());
#     728         [ +  - ]:     111987 :     if (data_hash.IsNull())
#     729                 :     111987 :         hasher.Finalize(data_hash);
#     730                 :     111987 :     return data_hash;
#     731                 :     111987 : }
#     732                 :            : 
#     733                 :            : std::optional<CNetMessage> V1TransportDeserializer::GetMessage(const std::chrono::microseconds time, uint32_t& out_err_raw_size)
#     734                 :     111987 : {
#     735                 :            :     // decompose a single CNetMessage from the TransportDeserializer
#     736                 :     111987 :     std::optional<CNetMessage> msg(std::move(vRecv));
#     737                 :            : 
#     738                 :            :     // store command string, time, and sizes
#     739                 :     111987 :     msg->m_command = hdr.GetCommand();
#     740                 :     111987 :     msg->m_time = time;
#     741                 :     111987 :     msg->m_message_size = hdr.nMessageSize;
#     742                 :     111987 :     msg->m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
#     743                 :            : 
#     744                 :     111987 :     uint256 hash = GetMessageHash();
#     745                 :            : 
#     746                 :            :     // We just received a message off the wire, harvest entropy from the time (and the message checksum)
#     747                 :     111987 :     RandAddEvent(ReadLE32(hash.begin()));
#     748                 :            : 
#     749                 :            :     // Check checksum and header command string
#     750         [ +  + ]:     111987 :     if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) {
#     751         [ +  - ]:          1 :         LogPrint(BCLog::NET, "Header error: Wrong checksum (%s, %u bytes), expected %s was %s, peer=%d\n",
#     752                 :          1 :                  SanitizeString(msg->m_command), msg->m_message_size,
#     753                 :          1 :                  HexStr(Span<uint8_t>(hash.begin(), hash.begin() + CMessageHeader::CHECKSUM_SIZE)),
#     754                 :          1 :                  HexStr(hdr.pchChecksum),
#     755                 :          1 :                  m_node_id);
#     756                 :          1 :         out_err_raw_size = msg->m_raw_message_size;
#     757                 :          1 :         msg = std::nullopt;
#     758         [ +  + ]:     111986 :     } else if (!hdr.IsCommandValid()) {
#     759         [ +  - ]:         81 :         LogPrint(BCLog::NET, "Header error: Invalid message type (%s, %u bytes), peer=%d\n",
#     760                 :         81 :                  SanitizeString(hdr.GetCommand()), msg->m_message_size, m_node_id);
#     761                 :         81 :         out_err_raw_size = msg->m_raw_message_size;
#     762                 :         81 :         msg.reset();
#     763                 :         81 :     }
#     764                 :            : 
#     765                 :            :     // Always reset the network deserializer (prepare for the next message)
#     766                 :     111987 :     Reset();
#     767                 :     111987 :     return msg;
#     768                 :     111987 : }
#     769                 :            : 
#     770                 :     117288 : void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) {
#     771                 :            :     // create dbl-sha256 checksum
#     772                 :     117288 :     uint256 hash = Hash(msg.data);
#     773                 :            : 
#     774                 :            :     // create header
#     775                 :     117288 :     CMessageHeader hdr(Params().MessageStart(), msg.m_type.c_str(), msg.data.size());
#     776                 :     117288 :     memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
#     777                 :            : 
#     778                 :            :     // serialize header
#     779                 :     117288 :     header.reserve(CMessageHeader::HEADER_SIZE);
#     780                 :     117288 :     CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, header, 0, hdr};
#     781                 :     117288 : }
#     782                 :            : 
#     783                 :            : size_t CConnman::SocketSendData(CNode& node) const
#     784                 :     117533 : {
#     785                 :     117533 :     auto it = node.vSendMsg.begin();
#     786                 :     117533 :     size_t nSentSize = 0;
#     787                 :            : 
#     788         [ +  + ]:     347898 :     while (it != node.vSendMsg.end()) {
#     789                 :     230757 :         const auto& data = *it;
#     790                 :     230757 :         assert(data.size() > node.nSendOffset);
#     791                 :     230757 :         int nBytes = 0;
#     792                 :     230757 :         {
#     793                 :     230757 :             LOCK(node.cs_hSocket);
#     794         [ +  + ]:     230757 :             if (node.hSocket == INVALID_SOCKET)
#     795                 :     230757 :                 break;
#     796                 :     230729 :             nBytes = send(node.hSocket, reinterpret_cast<const char*>(data.data()) + node.nSendOffset, data.size() - node.nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
#     797                 :     230729 :         }
#     798         [ +  + ]:     230729 :         if (nBytes > 0) {
#     799                 :     230728 :             node.nLastSend = GetSystemTimeInSeconds();
#     800                 :     230728 :             node.nSendBytes += nBytes;
#     801                 :     230728 :             node.nSendOffset += nBytes;
#     802                 :     230728 :             nSentSize += nBytes;
#     803         [ +  + ]:     230728 :             if (node.nSendOffset == data.size()) {
#     804                 :     230365 :                 node.nSendOffset = 0;
#     805                 :     230365 :                 node.nSendSize -= data.size();
#     806                 :     230365 :                 node.fPauseSend = node.nSendSize > nSendBufferMaxSize;
#     807                 :     230365 :                 it++;
#     808                 :     230365 :             } else {
#     809                 :            :                 // could not send full message; stop sending more
#     810                 :        363 :                 break;
#     811                 :        363 :             }
#     812                 :          1 :         } else {
#     813         [ +  - ]:          1 :             if (nBytes < 0) {
#     814                 :            :                 // error
#     815                 :          1 :                 int nErr = WSAGetLastError();
#     816 [ +  - ][ +  - ]:          1 :                 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) {
#         [ +  - ][ +  - ]
#     817         [ +  - ]:          1 :                     LogPrint(BCLog::NET, "socket send error for peer=%d: %s\n", node.GetId(), NetworkErrorString(nErr));
#     818                 :          1 :                     node.CloseSocketDisconnect();
#     819                 :          1 :                 }
#     820                 :          1 :             }
#     821                 :            :             // couldn't send anything at all
#     822                 :          1 :             break;
#     823                 :          1 :         }
#     824                 :     230729 :     }
#     825                 :            : 
#     826         [ +  + ]:     117533 :     if (it == node.vSendMsg.end()) {
#     827                 :     117141 :         assert(node.nSendOffset == 0);
#     828                 :     117141 :         assert(node.nSendSize == 0);
#     829                 :     117141 :     }
#     830                 :     117533 :     node.vSendMsg.erase(node.vSendMsg.begin(), it);
#     831                 :     117533 :     return nSentSize;
#     832                 :     117533 : }
#     833                 :            : 
#     834                 :            : static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#     835                 :   23366098 : {
#     836                 :   23366098 :     return a.m_min_ping_time > b.m_min_ping_time;
#     837                 :   23366098 : }
#     838                 :            : 
#     839                 :            : static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#     840                 :   15870316 : {
#     841                 :   15870316 :     return a.nTimeConnected > b.nTimeConnected;
#     842                 :   15870316 : }
#     843                 :            : 
#     844                 :            : static bool CompareLocalHostTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#     845                 :   13919124 : {
#     846         [ +  + ]:   13919124 :     if (a.m_is_local != b.m_is_local) return b.m_is_local;
#     847                 :   11648258 :     return a.nTimeConnected > b.nTimeConnected;
#     848                 :   11648258 : }
#     849                 :            : 
#     850                 :            : static bool CompareOnionTimeConnected(const NodeEvictionCandidate& a, const NodeEvictionCandidate& b)
#     851                 :   20456246 : {
#     852         [ +  + ]:   20456246 :     if (a.m_is_onion != b.m_is_onion) return b.m_is_onion;
#     853                 :   17198088 :     return a.nTimeConnected > b.nTimeConnected;
#     854                 :   17198088 : }
#     855                 :            : 
#     856                 :   27096216 : static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
#     857                 :   27096216 :     return a.nKeyedNetGroup < b.nKeyedNetGroup;
#     858                 :   27096216 : }
#     859                 :            : 
#     860                 :            : static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#     861                 :   25034772 : {
#     862                 :            :     // There is a fall-through here because it is common for a node to have many peers which have not yet relayed a block.
#     863         [ +  + ]:   25034772 :     if (a.nLastBlockTime != b.nLastBlockTime) return a.nLastBlockTime < b.nLastBlockTime;
#     864         [ +  + ]:     881197 :     if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
#     865                 :     556385 :     return a.nTimeConnected > b.nTimeConnected;
#     866                 :     556385 : }
#     867                 :            : 
#     868                 :            : static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#     869                 :   21890674 : {
#     870                 :            :     // There is a fall-through here because it is common for a node to have more than a few peers that have not yet relayed txn.
#     871         [ +  + ]:   21890674 :     if (a.nLastTXTime != b.nLastTXTime) return a.nLastTXTime < b.nLastTXTime;
#     872         [ +  + ]:    1284041 :     if (a.fRelayTxes != b.fRelayTxes) return b.fRelayTxes;
#     873         [ +  + ]:     739815 :     if (a.fBloomFilter != b.fBloomFilter) return a.fBloomFilter;
#     874                 :     441985 :     return a.nTimeConnected > b.nTimeConnected;
#     875                 :     441985 : }
#     876                 :            : 
#     877                 :            : // Pick out the potential block-relay only peers, and sort them by last block time.
#     878                 :            : static bool CompareNodeBlockRelayOnlyTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
#     879                 :   22989734 : {
#     880         [ +  + ]:   22989734 :     if (a.fRelayTxes != b.fRelayTxes) return a.fRelayTxes;
#     881         [ +  + ]:   19513356 :     if (a.nLastBlockTime != b.nLastBlockTime) return a.nLastBlockTime < b.nLastBlockTime;
#     882         [ +  + ]:     511665 :     if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
#     883                 :     326445 :     return a.nTimeConnected > b.nTimeConnected;
#     884                 :     326445 : }
#     885                 :            : 
#     886                 :            : //! Sort an array by the specified comparator, then erase the last K elements where predicate is true.
#     887                 :            : template <typename T, typename Comparator>
#     888                 :            : static void EraseLastKElements(
#     889                 :            :     std::vector<T>& elements, Comparator comparator, size_t k,
#     890                 :    1162632 :     std::function<bool(const NodeEvictionCandidate&)> predicate = [](const NodeEvictionCandidate& n) { return true; })
#     891                 :     245596 : {
#     892                 :     245596 :     std::sort(elements.begin(), elements.end(), comparator);
#     893                 :     245596 :     size_t eraseSize = std::min(k, elements.size());
#     894                 :     245596 :     elements.erase(std::remove_if(elements.end() - eraseSize, elements.end(), predicate), elements.end());
#     895                 :     245596 : }
#     896                 :            : 
#     897                 :            : void ProtectEvictionCandidatesByRatio(std::vector<NodeEvictionCandidate>& vEvictionCandidates)
#     898                 :      31865 : {
#     899                 :            :     // Protect the half of the remaining nodes which have been connected the longest.
#     900                 :            :     // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
#     901                 :            :     // To favorise the diversity of our peer connections, reserve up to (half + 2) of
#     902                 :            :     // these protected spots for onion and localhost peers, if any, even if they're not
#     903                 :            :     // longest uptime overall. This helps protect tor peers, which tend to be otherwise
#     904                 :            :     // disadvantaged under our eviction criteria.
#     905                 :      31865 :     const size_t initial_size = vEvictionCandidates.size();
#     906                 :      31865 :     size_t total_protect_size = initial_size / 2;
#     907                 :      31865 :     const size_t onion_protect_size = total_protect_size / 2;
#     908                 :            : 
#     909         [ +  + ]:      31865 :     if (onion_protect_size) {
#     910                 :            :         // Pick out up to 1/4 peers connected via our onion service, sorted by longest uptime.
#     911                 :      27618 :         EraseLastKElements(vEvictionCandidates, CompareOnionTimeConnected, onion_protect_size,
#     912                 :     599946 :                            [](const NodeEvictionCandidate& n) { return n.m_is_onion; });
#     913                 :      27618 :     }
#     914                 :            : 
#     915                 :      31865 :     const size_t localhost_min_protect_size{2};
#     916         [ +  + ]:      31865 :     if (onion_protect_size >= localhost_min_protect_size) {
#     917                 :            :         // Allocate any remaining slots of the 1/4, or minimum 2 additional slots,
#     918                 :            :         // to localhost peers, sorted by longest uptime, as manually configured
#     919                 :            :         // hidden services not using `-bind=addr[:port]=onion` will not be detected
#     920                 :            :         // as inbound onion connections.
#     921                 :      26908 :         const size_t remaining_tor_slots{onion_protect_size - (initial_size - vEvictionCandidates.size())};
#     922                 :      26908 :         const size_t localhost_protect_size{std::max(remaining_tor_slots, localhost_min_protect_size)};
#     923                 :      26908 :         EraseLastKElements(vEvictionCandidates, CompareLocalHostTimeConnected, localhost_protect_size,
#     924                 :      53826 :                            [](const NodeEvictionCandidate& n) { return n.m_is_local; });
#     925                 :      26908 :     }
#     926                 :            : 
#     927                 :            :     // Calculate how many we removed, and update our total number of peers that
#     928                 :            :     // we want to protect based on uptime accordingly.
#     929                 :      31865 :     total_protect_size -= initial_size - vEvictionCandidates.size();
#     930                 :      31865 :     EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
#     931                 :      31865 : }
#     932                 :            : 
#     933                 :            : [[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
#     934                 :      31841 : {
#     935                 :            :     // Protect connections with certain characteristics
#     936                 :            : 
#     937                 :            :     // Deterministically select 4 peers to protect by netgroup.
#     938                 :            :     // An attacker cannot predict which netgroups will be protected
#     939                 :      31841 :     EraseLastKElements(vEvictionCandidates, CompareNetGroupKeyed, 4);
#     940                 :            :     // Protect the 8 nodes with the lowest minimum ping time.
#     941                 :            :     // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
#     942                 :      31841 :     EraseLastKElements(vEvictionCandidates, ReverseCompareNodeMinPingTime, 8);
#     943                 :            :     // Protect 4 nodes that most recently sent us novel transactions accepted into our mempool.
#     944                 :            :     // An attacker cannot manipulate this metric without performing useful work.
#     945                 :      31841 :     EraseLastKElements(vEvictionCandidates, CompareNodeTXTime, 4);
#     946                 :            :     // Protect up to 8 non-tx-relay peers that have sent us novel blocks.
#     947                 :      31841 :     const size_t erase_size = std::min(size_t(8), vEvictionCandidates.size());
#     948                 :      31841 :     EraseLastKElements(vEvictionCandidates, CompareNodeBlockRelayOnlyTime, erase_size,
#     949 [ +  + ][ +  + ]:     228605 :                        [](const NodeEvictionCandidate& n) { return !n.fRelayTxes && n.fRelevantServices; });
#     950                 :            : 
#     951                 :            :     // Protect 4 nodes that most recently sent us novel blocks.
#     952                 :            :     // An attacker cannot manipulate this metric without performing useful work.
#     953                 :      31841 :     EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4);
#     954                 :            : 
#     955                 :            :     // Protect some of the remaining eviction candidates by ratios of desirable
#     956                 :            :     // or disadvantaged characteristics.
#     957                 :      31841 :     ProtectEvictionCandidatesByRatio(vEvictionCandidates);
#     958                 :            : 
#     959         [ +  + ]:      31841 :     if (vEvictionCandidates.empty()) return std::nullopt;
#     960                 :            : 
#     961                 :            :     // If any remaining peers are preferred for eviction consider only them.
#     962                 :            :     // This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
#     963                 :            :     //  then we probably don't want to evict it no matter what.
#     964         [ +  + ]:      55601 :     if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](NodeEvictionCandidate const &n){return n.prefer_evict;})) {
#     965                 :      27786 :         vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
#     966                 :    1227268 :                                   [](NodeEvictionCandidate const &n){return !n.prefer_evict;}),vEvictionCandidates.end());
#     967                 :      27786 :     }
#     968                 :            : 
#     969                 :            :     // Identify the network group with the most connections and youngest member.
#     970                 :            :     // (vEvictionCandidates is already sorted by reverse connect time)
#     971                 :      28139 :     uint64_t naMostConnections;
#     972                 :      28139 :     unsigned int nMostConnections = 0;
#     973                 :      28139 :     int64_t nMostConnectionsTime = 0;
#     974                 :      28139 :     std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
#     975         [ +  + ]:     613417 :     for (const NodeEvictionCandidate &node : vEvictionCandidates) {
#     976                 :     613417 :         std::vector<NodeEvictionCandidate> &group = mapNetGroupNodes[node.nKeyedNetGroup];
#     977                 :     613417 :         group.push_back(node);
#     978                 :     613417 :         const int64_t grouptime = group[0].nTimeConnected;
#     979                 :            : 
#     980 [ +  + ][ +  + ]:     613417 :         if (group.size() > nMostConnections || (group.size() == nMostConnections && grouptime > nMostConnectionsTime)) {
#                 [ +  + ]
#     981                 :      54471 :             nMostConnections = group.size();
#     982                 :      54471 :             nMostConnectionsTime = grouptime;
#     983                 :      54471 :             naMostConnections = node.nKeyedNetGroup;
#     984                 :      54471 :         }
#     985                 :     613417 :     }
#     986                 :            : 
#     987                 :            :     // Reduce to the network group with the most connections
#     988                 :      28139 :     vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
#     989                 :            : 
#     990                 :            :     // Disconnect from the network group with the most connections
#     991                 :      28139 :     return vEvictionCandidates.front().id;
#     992                 :      28139 : }
#     993                 :            : 
#     994                 :            : /** Try to find a connection to evict when the node is full.
#     995                 :            :  *  Extreme care must be taken to avoid opening the node to attacker
#     996                 :            :  *   triggered network partitioning.
#     997                 :            :  *  The strategy used here is to protect a small number of peers
#     998                 :            :  *   for each of several distinct characteristics which are difficult
#     999                 :            :  *   to forge.  In order to partition a node the attacker must be
#    1000                 :            :  *   simultaneously better at all of them than honest peers.
#    1001                 :            :  */
#    1002                 :            : bool CConnman::AttemptToEvictConnection()
#    1003                 :          1 : {
#    1004                 :          1 :     std::vector<NodeEvictionCandidate> vEvictionCandidates;
#    1005                 :          1 :     {
#    1006                 :            : 
#    1007                 :          1 :         LOCK(cs_vNodes);
#    1008         [ +  + ]:         21 :         for (const CNode* node : vNodes) {
#    1009         [ -  + ]:         21 :             if (node->HasPermission(NetPermissionFlags::NoBan))
#    1010                 :          0 :                 continue;
#    1011         [ -  + ]:         21 :             if (!node->IsInboundConn())
#    1012                 :          0 :                 continue;
#    1013         [ -  + ]:         21 :             if (node->fDisconnect)
#    1014                 :          0 :                 continue;
#    1015                 :         21 :             bool peer_relay_txes = false;
#    1016                 :         21 :             bool peer_filter_not_null = false;
#    1017         [ +  - ]:         21 :             if (node->m_tx_relay != nullptr) {
#    1018                 :         21 :                 LOCK(node->m_tx_relay->cs_filter);
#    1019                 :         21 :                 peer_relay_txes = node->m_tx_relay->fRelayTxes;
#    1020                 :         21 :                 peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
#    1021                 :         21 :             }
#    1022                 :         21 :             NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->m_min_ping_time,
#    1023                 :         21 :                                                node->nLastBlockTime, node->nLastTXTime,
#    1024                 :         21 :                                                HasAllDesirableServiceFlags(node->nServices),
#    1025                 :         21 :                                                peer_relay_txes, peer_filter_not_null, node->nKeyedNetGroup,
#    1026                 :         21 :                                                node->m_prefer_evict, node->addr.IsLocal(),
#    1027                 :         21 :                                                node->m_inbound_onion};
#    1028                 :         21 :             vEvictionCandidates.push_back(candidate);
#    1029                 :         21 :         }
#    1030                 :          1 :     }
#    1031                 :          1 :     const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
#    1032         [ -  + ]:          1 :     if (!node_id_to_evict) {
#    1033                 :          0 :         return false;
#    1034                 :          0 :     }
#    1035                 :          1 :     LOCK(cs_vNodes);
#    1036         [ +  - ]:          8 :     for (CNode* pnode : vNodes) {
#    1037         [ +  + ]:          8 :         if (pnode->GetId() == *node_id_to_evict) {
#    1038         [ +  - ]:          1 :             LogPrint(BCLog::NET, "selected %s connection for eviction peer=%d; disconnecting\n", pnode->ConnectionTypeAsString(), pnode->GetId());
#    1039                 :          1 :             pnode->fDisconnect = true;
#    1040                 :          1 :             return true;
#    1041                 :          1 :         }
#    1042                 :          8 :     }
#    1043                 :          1 :     return false;
#    1044                 :          1 : }
#    1045                 :            : 
#    1046                 :        613 : void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
#    1047                 :        613 :     struct sockaddr_storage sockaddr;
#    1048                 :        613 :     socklen_t len = sizeof(sockaddr);
#    1049                 :        613 :     SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
#    1050                 :        613 :     CAddress addr;
#    1051                 :            : 
#    1052         [ -  + ]:        613 :     if (hSocket == INVALID_SOCKET) {
#    1053                 :          0 :         const int nErr = WSAGetLastError();
#    1054         [ #  # ]:          0 :         if (nErr != WSAEWOULDBLOCK) {
#    1055                 :          0 :             LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
#    1056                 :          0 :         }
#    1057                 :          0 :         return;
#    1058                 :          0 :     }
#    1059                 :            : 
#    1060         [ -  + ]:        613 :     if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
#    1061                 :          0 :         LogPrintf("Warning: Unknown socket family\n");
#    1062                 :          0 :     }
#    1063                 :            : 
#    1064                 :        613 :     const CAddress addr_bind = GetBindAddress(hSocket);
#    1065                 :            : 
#    1066                 :        613 :     NetPermissionFlags permissionFlags = NetPermissionFlags::None;
#    1067                 :        613 :     hListenSocket.AddSocketPermissionFlags(permissionFlags);
#    1068                 :            : 
#    1069                 :        613 :     CreateNodeFromAcceptedSocket(hSocket, permissionFlags, addr_bind, addr);
#    1070                 :        613 : }
#    1071                 :            : 
#    1072                 :            : void CConnman::CreateNodeFromAcceptedSocket(SOCKET hSocket,
#    1073                 :            :                                             NetPermissionFlags permissionFlags,
#    1074                 :            :                                             const CAddress& addr_bind,
#    1075                 :            :                                             const CAddress& addr)
#    1076                 :        613 : {
#    1077                 :        613 :     int nInbound = 0;
#    1078                 :        613 :     int nMaxInbound = nMaxConnections - m_max_outbound;
#    1079                 :            : 
#    1080                 :        613 :     AddWhitelistPermissionFlags(permissionFlags, addr);
#    1081         [ +  + ]:        613 :     if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::Implicit)) {
#    1082                 :          6 :         NetPermissions::ClearFlag(permissionFlags, NetPermissionFlags::Implicit);
#    1083         [ +  + ]:          6 :         if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::ForceRelay);
#    1084         [ +  + ]:          6 :         if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::Relay);
#    1085                 :          6 :         NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::Mempool);
#    1086                 :          6 :         NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::NoBan);
#    1087                 :          6 :     }
#    1088                 :            : 
#    1089                 :        613 :     {
#    1090                 :        613 :         LOCK(cs_vNodes);
#    1091         [ +  + ]:        912 :         for (const CNode* pnode : vNodes) {
#    1092         [ +  + ]:        912 :             if (pnode->IsInboundConn()) nInbound++;
#    1093                 :        912 :         }
#    1094                 :        613 :     }
#    1095                 :            : 
#    1096         [ -  + ]:        613 :     if (!fNetworkActive) {
#    1097         [ #  # ]:          0 :         LogPrint(BCLog::NET, "connection from %s dropped: not accepting new connections\n", addr.ToString());
#    1098                 :          0 :         CloseSocket(hSocket);
#    1099                 :          0 :         return;
#    1100                 :          0 :     }
#    1101                 :            : 
#    1102         [ -  + ]:        613 :     if (!IsSelectableSocket(hSocket))
#    1103                 :          0 :     {
#    1104                 :          0 :         LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString());
#    1105                 :          0 :         CloseSocket(hSocket);
#    1106                 :          0 :         return;
#    1107                 :          0 :     }
#    1108                 :            : 
#    1109                 :            :     // According to the internet TCP_NODELAY is not carried into accepted sockets
#    1110                 :            :     // on all platforms.  Set it again here just to be sure.
#    1111                 :        613 :     SetSocketNoDelay(hSocket);
#    1112                 :            : 
#    1113                 :            :     // Don't accept connections from banned peers.
#    1114 [ +  - ][ +  + ]:        613 :     bool banned = m_banman && m_banman->IsBanned(addr);
#    1115 [ +  + ][ +  + ]:        613 :     if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && banned)
#    1116                 :          1 :     {
#    1117         [ +  - ]:          1 :         LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
#    1118                 :          1 :         CloseSocket(hSocket);
#    1119                 :          1 :         return;
#    1120                 :          1 :     }
#    1121                 :            : 
#    1122                 :            :     // Only accept connections from discouraged peers if our inbound slots aren't (almost) full.
#    1123 [ +  - ][ -  + ]:        612 :     bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
#    1124 [ +  + ][ +  + ]:        612 :     if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged)
#                 [ -  + ]
#    1125                 :          0 :     {
#    1126         [ #  # ]:          0 :         LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToString());
#    1127                 :          0 :         CloseSocket(hSocket);
#    1128                 :          0 :         return;
#    1129                 :          0 :     }
#    1130                 :            : 
#    1131         [ +  + ]:        612 :     if (nInbound >= nMaxInbound)
#    1132                 :          1 :     {
#    1133         [ -  + ]:          1 :         if (!AttemptToEvictConnection()) {
#    1134                 :            :             // No connection to evict, disconnect the new connection
#    1135         [ #  # ]:          0 :             LogPrint(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
#    1136                 :          0 :             CloseSocket(hSocket);
#    1137                 :          0 :             return;
#    1138                 :          0 :         }
#    1139                 :        612 :     }
#    1140                 :            : 
#    1141                 :        612 :     NodeId id = GetNewNodeId();
#    1142                 :        612 :     uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
#    1143                 :            : 
#    1144                 :        612 :     ServiceFlags nodeServices = nLocalServices;
#    1145         [ +  + ]:        612 :     if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::BloomFilter)) {
#    1146                 :          2 :         nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
#    1147                 :          2 :     }
#    1148                 :            : 
#    1149                 :        612 :     const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
#    1150                 :        612 :     CNode* pnode = new CNode(id, nodeServices, hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND, inbound_onion);
#    1151                 :        612 :     pnode->AddRef();
#    1152                 :        612 :     pnode->m_permissionFlags = permissionFlags;
#    1153                 :        612 :     pnode->m_prefer_evict = discouraged;
#    1154                 :        612 :     m_msgproc->InitializeNode(pnode);
#    1155                 :            : 
#    1156         [ +  - ]:        612 :     LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
#    1157                 :            : 
#    1158                 :        612 :     {
#    1159                 :        612 :         LOCK(cs_vNodes);
#    1160                 :        612 :         vNodes.push_back(pnode);
#    1161                 :        612 :     }
#    1162                 :            : 
#    1163                 :            :     // We received a new connection, harvest entropy from the time (and our peer count)
#    1164                 :        612 :     RandAddEvent((uint32_t)id);
#    1165                 :        612 : }
#    1166                 :            : 
#    1167                 :            : bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type)
#    1168                 :         46 : {
#    1169 [ +  + ][ -  + ]:         46 :     if (conn_type != ConnectionType::OUTBOUND_FULL_RELAY && conn_type != ConnectionType::BLOCK_RELAY) return false;
#    1170                 :            : 
#    1171         [ +  + ]:         46 :     const int max_connections = conn_type == ConnectionType::OUTBOUND_FULL_RELAY ? m_max_outbound_full_relay : m_max_outbound_block_relay;
#    1172                 :            : 
#    1173                 :            :     // Count existing connections
#    1174                 :         46 :     int existing_connections = WITH_LOCK(cs_vNodes,
#    1175                 :         46 :                                          return std::count_if(vNodes.begin(), vNodes.end(), [conn_type](CNode* node) { return node->m_conn_type == conn_type; }););
#    1176                 :            : 
#    1177                 :            :     // Max connections of specified type already exist
#    1178         [ -  + ]:         46 :     if (existing_connections >= max_connections) return false;
#    1179                 :            : 
#    1180                 :            :     // Max total outbound connections already exist
#    1181                 :         46 :     CSemaphoreGrant grant(*semOutbound, true);
#    1182         [ -  + ]:         46 :     if (!grant) return false;
#    1183                 :            : 
#    1184                 :         46 :     OpenNetworkConnection(CAddress(), false, &grant, address.c_str(), conn_type);
#    1185                 :         46 :     return true;
#    1186                 :         46 : }
#    1187                 :            : 
#    1188                 :            : void CConnman::DisconnectNodes()
#    1189                 :     363336 : {
#    1190                 :     363336 :     {
#    1191                 :     363336 :         LOCK(cs_vNodes);
#    1192                 :            : 
#    1193         [ +  + ]:     363336 :         if (!fNetworkActive) {
#    1194                 :            :             // Disconnect any connected nodes
#    1195         [ +  + ]:         20 :             for (CNode* pnode : vNodes) {
#    1196         [ +  - ]:          3 :                 if (!pnode->fDisconnect) {
#    1197         [ +  - ]:          3 :                     LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
#    1198                 :          3 :                     pnode->fDisconnect = true;
#    1199                 :          3 :                 }
#    1200                 :          3 :             }
#    1201                 :         20 :         }
#    1202                 :            : 
#    1203                 :            :         // Disconnect unused nodes
#    1204                 :     363336 :         std::vector<CNode*> vNodesCopy = vNodes;
#    1205         [ +  + ]:     363336 :         for (CNode* pnode : vNodesCopy)
#    1206                 :     589742 :         {
#    1207         [ +  + ]:     589742 :             if (pnode->fDisconnect)
#    1208                 :        342 :             {
#    1209                 :            :                 // remove from vNodes
#    1210                 :        342 :                 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
#    1211                 :            : 
#    1212                 :            :                 // release outbound grant (if any)
#    1213                 :        342 :                 pnode->grantOutbound.Release();
#    1214                 :            : 
#    1215                 :            :                 // close socket and cleanup
#    1216                 :        342 :                 pnode->CloseSocketDisconnect();
#    1217                 :            : 
#    1218                 :            :                 // hold in disconnected pool until all refs are released
#    1219                 :        342 :                 pnode->Release();
#    1220                 :        342 :                 vNodesDisconnected.push_back(pnode);
#    1221                 :        342 :             }
#    1222                 :     589742 :         }
#    1223                 :     363336 :     }
#    1224                 :     363336 :     {
#    1225                 :            :         // Delete disconnected nodes
#    1226                 :     363336 :         std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
#    1227         [ +  + ]:     363336 :         for (CNode* pnode : vNodesDisconnectedCopy)
#    1228                 :        348 :         {
#    1229                 :            :             // Destroy the object only after other threads have stopped using it.
#    1230         [ +  + ]:        348 :             if (pnode->GetRefCount() <= 0) {
#    1231                 :        342 :                 vNodesDisconnected.remove(pnode);
#    1232                 :        342 :                 DeleteNode(pnode);
#    1233                 :        342 :             }
#    1234                 :        348 :         }
#    1235                 :     363336 :     }
#    1236                 :     363336 : }
#    1237                 :            : 
#    1238                 :            : void CConnman::NotifyNumConnectionsChanged()
#    1239                 :     363336 : {
#    1240                 :     363336 :     size_t vNodesSize;
#    1241                 :     363336 :     {
#    1242                 :     363336 :         LOCK(cs_vNodes);
#    1243                 :     363336 :         vNodesSize = vNodes.size();
#    1244                 :     363336 :     }
#    1245         [ +  + ]:     363336 :     if(vNodesSize != nPrevNodeCount) {
#    1246                 :       1274 :         nPrevNodeCount = vNodesSize;
#    1247         [ +  - ]:       1274 :         if(clientInterface)
#    1248                 :       1274 :             clientInterface->NotifyNumConnectionsChanged(vNodesSize);
#    1249                 :       1274 :     }
#    1250                 :     363336 : }
#    1251                 :            : 
#    1252                 :            : bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::optional<int64_t> now_in) const
#    1253                 :     955393 : {
#    1254         [ +  + ]:     955393 :     const int64_t now = now_in ? now_in.value() : GetSystemTimeInSeconds();
#    1255                 :     955393 :     return node.nTimeConnected + m_peer_connect_timeout < now;
#    1256                 :     955393 : }
#    1257                 :            : 
#    1258                 :            : bool CConnman::InactivityCheck(const CNode& node) const
#    1259                 :     589740 : {
#    1260                 :            :     // Use non-mockable system time (otherwise these timers will pop when we
#    1261                 :            :     // use setmocktime in the tests).
#    1262                 :     589740 :     int64_t now = GetSystemTimeInSeconds();
#    1263                 :            : 
#    1264         [ +  + ]:     589740 :     if (!ShouldRunInactivityChecks(node, now)) return false;
#    1265                 :            : 
#    1266 [ +  + ][ +  + ]:     207091 :     if (node.nLastRecv == 0 || node.nLastSend == 0) {
#    1267         [ +  - ]:          3 :         LogPrint(BCLog::NET, "socket no message in first %i seconds, %d %d peer=%d\n", m_peer_connect_timeout, node.nLastRecv != 0, node.nLastSend != 0, node.GetId());
#    1268                 :          3 :         return true;
#    1269                 :          3 :     }
#    1270                 :            : 
#    1271         [ -  + ]:     207088 :     if (now > node.nLastSend + TIMEOUT_INTERVAL) {
#    1272         [ #  # ]:          0 :         LogPrint(BCLog::NET, "socket sending timeout: %is peer=%d\n", now - node.nLastSend, node.GetId());
#    1273                 :          0 :         return true;
#    1274                 :          0 :     }
#    1275                 :            : 
#    1276         [ -  + ]:     207088 :     if (now > node.nLastRecv + TIMEOUT_INTERVAL) {
#    1277         [ #  # ]:          0 :         LogPrint(BCLog::NET, "socket receive timeout: %is peer=%d\n", now - node.nLastRecv, node.GetId());
#    1278                 :          0 :         return true;
#    1279                 :          0 :     }
#    1280                 :            : 
#    1281         [ +  + ]:     207088 :     if (!node.fSuccessfullyConnected) {
#    1282         [ +  - ]:          3 :         LogPrint(BCLog::NET, "version handshake timeout peer=%d\n", node.GetId());
#    1283                 :          3 :         return true;
#    1284                 :          3 :     }
#    1285                 :            : 
#    1286                 :     207085 :     return false;
#    1287                 :     207085 : }
#    1288                 :            : 
#    1289                 :            : bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
#    1290                 :     363336 : {
#    1291         [ +  + ]:     398331 :     for (const ListenSocket& hListenSocket : vhListenSocket) {
#    1292                 :     398331 :         recv_set.insert(hListenSocket.socket);
#    1293                 :     398331 :     }
#    1294                 :            : 
#    1295                 :     363336 :     {
#    1296                 :     363336 :         LOCK(cs_vNodes);
#    1297         [ +  + ]:     363336 :         for (CNode* pnode : vNodes)
#    1298                 :     589401 :         {
#    1299                 :            :             // Implement the following logic:
#    1300                 :            :             // * If there is data to send, select() for sending data. As this only
#    1301                 :            :             //   happens when optimistic write failed, we choose to first drain the
#    1302                 :            :             //   write buffer in this case before receiving more. This avoids
#    1303                 :            :             //   needlessly queueing received data, if the remote peer is not themselves
#    1304                 :            :             //   receiving data. This means properly utilizing TCP flow control signalling.
#    1305                 :            :             // * Otherwise, if there is space left in the receive buffer, select() for
#    1306                 :            :             //   receiving data.
#    1307                 :            :             // * Hand off all complete messages to the processor, to be handled without
#    1308                 :            :             //   blocking here.
#    1309                 :            : 
#    1310                 :     589401 :             bool select_recv = !pnode->fPauseRecv;
#    1311                 :     589401 :             bool select_send;
#    1312                 :     589401 :             {
#    1313                 :     589401 :                 LOCK(pnode->cs_vSend);
#    1314                 :     589401 :                 select_send = !pnode->vSendMsg.empty();
#    1315                 :     589401 :             }
#    1316                 :            : 
#    1317                 :     589401 :             LOCK(pnode->cs_hSocket);
#    1318         [ -  + ]:     589401 :             if (pnode->hSocket == INVALID_SOCKET)
#    1319                 :     589401 :                 continue;
#    1320                 :            : 
#    1321                 :     589401 :             error_set.insert(pnode->hSocket);
#    1322         [ +  + ]:     589401 :             if (select_send) {
#    1323                 :        369 :                 send_set.insert(pnode->hSocket);
#    1324                 :        369 :                 continue;
#    1325                 :        369 :             }
#    1326         [ +  - ]:     589032 :             if (select_recv) {
#    1327                 :     589032 :                 recv_set.insert(pnode->hSocket);
#    1328                 :     589032 :             }
#    1329                 :     589032 :         }
#    1330                 :     363336 :     }
#    1331                 :            : 
#    1332 [ +  - ][ #  # ]:     363336 :     return !recv_set.empty() || !send_set.empty() || !error_set.empty();
#                 [ #  # ]
#    1333                 :     363336 : }
#    1334                 :            : 
#    1335                 :            : #ifdef USE_POLL
#    1336                 :            : void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
#    1337                 :            : {
#    1338                 :            :     std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
#    1339                 :            :     if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
#    1340                 :            :         interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
#    1341                 :            :         return;
#    1342                 :            :     }
#    1343                 :            : 
#    1344                 :            :     std::unordered_map<SOCKET, struct pollfd> pollfds;
#    1345                 :            :     for (SOCKET socket_id : recv_select_set) {
#    1346                 :            :         pollfds[socket_id].fd = socket_id;
#    1347                 :            :         pollfds[socket_id].events |= POLLIN;
#    1348                 :            :     }
#    1349                 :            : 
#    1350                 :            :     for (SOCKET socket_id : send_select_set) {
#    1351                 :            :         pollfds[socket_id].fd = socket_id;
#    1352                 :            :         pollfds[socket_id].events |= POLLOUT;
#    1353                 :            :     }
#    1354                 :            : 
#    1355                 :            :     for (SOCKET socket_id : error_select_set) {
#    1356                 :            :         pollfds[socket_id].fd = socket_id;
#    1357                 :            :         // These flags are ignored, but we set them for clarity
#    1358                 :            :         pollfds[socket_id].events |= POLLERR|POLLHUP;
#    1359                 :            :     }
#    1360                 :            : 
#    1361                 :            :     std::vector<struct pollfd> vpollfds;
#    1362                 :            :     vpollfds.reserve(pollfds.size());
#    1363                 :            :     for (auto it : pollfds) {
#    1364                 :            :         vpollfds.push_back(std::move(it.second));
#    1365                 :            :     }
#    1366                 :            : 
#    1367                 :            :     if (poll(vpollfds.data(), vpollfds.size(), SELECT_TIMEOUT_MILLISECONDS) < 0) return;
#    1368                 :            : 
#    1369                 :            :     if (interruptNet) return;
#    1370                 :            : 
#    1371                 :            :     for (struct pollfd pollfd_entry : vpollfds) {
#    1372                 :            :         if (pollfd_entry.revents & POLLIN)            recv_set.insert(pollfd_entry.fd);
#    1373                 :            :         if (pollfd_entry.revents & POLLOUT)           send_set.insert(pollfd_entry.fd);
#    1374                 :            :         if (pollfd_entry.revents & (POLLERR|POLLHUP)) error_set.insert(pollfd_entry.fd);
#    1375                 :            :     }
#    1376                 :            : }
#    1377                 :            : #else
#    1378                 :            : void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
#    1379                 :     363336 : {
#    1380                 :     363336 :     std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
#    1381         [ -  + ]:     363336 :     if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
#    1382                 :          0 :         interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
#    1383                 :          0 :         return;
#    1384                 :          0 :     }
#    1385                 :            : 
#    1386                 :            :     //
#    1387                 :            :     // Find which sockets have data to receive
#    1388                 :            :     //
#    1389                 :     363336 :     struct timeval timeout;
#    1390                 :     363336 :     timeout.tv_sec  = 0;
#    1391                 :     363336 :     timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend
#    1392                 :            : 
#    1393                 :     363336 :     fd_set fdsetRecv;
#    1394                 :     363336 :     fd_set fdsetSend;
#    1395                 :     363336 :     fd_set fdsetError;
#    1396                 :     363336 :     FD_ZERO(&fdsetRecv);
#    1397                 :     363336 :     FD_ZERO(&fdsetSend);
#    1398                 :     363336 :     FD_ZERO(&fdsetError);
#    1399                 :     363336 :     SOCKET hSocketMax = 0;
#    1400                 :            : 
#    1401         [ +  + ]:     987363 :     for (SOCKET hSocket : recv_select_set) {
#    1402                 :     987363 :         FD_SET(hSocket, &fdsetRecv);
#    1403                 :     987363 :         hSocketMax = std::max(hSocketMax, hSocket);
#    1404                 :     987363 :     }
#    1405                 :            : 
#    1406         [ +  + ]:     363336 :     for (SOCKET hSocket : send_select_set) {
#    1407                 :        369 :         FD_SET(hSocket, &fdsetSend);
#    1408                 :        369 :         hSocketMax = std::max(hSocketMax, hSocket);
#    1409                 :        369 :     }
#    1410                 :            : 
#    1411         [ +  + ]:     589401 :     for (SOCKET hSocket : error_select_set) {
#    1412                 :     589401 :         FD_SET(hSocket, &fdsetError);
#    1413                 :     589401 :         hSocketMax = std::max(hSocketMax, hSocket);
#    1414                 :     589401 :     }
#    1415                 :            : 
#    1416                 :     363336 :     int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
#    1417                 :            : 
#    1418         [ +  + ]:     363336 :     if (interruptNet)
#    1419                 :        618 :         return;
#    1420                 :            : 
#    1421         [ -  + ]:     362718 :     if (nSelect == SOCKET_ERROR)
#    1422                 :     362718 :     {
#    1423                 :          0 :         int nErr = WSAGetLastError();
#    1424                 :          0 :         LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
#    1425         [ #  # ]:          0 :         for (unsigned int i = 0; i <= hSocketMax; i++)
#    1426                 :          0 :             FD_SET(i, &fdsetRecv);
#    1427                 :          0 :         FD_ZERO(&fdsetSend);
#    1428                 :          0 :         FD_ZERO(&fdsetError);
#    1429         [ #  # ]:          0 :         if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)))
#    1430                 :          0 :             return;
#    1431                 :     362718 :     }
#    1432                 :            : 
#    1433         [ +  + ]:     985978 :     for (SOCKET hSocket : recv_select_set) {
#    1434                 :     985978 :         if (FD_ISSET(hSocket, &fdsetRecv)) {
#    1435                 :     130889 :             recv_set.insert(hSocket);
#    1436                 :     130889 :         }
#    1437                 :     985978 :     }
#    1438                 :            : 
#    1439         [ +  + ]:     362718 :     for (SOCKET hSocket : send_select_set) {
#    1440                 :        369 :         if (FD_ISSET(hSocket, &fdsetSend)) {
#    1441                 :        363 :             send_set.insert(hSocket);
#    1442                 :        363 :         }
#    1443                 :        369 :     }
#    1444                 :            : 
#    1445         [ +  + ]:     588767 :     for (SOCKET hSocket : error_select_set) {
#    1446                 :     588767 :         if (FD_ISSET(hSocket, &fdsetError)) {
#    1447                 :          0 :             error_set.insert(hSocket);
#    1448                 :          0 :         }
#    1449                 :     588767 :     }
#    1450                 :     362718 : }
#    1451                 :            : #endif
#    1452                 :            : 
#    1453                 :            : void CConnman::SocketHandler()
#    1454                 :     363336 : {
#    1455                 :     363336 :     std::set<SOCKET> recv_set, send_set, error_set;
#    1456                 :     363336 :     SocketEvents(recv_set, send_set, error_set);
#    1457                 :            : 
#    1458         [ +  + ]:     363336 :     if (interruptNet) return;
#    1459                 :            : 
#    1460                 :            :     //
#    1461                 :            :     // Accept new connections
#    1462                 :            :     //
#    1463         [ +  + ]:     362718 :     for (const ListenSocket& hListenSocket : vhListenSocket)
#    1464                 :     397580 :     {
#    1465 [ +  - ][ +  + ]:     397580 :         if (hListenSocket.socket != INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0)
#    1466                 :        613 :         {
#    1467                 :        613 :             AcceptConnection(hListenSocket);
#    1468                 :        613 :         }
#    1469                 :     397580 :     }
#    1470                 :            : 
#    1471                 :            :     //
#    1472                 :            :     // Service each socket
#    1473                 :            :     //
#    1474                 :     362718 :     std::vector<CNode*> vNodesCopy;
#    1475                 :     362718 :     {
#    1476                 :     362718 :         LOCK(cs_vNodes);
#    1477                 :     362718 :         vNodesCopy = vNodes;
#    1478         [ +  + ]:     362718 :         for (CNode* pnode : vNodesCopy)
#    1479                 :     589741 :             pnode->AddRef();
#    1480                 :     362718 :     }
#    1481         [ +  + ]:     362718 :     for (CNode* pnode : vNodesCopy)
#    1482                 :     589741 :     {
#    1483         [ -  + ]:     589741 :         if (interruptNet)
#    1484                 :          0 :             return;
#    1485                 :            : 
#    1486                 :            :         //
#    1487                 :            :         // Receive
#    1488                 :            :         //
#    1489                 :     589741 :         bool recvSet = false;
#    1490                 :     589741 :         bool sendSet = false;
#    1491                 :     589741 :         bool errorSet = false;
#    1492                 :     589741 :         {
#    1493                 :     589741 :             LOCK(pnode->cs_hSocket);
#    1494         [ +  + ]:     589741 :             if (pnode->hSocket == INVALID_SOCKET)
#    1495                 :     589741 :                 continue;
#    1496                 :     589740 :             recvSet = recv_set.count(pnode->hSocket) > 0;
#    1497                 :     589740 :             sendSet = send_set.count(pnode->hSocket) > 0;
#    1498                 :     589740 :             errorSet = error_set.count(pnode->hSocket) > 0;
#    1499                 :     589740 :         }
#    1500 [ +  + ][ -  + ]:     589740 :         if (recvSet || errorSet)
#    1501                 :     130276 :         {
#    1502                 :            :             // typical socket buffer is 8K-64K
#    1503                 :     130276 :             uint8_t pchBuf[0x10000];
#    1504                 :     130276 :             int nBytes = 0;
#    1505                 :     130276 :             {
#    1506                 :     130276 :                 LOCK(pnode->cs_hSocket);
#    1507         [ -  + ]:     130276 :                 if (pnode->hSocket == INVALID_SOCKET)
#    1508                 :     130276 :                     continue;
#    1509                 :     130276 :                 nBytes = recv(pnode->hSocket, (char*)pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
#    1510                 :     130276 :             }
#    1511         [ +  + ]:     130276 :             if (nBytes > 0)
#    1512                 :     130090 :             {
#    1513                 :     130090 :                 bool notify = false;
#    1514         [ +  + ]:     130090 :                 if (!pnode->ReceiveMsgBytes(Span<const uint8_t>(pchBuf, nBytes), notify))
#    1515                 :          4 :                     pnode->CloseSocketDisconnect();
#    1516                 :     130090 :                 RecordBytesRecv(nBytes);
#    1517         [ +  + ]:     130090 :                 if (notify) {
#    1518                 :     107885 :                     size_t nSizeAdded = 0;
#    1519                 :     107885 :                     auto it(pnode->vRecvMsg.begin());
#    1520         [ +  + ]:     219790 :                     for (; it != pnode->vRecvMsg.end(); ++it) {
#    1521                 :            :                         // vRecvMsg contains only completed CNetMessage
#    1522                 :            :                         // the single possible partially deserialized message are held by TransportDeserializer
#    1523                 :     111905 :                         nSizeAdded += it->m_raw_message_size;
#    1524                 :     111905 :                     }
#    1525                 :     107885 :                     {
#    1526                 :     107885 :                         LOCK(pnode->cs_vProcessMsg);
#    1527                 :     107885 :                         pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
#    1528                 :     107885 :                         pnode->nProcessQueueSize += nSizeAdded;
#    1529                 :     107885 :                         pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
#    1530                 :     107885 :                     }
#    1531                 :     107885 :                     WakeMessageHandler();
#    1532                 :     107885 :                 }
#    1533                 :     130090 :             }
#    1534         [ +  + ]:        186 :             else if (nBytes == 0)
#    1535                 :        171 :             {
#    1536                 :            :                 // socket closed gracefully
#    1537         [ +  - ]:        171 :                 if (!pnode->fDisconnect) {
#    1538         [ +  - ]:        171 :                     LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId());
#    1539                 :        171 :                 }
#    1540                 :        171 :                 pnode->CloseSocketDisconnect();
#    1541                 :        171 :             }
#    1542         [ +  - ]:         15 :             else if (nBytes < 0)
#    1543                 :         15 :             {
#    1544                 :            :                 // error
#    1545                 :         15 :                 int nErr = WSAGetLastError();
#    1546 [ +  - ][ +  - ]:         15 :                 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
#         [ +  - ][ +  - ]
#    1547                 :         15 :                 {
#    1548         [ +  - ]:         15 :                     if (!pnode->fDisconnect) {
#    1549         [ +  - ]:         15 :                         LogPrint(BCLog::NET, "socket recv error for peer=%d: %s\n", pnode->GetId(), NetworkErrorString(nErr));
#    1550                 :         15 :                     }
#    1551                 :         15 :                     pnode->CloseSocketDisconnect();
#    1552                 :         15 :                 }
#    1553                 :         15 :             }
#    1554                 :     130276 :         }
#    1555                 :            : 
#    1556         [ +  + ]:     589740 :         if (sendSet) {
#    1557                 :            :             // Send data
#    1558                 :        363 :             size_t bytes_sent = WITH_LOCK(pnode->cs_vSend, return SocketSendData(*pnode));
#    1559         [ +  - ]:        363 :             if (bytes_sent) RecordBytesSent(bytes_sent);
#    1560                 :        363 :         }
#    1561                 :            : 
#    1562         [ +  + ]:     589740 :         if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
#    1563                 :     589740 :     }
#    1564                 :     362718 :     {
#    1565                 :     362718 :         LOCK(cs_vNodes);
#    1566         [ +  + ]:     362718 :         for (CNode* pnode : vNodesCopy)
#    1567                 :     589741 :             pnode->Release();
#    1568                 :     362718 :     }
#    1569                 :     362718 : }
#    1570                 :            : 
#    1571                 :            : void CConnman::ThreadSocketHandler()
#    1572                 :        618 : {
#    1573         [ +  + ]:     363954 :     while (!interruptNet)
#    1574                 :     363336 :     {
#    1575                 :     363336 :         DisconnectNodes();
#    1576                 :     363336 :         NotifyNumConnectionsChanged();
#    1577                 :     363336 :         SocketHandler();
#    1578                 :     363336 :     }
#    1579                 :        618 : }
#    1580                 :            : 
#    1581                 :            : void CConnman::WakeMessageHandler()
#    1582                 :     162375 : {
#    1583                 :     162375 :     {
#    1584                 :     162375 :         LOCK(mutexMsgProc);
#    1585                 :     162375 :         fMsgProcWake = true;
#    1586                 :     162375 :     }
#    1587                 :     162375 :     condMsgProc.notify_one();
#    1588                 :     162375 : }
#    1589                 :            : 
#    1590                 :            : void CConnman::ThreadDNSAddressSeed()
#    1591                 :          1 : {
#    1592                 :          1 :     FastRandomContext rng;
#    1593                 :          1 :     std::vector<std::string> seeds = Params().DNSSeeds();
#    1594                 :          1 :     Shuffle(seeds.begin(), seeds.end(), rng);
#    1595                 :          1 :     int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections
#    1596                 :          1 :     int found = 0;
#    1597                 :            : 
#    1598         [ -  + ]:          1 :     if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
#    1599                 :            :         // When -forcednsseed is provided, query all.
#    1600                 :          0 :         seeds_right_now = seeds.size();
#    1601         [ +  - ]:          1 :     } else if (addrman.size() == 0) {
#    1602                 :            :         // If we have no known peers, query all.
#    1603                 :            :         // This will occur on the first run, or if peers.dat has been
#    1604                 :            :         // deleted.
#    1605                 :          1 :         seeds_right_now = seeds.size();
#    1606                 :          1 :     }
#    1607                 :            : 
#    1608                 :            :     // goal: only query DNS seed if address need is acute
#    1609                 :            :     // * If we have a reasonable number of peers in addrman, spend
#    1610                 :            :     //   some time trying them first. This improves user privacy by
#    1611                 :            :     //   creating fewer identifying DNS requests, reduces trust by
#    1612                 :            :     //   giving seeds less influence on the network topology, and
#    1613                 :            :     //   reduces traffic to the seeds.
#    1614                 :            :     // * When querying DNS seeds query a few at once, this ensures
#    1615                 :            :     //   that we don't give DNS seeds the ability to eclipse nodes
#    1616                 :            :     //   that query them.
#    1617                 :            :     // * If we continue having problems, eventually query all the
#    1618                 :            :     //   DNS seeds, and if that fails too, also try the fixed seeds.
#    1619                 :            :     //   (done in ThreadOpenConnections)
#    1620         [ -  + ]:          1 :     const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
#    1621                 :            : 
#    1622         [ -  + ]:          1 :     for (const std::string& seed : seeds) {
#    1623         [ #  # ]:          0 :         if (seeds_right_now == 0) {
#    1624                 :          0 :             seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
#    1625                 :            : 
#    1626         [ #  # ]:          0 :             if (addrman.size() > 0) {
#    1627                 :          0 :                 LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
#    1628                 :          0 :                 std::chrono::seconds to_wait = seeds_wait_time;
#    1629         [ #  # ]:          0 :                 while (to_wait.count() > 0) {
#    1630                 :            :                     // if sleeping for the MANY_PEERS interval, wake up
#    1631                 :            :                     // early to see if we have enough peers and can stop
#    1632                 :            :                     // this thread entirely freeing up its resources
#    1633                 :          0 :                     std::chrono::seconds w = std::min(DNSSEEDS_DELAY_FEW_PEERS, to_wait);
#    1634         [ #  # ]:          0 :                     if (!interruptNet.sleep_for(w)) return;
#    1635                 :          0 :                     to_wait -= w;
#    1636                 :            : 
#    1637                 :          0 :                     int nRelevant = 0;
#    1638                 :          0 :                     {
#    1639                 :          0 :                         LOCK(cs_vNodes);
#    1640         [ #  # ]:          0 :                         for (const CNode* pnode : vNodes) {
#    1641 [ #  # ][ #  # ]:          0 :                             if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant;
#    1642                 :          0 :                         }
#    1643                 :          0 :                     }
#    1644         [ #  # ]:          0 :                     if (nRelevant >= 2) {
#    1645         [ #  # ]:          0 :                         if (found > 0) {
#    1646                 :          0 :                             LogPrintf("%d addresses found from DNS seeds\n", found);
#    1647                 :          0 :                             LogPrintf("P2P peers available. Finished DNS seeding.\n");
#    1648                 :          0 :                         } else {
#    1649                 :          0 :                             LogPrintf("P2P peers available. Skipped DNS seeding.\n");
#    1650                 :          0 :                         }
#    1651                 :          0 :                         return;
#    1652                 :          0 :                     }
#    1653                 :          0 :                 }
#    1654                 :          0 :             }
#    1655                 :          0 :         }
#    1656                 :            : 
#    1657         [ #  # ]:          0 :         if (interruptNet) return;
#    1658                 :            : 
#    1659                 :            :         // hold off on querying seeds if P2P network deactivated
#    1660         [ #  # ]:          0 :         if (!fNetworkActive) {
#    1661                 :          0 :             LogPrintf("Waiting for network to be reactivated before querying DNS seeds.\n");
#    1662                 :          0 :             do {
#    1663         [ #  # ]:          0 :                 if (!interruptNet.sleep_for(std::chrono::seconds{1})) return;
#    1664         [ #  # ]:          0 :             } while (!fNetworkActive);
#    1665                 :          0 :         }
#    1666                 :            : 
#    1667                 :          0 :         LogPrintf("Loading addresses from DNS seed %s\n", seed);
#    1668         [ #  # ]:          0 :         if (HaveNameProxy()) {
#    1669                 :          0 :             AddAddrFetch(seed);
#    1670                 :          0 :         } else {
#    1671                 :          0 :             std::vector<CNetAddr> vIPs;
#    1672                 :          0 :             std::vector<CAddress> vAdd;
#    1673                 :          0 :             ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE);
#    1674                 :          0 :             std::string host = strprintf("x%x.%s", requiredServiceBits, seed);
#    1675                 :          0 :             CNetAddr resolveSource;
#    1676         [ #  # ]:          0 :             if (!resolveSource.SetInternal(host)) {
#    1677                 :          0 :                 continue;
#    1678                 :          0 :             }
#    1679                 :          0 :             unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed
#    1680         [ #  # ]:          0 :             if (LookupHost(host, vIPs, nMaxIPs, true)) {
#    1681         [ #  # ]:          0 :                 for (const CNetAddr& ip : vIPs) {
#    1682                 :          0 :                     int nOneDay = 24*3600;
#    1683                 :          0 :                     CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
#    1684                 :          0 :                     addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old
#    1685                 :          0 :                     vAdd.push_back(addr);
#    1686                 :          0 :                     found++;
#    1687                 :          0 :                 }
#    1688                 :          0 :                 addrman.Add(vAdd, resolveSource);
#    1689                 :          0 :             } else {
#    1690                 :            :                 // We now avoid directly using results from DNS Seeds which do not support service bit filtering,
#    1691                 :            :                 // instead using them as a addrfetch to get nodes with our desired service bits.
#    1692                 :          0 :                 AddAddrFetch(seed);
#    1693                 :          0 :             }
#    1694                 :          0 :         }
#    1695                 :          0 :         --seeds_right_now;
#    1696                 :          0 :     }
#    1697                 :          1 :     LogPrintf("%d addresses found from DNS seeds\n", found);
#    1698                 :          1 : }
#    1699                 :            : 
#    1700                 :            : void CConnman::DumpAddresses()
#    1701                 :        995 : {
#    1702                 :        995 :     int64_t nStart = GetTimeMillis();
#    1703                 :            : 
#    1704                 :        995 :     CAddrDB adb;
#    1705                 :        995 :     adb.Write(addrman);
#    1706                 :            : 
#    1707         [ +  - ]:        995 :     LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat  %dms\n",
#    1708                 :        995 :            addrman.size(), GetTimeMillis() - nStart);
#    1709                 :        995 : }
#    1710                 :            : 
#    1711                 :            : void CConnman::ProcessAddrFetch()
#    1712                 :      19470 : {
#    1713                 :      19470 :     std::string strDest;
#    1714                 :      19470 :     {
#    1715                 :      19470 :         LOCK(m_addr_fetches_mutex);
#    1716         [ +  - ]:      19470 :         if (m_addr_fetches.empty())
#    1717                 :      19470 :             return;
#    1718                 :          0 :         strDest = m_addr_fetches.front();
#    1719                 :          0 :         m_addr_fetches.pop_front();
#    1720                 :          0 :     }
#    1721                 :          0 :     CAddress addr;
#    1722                 :          0 :     CSemaphoreGrant grant(*semOutbound, true);
#    1723         [ #  # ]:          0 :     if (grant) {
#    1724                 :          0 :         OpenNetworkConnection(addr, false, &grant, strDest.c_str(), ConnectionType::ADDR_FETCH);
#    1725                 :          0 :     }
#    1726                 :          0 : }
#    1727                 :            : 
#    1728                 :            : bool CConnman::GetTryNewOutboundPeer() const
#    1729                 :         83 : {
#    1730                 :         83 :     return m_try_another_outbound_peer;
#    1731                 :         83 : }
#    1732                 :            : 
#    1733                 :            : void CConnman::SetTryNewOutboundPeer(bool flag)
#    1734                 :        804 : {
#    1735                 :        804 :     m_try_another_outbound_peer = flag;
#    1736 [ +  - ][ +  + ]:        804 :     LogPrint(BCLog::NET, "net: setting try another outbound peer=%s\n", flag ? "true" : "false");
#    1737                 :        804 : }
#    1738                 :            : 
#    1739                 :            : // Return the number of peers we have over our outbound connection limit
#    1740                 :            : // Exclude peers that are marked for disconnect, or are going to be
#    1741                 :            : // disconnected soon (eg ADDR_FETCH and FEELER)
#    1742                 :            : // Also exclude peers that haven't finished initial connection handshake yet
#    1743                 :            : // (so that we don't decide we're over our desired connection limit, and then
#    1744                 :            : // evict some peer that has finished the handshake)
#    1745                 :            : int CConnman::GetExtraFullOutboundCount() const
#    1746                 :        209 : {
#    1747                 :        209 :     int full_outbound_peers = 0;
#    1748                 :        209 :     {
#    1749                 :        209 :         LOCK(cs_vNodes);
#    1750         [ +  + ]:        376 :         for (const CNode* pnode : vNodes) {
#    1751 [ +  - ][ +  - ]:        376 :             if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
#                 [ +  + ]
#    1752                 :         68 :                 ++full_outbound_peers;
#    1753                 :         68 :             }
#    1754                 :        376 :         }
#    1755                 :        209 :     }
#    1756                 :        209 :     return std::max(full_outbound_peers - m_max_outbound_full_relay, 0);
#    1757                 :        209 : }
#    1758                 :            : 
#    1759                 :            : int CConnman::GetExtraBlockRelayCount() const
#    1760                 :        209 : {
#    1761                 :        209 :     int block_relay_peers = 0;
#    1762                 :        209 :     {
#    1763                 :        209 :         LOCK(cs_vNodes);
#    1764         [ +  + ]:        376 :         for (const CNode* pnode : vNodes) {
#    1765 [ +  - ][ +  - ]:        376 :             if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
#                 [ -  + ]
#    1766                 :          0 :                 ++block_relay_peers;
#    1767                 :          0 :             }
#    1768                 :        376 :         }
#    1769                 :        209 :     }
#    1770                 :        209 :     return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
#    1771                 :        209 : }
#    1772                 :            : 
#    1773                 :            : void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
#    1774                 :        618 : {
#    1775                 :            :     // Connect to specific addresses
#    1776         [ +  + ]:        618 :     if (!connect.empty())
#    1777                 :          1 :     {
#    1778                 :          1 :         for (int64_t nLoop = 0;; nLoop++)
#    1779                 :          1 :         {
#    1780                 :          1 :             ProcessAddrFetch();
#    1781         [ +  + ]:          1 :             for (const std::string& strAddr : connect)
#    1782                 :          1 :             {
#    1783                 :          1 :                 CAddress addr(CService(), NODE_NONE);
#    1784                 :          1 :                 OpenNetworkConnection(addr, false, nullptr, strAddr.c_str(), ConnectionType::MANUAL);
#    1785 [ +  - ][ -  + ]:          1 :                 for (int i = 0; i < 10 && i < nLoop; i++)
#    1786                 :          0 :                 {
#    1787         [ #  # ]:          0 :                     if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
#    1788                 :          0 :                         return;
#    1789                 :          0 :                 }
#    1790                 :          1 :             }
#    1791         [ +  - ]:          1 :             if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
#    1792                 :          1 :                 return;
#    1793                 :          1 :         }
#    1794                 :          1 :     }
#    1795                 :            : 
#    1796                 :            :     // Initiate network connections
#    1797                 :        618 :     auto start = GetTime<std::chrono::microseconds>();
#    1798                 :            : 
#    1799                 :            :     // Minimum time before next feeler connection (in microseconds).
#    1800                 :        617 :     auto next_feeler = PoissonNextSend(start, FEELER_INTERVAL);
#    1801                 :        617 :     auto next_extra_block_relay = PoissonNextSend(start, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
#    1802                 :        617 :     const bool dnsseed = gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED);
#    1803                 :        617 :     bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
#    1804                 :            : 
#    1805         [ +  + ]:        617 :     if (!add_fixed_seeds) {
#    1806                 :        614 :         LogPrintf("Fixed seeds are disabled\n");
#    1807                 :        614 :     }
#    1808                 :            : 
#    1809         [ +  + ]:      19476 :     while (!interruptNet)
#    1810                 :      19469 :     {
#    1811                 :      19469 :         ProcessAddrFetch();
#    1812                 :            : 
#    1813         [ +  + ]:      19469 :         if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
#    1814                 :        610 :             return;
#    1815                 :            : 
#    1816                 :      18859 :         CSemaphoreGrant grant(*semOutbound);
#    1817         [ -  + ]:      18859 :         if (interruptNet)
#    1818                 :          0 :             return;
#    1819                 :            : 
#    1820 [ +  + ][ +  - ]:      18859 :         if (add_fixed_seeds && addrman.size() == 0) {
#    1821                 :            :             // When the node starts with an empty peers.dat, there are a few other sources of peers before
#    1822                 :            :             // we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
#    1823                 :            :             // If none of those are available, we fallback on to fixed seeds immediately, else we allow
#    1824                 :            :             // 60 seconds for any of those sources to populate addrman.
#    1825                 :          3 :             bool add_fixed_seeds_now = false;
#    1826                 :            :             // It is cheapest to check if enough time has passed first.
#    1827         [ +  + ]:          3 :             if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
#    1828                 :          2 :                 add_fixed_seeds_now = true;
#    1829                 :          2 :                 LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty\n");
#    1830                 :          2 :             }
#    1831                 :            : 
#    1832                 :            :             // Checking !dnsseed is cheaper before locking 2 mutexes.
#    1833 [ +  + ][ +  - ]:          3 :             if (!add_fixed_seeds_now && !dnsseed) {
#    1834                 :          1 :                 LOCK2(m_addr_fetches_mutex, cs_vAddedNodes);
#    1835 [ +  - ][ +  - ]:          1 :                 if (m_addr_fetches.empty() && vAddedNodes.empty()) {
#    1836                 :          1 :                     add_fixed_seeds_now = true;
#    1837                 :          1 :                     LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n");
#    1838                 :          1 :                 }
#    1839                 :          1 :             }
#    1840                 :            : 
#    1841         [ +  - ]:          3 :             if (add_fixed_seeds_now) {
#    1842                 :          3 :                 CNetAddr local;
#    1843                 :          3 :                 local.SetInternal("fixedseeds");
#    1844                 :          3 :                 addrman.Add(ConvertSeeds(Params().FixedSeeds()), local);
#    1845                 :          3 :                 add_fixed_seeds = false;
#    1846                 :          3 :             }
#    1847                 :          3 :         }
#    1848                 :            : 
#    1849                 :            :         //
#    1850                 :            :         // Choose an address to connect to based on most recently seen
#    1851                 :            :         //
#    1852                 :      18859 :         CAddress addrConnect;
#    1853                 :            : 
#    1854                 :            :         // Only connect out to one peer per network group (/16 for IPv4).
#    1855                 :      18859 :         int nOutboundFullRelay = 0;
#    1856                 :      18859 :         int nOutboundBlockRelay = 0;
#    1857                 :      18859 :         std::set<std::vector<unsigned char> > setConnected;
#    1858                 :            : 
#    1859                 :      18859 :         {
#    1860                 :      18859 :             LOCK(cs_vNodes);
#    1861         [ +  + ]:      30276 :             for (const CNode* pnode : vNodes) {
#    1862         [ +  + ]:      30276 :                 if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
#    1863         [ +  + ]:      30276 :                 if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
#    1864                 :            : 
#    1865                 :            :                 // Netgroups for inbound and manual peers are not excluded because our goal here
#    1866                 :            :                 // is to not use multiple of our limited outbound slots on a single netgroup
#    1867                 :            :                 // but inbound and manual peers do not use our outbound slots. Inbound peers
#    1868                 :            :                 // also have the added issue that they could be attacker controlled and used
#    1869                 :            :                 // to prevent us from connecting to particular hosts if we used them here.
#    1870         [ -  + ]:      30276 :                 switch (pnode->m_conn_type) {
#    1871         [ +  + ]:      16722 :                     case ConnectionType::INBOUND:
#    1872         [ +  + ]:      30105 :                     case ConnectionType::MANUAL:
#    1873                 :      30105 :                         break;
#    1874         [ +  + ]:      16722 :                     case ConnectionType::OUTBOUND_FULL_RELAY:
#    1875         [ +  + ]:        171 :                     case ConnectionType::BLOCK_RELAY:
#    1876         [ -  + ]:        171 :                     case ConnectionType::ADDR_FETCH:
#    1877         [ -  + ]:        171 :                     case ConnectionType::FEELER:
#    1878                 :        171 :                         setConnected.insert(pnode->addr.GetGroup(addrman.m_asmap));
#    1879                 :      30276 :                 } // no default case, so the compiler can warn about missing cases
#    1880                 :      30276 :             }
#    1881                 :      18859 :         }
#    1882                 :            : 
#    1883                 :      18859 :         ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
#    1884                 :      18859 :         auto now = GetTime<std::chrono::microseconds>();
#    1885                 :      18859 :         bool anchor = false;
#    1886                 :      18859 :         bool fFeeler = false;
#    1887                 :            : 
#    1888                 :            :         // Determine what type of connection to open. Opening
#    1889                 :            :         // BLOCK_RELAY connections to addresses from anchors.dat gets the highest
#    1890                 :            :         // priority. Then we open OUTBOUND_FULL_RELAY priority until we
#    1891                 :            :         // meet our full-relay capacity. Then we open BLOCK_RELAY connection
#    1892                 :            :         // until we hit our block-relay-only peer limit.
#    1893                 :            :         // GetTryNewOutboundPeer() gets set when a stale tip is detected, so we
#    1894                 :            :         // try opening an additional OUTBOUND_FULL_RELAY connection. If none of
#    1895                 :            :         // these conditions are met, check to see if it's time to try an extra
#    1896                 :            :         // block-relay-only peer (to confirm our tip is current, see below) or the next_feeler
#    1897                 :            :         // timer to decide if we should open a FEELER.
#    1898                 :            : 
#    1899 [ +  + ][ +  - ]:      18859 :         if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) {
#    1900                 :          1 :             conn_type = ConnectionType::BLOCK_RELAY;
#    1901                 :          1 :             anchor = true;
#    1902         [ +  + ]:      18858 :         } else if (nOutboundFullRelay < m_max_outbound_full_relay) {
#    1903                 :            :             // OUTBOUND_FULL_RELAY
#    1904         [ +  + ]:      18845 :         } else if (nOutboundBlockRelay < m_max_outbound_block_relay) {
#    1905                 :          2 :             conn_type = ConnectionType::BLOCK_RELAY;
#    1906         [ -  + ]:         11 :         } else if (GetTryNewOutboundPeer()) {
#    1907                 :            :             // OUTBOUND_FULL_RELAY
#    1908 [ -  + ][ #  # ]:         11 :         } else if (now > next_extra_block_relay && m_start_extra_block_relay_peers) {
#    1909                 :            :             // Periodically connect to a peer (using regular outbound selection
#    1910                 :            :             // methodology from addrman) and stay connected long enough to sync
#    1911                 :            :             // headers, but not much else.
#    1912                 :            :             //
#    1913                 :            :             // Then disconnect the peer, if we haven't learned anything new.
#    1914                 :            :             //
#    1915                 :            :             // The idea is to make eclipse attacks very difficult to pull off,
#    1916                 :            :             // because every few minutes we're finding a new peer to learn headers
#    1917                 :            :             // from.
#    1918                 :            :             //
#    1919                 :            :             // This is similar to the logic for trying extra outbound (full-relay)
#    1920                 :            :             // peers, except:
#    1921                 :            :             // - we do this all the time on a poisson timer, rather than just when
#    1922                 :            :             //   our tip is stale
#    1923                 :            :             // - we potentially disconnect our next-youngest block-relay-only peer, if our
#    1924                 :            :             //   newest block-relay-only peer delivers a block more recently.
#    1925                 :            :             //   See the eviction logic in net_processing.cpp.
#    1926                 :            :             //
#    1927                 :            :             // Because we can promote these connections to block-relay-only
#    1928                 :            :             // connections, they do not get their own ConnectionType enum
#    1929                 :            :             // (similar to how we deal with extra outbound peers).
#    1930                 :          0 :             next_extra_block_relay = PoissonNextSend(now, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
#    1931                 :          0 :             conn_type = ConnectionType::BLOCK_RELAY;
#    1932         [ -  + ]:         11 :         } else if (now > next_feeler) {
#    1933                 :          0 :             next_feeler = PoissonNextSend(now, FEELER_INTERVAL);
#    1934                 :          0 :             conn_type = ConnectionType::FEELER;
#    1935                 :          0 :             fFeeler = true;
#    1936                 :         11 :         } else {
#    1937                 :            :             // skip to next iteration of while loop
#    1938                 :         11 :             continue;
#    1939                 :         11 :         }
#    1940                 :            : 
#    1941                 :      18848 :         addrman.ResolveCollisions();
#    1942                 :            : 
#    1943                 :      18848 :         int64_t nANow = GetAdjustedTime();
#    1944                 :      18848 :         int nTries = 0;
#    1945         [ +  + ]:      31321 :         while (!interruptNet)
#    1946                 :      31318 :         {
#    1947 [ +  + ][ +  + ]:      31318 :             if (anchor && !m_anchors.empty()) {
#    1948                 :          2 :                 const CAddress addr = m_anchors.back();
#    1949                 :          2 :                 m_anchors.pop_back();
#    1950 [ +  - ][ -  + ]:          2 :                 if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) ||
#         [ -  + ][ -  + ]
#    1951         [ +  - ]:          2 :                     !HasAllDesirableServiceFlags(addr.nServices) ||
#    1952         [ #  # ]:          2 :                     setConnected.count(addr.GetGroup(addrman.m_asmap))) continue;
#    1953                 :          0 :                 addrConnect = addr;
#    1954         [ #  # ]:          0 :                 LogPrint(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToString());
#    1955                 :          0 :                 break;
#    1956                 :          0 :             }
#    1957                 :            : 
#    1958                 :            :             // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
#    1959                 :            :             // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
#    1960                 :            :             // already-connected network ranges, ...) before trying new addrman addresses.
#    1961                 :      31316 :             nTries++;
#    1962         [ +  + ]:      31316 :             if (nTries > 100)
#    1963                 :         34 :                 break;
#    1964                 :            : 
#    1965                 :      31282 :             CAddrInfo addr;
#    1966                 :            : 
#    1967         [ -  + ]:      31282 :             if (fFeeler) {
#    1968                 :            :                 // First, try to get a tried table collision address. This returns
#    1969                 :            :                 // an empty (invalid) address if there are no collisions to try.
#    1970                 :          0 :                 addr = addrman.SelectTriedCollision();
#    1971                 :            : 
#    1972         [ #  # ]:          0 :                 if (!addr.IsValid()) {
#    1973                 :            :                     // No tried table collisions. Select a new table address
#    1974                 :            :                     // for our feeler.
#    1975                 :          0 :                     addr = addrman.Select(true);
#    1976         [ #  # ]:          0 :                 } else if (AlreadyConnectedToAddress(addr)) {
#    1977                 :            :                     // If test-before-evict logic would have us connect to a
#    1978                 :            :                     // peer that we're already connected to, just mark that
#    1979                 :            :                     // address as Good(). We won't be able to initiate the
#    1980                 :            :                     // connection anyway, so this avoids inadvertently evicting
#    1981                 :            :                     // a currently-connected peer.
#    1982                 :          0 :                     addrman.Good(addr);
#    1983                 :            :                     // Select a new table address for our feeler instead.
#    1984                 :          0 :                     addr = addrman.Select(true);
#    1985                 :          0 :                 }
#    1986                 :      31282 :             } else {
#    1987                 :            :                 // Not a feeler
#    1988                 :      31282 :                 addr = addrman.Select();
#    1989                 :      31282 :             }
#    1990                 :            : 
#    1991                 :            :             // Require outbound connections, other than feelers, to be to distinct network groups
#    1992 [ +  + ][ +  - ]:      31282 :             if (!fFeeler && setConnected.count(addr.GetGroup(addrman.m_asmap))) {
#                 [ +  + ]
#    1993                 :         13 :                 break;
#    1994                 :         13 :             }
#    1995                 :            : 
#    1996                 :            :             // if we selected an invalid or local address, restart
#    1997 [ +  + ][ -  + ]:      31269 :             if (!addr.IsValid() || IsLocal(addr)) {
#    1998                 :      18615 :                 break;
#    1999                 :      18615 :             }
#    2000                 :            : 
#    2001         [ -  + ]:      12654 :             if (!IsReachable(addr))
#    2002                 :          0 :                 continue;
#    2003                 :            : 
#    2004                 :            :             // only consider very recently tried nodes after 30 failed attempts
#    2005 [ -  + ][ #  # ]:      12654 :             if (nANow - addr.nLastTry < 600 && nTries < 30)
#    2006                 :          0 :                 continue;
#    2007                 :            : 
#    2008                 :            :             // for non-feelers, require all the services we'll want,
#    2009                 :            :             // for feelers, only require they be a full node (only because most
#    2010                 :            :             // SPV clients don't have a good address DB available)
#    2011 [ +  - ][ +  + ]:      12654 :             if (!fFeeler && !HasAllDesirableServiceFlags(addr.nServices)) {
#    2012                 :       3461 :                 continue;
#    2013 [ -  + ][ #  # ]:       9193 :             } else if (fFeeler && !MayHaveUsefulAddressDB(addr.nServices)) {
#    2014                 :          0 :                 continue;
#    2015                 :          0 :             }
#    2016                 :            : 
#    2017                 :            :             // Do not allow non-default ports, unless after 50 invalid
#    2018                 :            :             // addresses selected already. This is to prevent malicious peers
#    2019                 :            :             // from advertising themselves as a service on another host and
#    2020                 :            :             // port, causing a DoS attack as nodes around the network attempt
#    2021                 :            :             // to connect to it fruitlessly.
#    2022                 :            :             // Ports in I2P get special treatment, see i2p::sam::Session::Connect() in i2p.cpp.
#    2023 [ +  - ][ +  - ]:       9193 :             if (!addr.IsI2P() && addr.GetPort() != Params().GetDefaultPort() && nTries < 50) {
#                 [ +  + ]
#    2024                 :       9010 :                 continue;
#    2025                 :       9010 :             }
#    2026                 :            : 
#    2027                 :        183 :             addrConnect = addr;
#    2028                 :        183 :             break;
#    2029                 :        183 :         }
#    2030                 :            : 
#    2031         [ +  + ]:      18848 :         if (addrConnect.IsValid()) {
#    2032                 :            : 
#    2033         [ -  + ]:        183 :             if (fFeeler) {
#    2034                 :            :                 // Add small amount of random noise before connection to avoid synchronization.
#    2035                 :          0 :                 int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000);
#    2036         [ #  # ]:          0 :                 if (!interruptNet.sleep_for(std::chrono::milliseconds(randsleep)))
#    2037                 :          0 :                     return;
#    2038         [ #  # ]:          0 :                 LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString());
#    2039                 :          0 :             }
#    2040                 :            : 
#    2041                 :        183 :             OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant, nullptr, conn_type);
#    2042                 :        183 :         }
#    2043                 :      18848 :     }
#    2044                 :        617 : }
#    2045                 :            : 
#    2046                 :            : std::vector<CAddress> CConnman::GetCurrentBlockRelayOnlyConns() const
#    2047                 :        617 : {
#    2048                 :        617 :     std::vector<CAddress> ret;
#    2049                 :        617 :     LOCK(cs_vNodes);
#    2050         [ +  + ]:        634 :     for (const CNode* pnode : vNodes) {
#    2051         [ +  + ]:        634 :         if (pnode->IsBlockOnlyConn()) {
#    2052                 :         10 :             ret.push_back(pnode->addr);
#    2053                 :         10 :         }
#    2054                 :        634 :     }
#    2055                 :            : 
#    2056                 :        617 :     return ret;
#    2057                 :        617 : }
#    2058                 :            : 
#    2059                 :            : std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
#    2060                 :       6886 : {
#    2061                 :       6886 :     std::vector<AddedNodeInfo> ret;
#    2062                 :            : 
#    2063                 :       6886 :     std::list<std::string> lAddresses(0);
#    2064                 :       6886 :     {
#    2065                 :       6886 :         LOCK(cs_vAddedNodes);
#    2066                 :       6886 :         ret.reserve(vAddedNodes.size());
#    2067                 :       6886 :         std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), std::back_inserter(lAddresses));
#    2068                 :       6886 :     }
#    2069                 :            : 
#    2070                 :            : 
#    2071                 :            :     // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
#    2072                 :       6886 :     std::map<CService, bool> mapConnected;
#    2073                 :       6886 :     std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
#    2074                 :       6886 :     {
#    2075                 :       6886 :         LOCK(cs_vNodes);
#    2076         [ +  + ]:      10048 :         for (const CNode* pnode : vNodes) {
#    2077         [ +  - ]:      10048 :             if (pnode->addr.IsValid()) {
#    2078                 :      10048 :                 mapConnected[pnode->addr] = pnode->IsInboundConn();
#    2079                 :      10048 :             }
#    2080                 :      10048 :             std::string addrName = pnode->GetAddrName();
#    2081         [ +  - ]:      10048 :             if (!addrName.empty()) {
#    2082                 :      10048 :                 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(), static_cast<const CService&>(pnode->addr));
#    2083                 :      10048 :             }
#    2084                 :      10048 :         }
#    2085                 :       6886 :     }
#    2086                 :            : 
#    2087         [ +  + ]:       6886 :     for (const std::string& strAddNode : lAddresses) {
#    2088                 :          3 :         CService service(LookupNumeric(strAddNode, Params().GetDefaultPort()));
#    2089                 :          3 :         AddedNodeInfo addedNode{strAddNode, CService(), false, false};
#    2090         [ +  + ]:          3 :         if (service.IsValid()) {
#    2091                 :            :             // strAddNode is an IP:port
#    2092                 :          1 :             auto it = mapConnected.find(service);
#    2093         [ -  + ]:          1 :             if (it != mapConnected.end()) {
#    2094                 :          0 :                 addedNode.resolvedAddress = service;
#    2095                 :          0 :                 addedNode.fConnected = true;
#    2096                 :          0 :                 addedNode.fInbound = it->second;
#    2097                 :          0 :             }
#    2098                 :          2 :         } else {
#    2099                 :            :             // strAddNode is a name
#    2100                 :          2 :             auto it = mapConnectedByName.find(strAddNode);
#    2101         [ -  + ]:          2 :             if (it != mapConnectedByName.end()) {
#    2102                 :          0 :                 addedNode.resolvedAddress = it->second.second;
#    2103                 :          0 :                 addedNode.fConnected = true;
#    2104                 :          0 :                 addedNode.fInbound = it->second.first;
#    2105                 :          0 :             }
#    2106                 :          2 :         }
#    2107                 :          3 :         ret.emplace_back(std::move(addedNode));
#    2108                 :          3 :     }
#    2109                 :            : 
#    2110                 :       6886 :     return ret;
#    2111                 :       6886 : }
#    2112                 :            : 
#    2113                 :            : void CConnman::ThreadOpenAddedConnections()
#    2114                 :        618 : {
#    2115                 :       6882 :     while (true)
#    2116                 :       6882 :     {
#    2117                 :       6882 :         CSemaphoreGrant grant(*semAddnode);
#    2118                 :       6882 :         std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
#    2119                 :       6882 :         bool tried = false;
#    2120         [ +  + ]:       6882 :         for (const AddedNodeInfo& info : vInfo) {
#    2121         [ +  - ]:          2 :             if (!info.fConnected) {
#    2122         [ -  + ]:          2 :                 if (!grant.TryAcquire()) {
#    2123                 :            :                     // If we've used up our semaphore and need a new one, let's not wait here since while we are waiting
#    2124                 :            :                     // the addednodeinfo state might change.
#    2125                 :          0 :                     break;
#    2126                 :          0 :                 }
#    2127                 :          2 :                 tried = true;
#    2128                 :          2 :                 CAddress addr(CService(), NODE_NONE);
#    2129                 :          2 :                 OpenNetworkConnection(addr, false, &grant, info.strAddedNode.c_str(), ConnectionType::MANUAL);
#    2130         [ +  - ]:          2 :                 if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
#    2131                 :          2 :                     return;
#    2132                 :          2 :             }
#    2133                 :          2 :         }
#    2134                 :            :         // Retry every 60 seconds if a connection was attempted, otherwise two seconds
#    2135 [ +  + ][ -  + ]:       6882 :         if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)))
#    2136                 :        616 :             return;
#    2137                 :       6880 :     }
#    2138                 :        618 : }
#    2139                 :            : 
#    2140                 :            : // if successful, this moves the passed grant to the constructed node
#    2141                 :            : void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, ConnectionType conn_type)
#    2142                 :        552 : {
#    2143                 :        552 :     assert(conn_type != ConnectionType::INBOUND);
#    2144                 :            : 
#    2145                 :            :     //
#    2146                 :            :     // Initiate outbound network connection
#    2147                 :            :     //
#    2148         [ +  + ]:        552 :     if (interruptNet) {
#    2149                 :          1 :         return;
#    2150                 :          1 :     }
#    2151         [ -  + ]:        551 :     if (!fNetworkActive) {
#    2152                 :          0 :         return;
#    2153                 :          0 :     }
#    2154         [ +  + ]:        551 :     if (!pszDest) {
#    2155 [ +  - ][ -  + ]:        182 :         bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect));
#                 [ -  + ]
#    2156 [ -  + ][ -  + ]:        182 :         if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) {
#                 [ -  + ]
#    2157                 :          0 :             return;
#    2158                 :          0 :         }
#    2159         [ -  + ]:        369 :     } else if (FindNode(std::string(pszDest)))
#    2160                 :          0 :         return;
#    2161                 :            : 
#    2162                 :        551 :     CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
#    2163                 :            : 
#    2164         [ +  + ]:        551 :     if (!pnode)
#    2165                 :        187 :         return;
#    2166         [ +  + ]:        364 :     if (grantOutbound)
#    2167                 :         46 :         grantOutbound->MoveTo(pnode->grantOutbound);
#    2168                 :            : 
#    2169                 :        364 :     m_msgproc->InitializeNode(pnode);
#    2170                 :        364 :     {
#    2171                 :        364 :         LOCK(cs_vNodes);
#    2172                 :        364 :         vNodes.push_back(pnode);
#    2173                 :        364 :     }
#    2174                 :        364 : }
#    2175                 :            : 
#    2176                 :            : void CConnman::ThreadMessageHandler()
#    2177                 :        618 : {
#    2178         [ +  + ]:     236529 :     while (!flagInterruptMsgProc)
#    2179                 :     235921 :     {
#    2180                 :     235921 :         std::vector<CNode*> vNodesCopy;
#    2181                 :     235921 :         {
#    2182                 :     235921 :             LOCK(cs_vNodes);
#    2183                 :     235921 :             vNodesCopy = vNodes;
#    2184         [ +  + ]:     368642 :             for (CNode* pnode : vNodesCopy) {
#    2185                 :     368642 :                 pnode->AddRef();
#    2186                 :     368642 :             }
#    2187                 :     235921 :         }
#    2188                 :            : 
#    2189                 :     235921 :         bool fMoreWork = false;
#    2190                 :            : 
#    2191         [ +  + ]:     235921 :         for (CNode* pnode : vNodesCopy)
#    2192                 :     368639 :         {
#    2193         [ +  + ]:     368639 :             if (pnode->fDisconnect)
#    2194                 :         17 :                 continue;
#    2195                 :            : 
#    2196                 :            :             // Receive messages
#    2197                 :     368622 :             bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
#    2198 [ +  + ][ +  + ]:     368622 :             fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
#    2199         [ +  + ]:     368622 :             if (flagInterruptMsgProc)
#    2200                 :          6 :                 return;
#    2201                 :            :             // Send messages
#    2202                 :     368616 :             {
#    2203                 :     368616 :                 LOCK(pnode->cs_sendProcessing);
#    2204                 :     368616 :                 m_msgproc->SendMessages(pnode);
#    2205                 :     368616 :             }
#    2206                 :            : 
#    2207         [ +  + ]:     368616 :             if (flagInterruptMsgProc)
#    2208                 :          4 :                 return;
#    2209                 :     368616 :         }
#    2210                 :            : 
#    2211                 :     235921 :         {
#    2212                 :     235911 :             LOCK(cs_vNodes);
#    2213         [ +  + ]:     235911 :             for (CNode* pnode : vNodesCopy)
#    2214                 :     368625 :                 pnode->Release();
#    2215                 :     235911 :         }
#    2216                 :            : 
#    2217                 :     235911 :         WAIT_LOCK(mutexMsgProc, lock);
#    2218         [ +  + ]:     235911 :         if (!fMoreWork) {
#    2219                 :     361141 :             condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this]() EXCLUSIVE_LOCKS_REQUIRED(mutexMsgProc) { return fMsgProcWake; });
#    2220                 :     190453 :         }
#    2221                 :     235911 :         fMsgProcWake = false;
#    2222                 :     235911 :     }
#    2223                 :        618 : }
#    2224                 :            : 
#    2225                 :            : void CConnman::ThreadI2PAcceptIncoming()
#    2226                 :          1 : {
#    2227                 :          1 :     static constexpr auto err_wait_begin = 1s;
#    2228                 :          1 :     static constexpr auto err_wait_cap = 5min;
#    2229                 :          1 :     auto err_wait = err_wait_begin;
#    2230                 :            : 
#    2231                 :          1 :     bool advertising_listen_addr = false;
#    2232                 :          1 :     i2p::Connection conn;
#    2233                 :            : 
#    2234         [ +  + ]:          2 :     while (!interruptNet) {
#    2235                 :            : 
#    2236         [ +  - ]:          1 :         if (!m_i2p_sam_session->Listen(conn)) {
#    2237 [ -  + ][ #  # ]:          1 :             if (advertising_listen_addr && conn.me.IsValid()) {
#    2238                 :          0 :                 RemoveLocal(conn.me);
#    2239                 :          0 :                 advertising_listen_addr = false;
#    2240                 :          0 :             }
#    2241                 :            : 
#    2242                 :          1 :             interruptNet.sleep_for(err_wait);
#    2243         [ +  - ]:          1 :             if (err_wait < err_wait_cap) {
#    2244                 :          1 :                 err_wait *= 2;
#    2245                 :          1 :             }
#    2246                 :            : 
#    2247                 :          1 :             continue;
#    2248                 :          1 :         }
#    2249                 :            : 
#    2250         [ #  # ]:          0 :         if (!advertising_listen_addr) {
#    2251                 :          0 :             AddLocal(conn.me, LOCAL_MANUAL);
#    2252                 :          0 :             advertising_listen_addr = true;
#    2253                 :          0 :         }
#    2254                 :            : 
#    2255         [ #  # ]:          0 :         if (!m_i2p_sam_session->Accept(conn)) {
#    2256                 :          0 :             continue;
#    2257                 :          0 :         }
#    2258                 :            : 
#    2259                 :          0 :         CreateNodeFromAcceptedSocket(conn.sock->Release(), NetPermissionFlags::None,
#    2260                 :          0 :                                      CAddress{conn.me, NODE_NONE}, CAddress{conn.peer, NODE_NONE});
#    2261                 :          0 :     }
#    2262                 :          1 : }
#    2263                 :            : 
#    2264                 :            : bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError, NetPermissionFlags permissions)
#    2265                 :       1237 : {
#    2266                 :       1237 :     int nOne = 1;
#    2267                 :            : 
#    2268                 :            :     // Create socket for listening for incoming connections
#    2269                 :       1237 :     struct sockaddr_storage sockaddr;
#    2270                 :       1237 :     socklen_t len = sizeof(sockaddr);
#    2271         [ -  + ]:       1237 :     if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
#    2272                 :          0 :     {
#    2273                 :          0 :         strError = strprintf(Untranslated("Error: Bind address family for %s not supported"), addrBind.ToString());
#    2274                 :          0 :         LogPrintf("%s\n", strError.original);
#    2275                 :          0 :         return false;
#    2276                 :          0 :     }
#    2277                 :            : 
#    2278                 :       1237 :     std::unique_ptr<Sock> sock = CreateSock(addrBind);
#    2279         [ -  + ]:       1237 :     if (!sock) {
#    2280                 :          0 :         strError = strprintf(Untranslated("Error: Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
#    2281                 :          0 :         LogPrintf("%s\n", strError.original);
#    2282                 :          0 :         return false;
#    2283                 :          0 :     }
#    2284                 :            : 
#    2285                 :            :     // Allow binding if the port is still in TIME_WAIT state after
#    2286                 :            :     // the program was closed and restarted.
#    2287                 :       1237 :     setsockopt(sock->Get(), SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, sizeof(int));
#    2288                 :            : 
#    2289                 :            :     // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
#    2290                 :            :     // and enable it by default or not. Try to enable it, if possible.
#    2291         [ +  + ]:       1237 :     if (addrBind.IsIPv6()) {
#    2292                 :          1 : #ifdef IPV6_V6ONLY
#    2293                 :          1 :         setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_arg_type)&nOne, sizeof(int));
#    2294                 :          1 : #endif
#    2295                 :            : #ifdef WIN32
#    2296                 :            :         int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
#    2297                 :            :         setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
#    2298                 :            : #endif
#    2299                 :          1 :     }
#    2300                 :            : 
#    2301         [ +  + ]:       1237 :     if (::bind(sock->Get(), (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
#    2302                 :       1237 :     {
#    2303                 :        486 :         int nErr = WSAGetLastError();
#    2304         [ +  - ]:        486 :         if (nErr == WSAEADDRINUSE)
#    2305                 :        486 :             strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
#    2306                 :          0 :         else
#    2307                 :          0 :             strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
#    2308                 :        486 :         LogPrintf("%s\n", strError.original);
#    2309                 :        486 :         return false;
#    2310                 :        486 :     }
#    2311                 :        751 :     LogPrintf("Bound to %s\n", addrBind.ToString());
#    2312                 :            : 
#    2313                 :            :     // Listen for incoming connections
#    2314         [ -  + ]:        751 :     if (listen(sock->Get(), SOMAXCONN) == SOCKET_ERROR)
#    2315                 :        751 :     {
#    2316                 :          0 :         strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
#    2317                 :          0 :         LogPrintf("%s\n", strError.original);
#    2318                 :          0 :         return false;
#    2319                 :          0 :     }
#    2320                 :            : 
#    2321                 :        751 :     vhListenSocket.push_back(ListenSocket(sock->Release(), permissions));
#    2322                 :        751 :     return true;
#    2323                 :        751 : }
#    2324                 :            : 
#    2325                 :            : void Discover()
#    2326                 :        621 : {
#    2327         [ +  - ]:        621 :     if (!fDiscover)
#    2328                 :        621 :         return;
#    2329                 :            : 
#    2330                 :            : #ifdef WIN32
#    2331                 :            :     // Get local host IP
#    2332                 :            :     char pszHostName[256] = "";
#    2333                 :            :     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
#    2334                 :            :     {
#    2335                 :            :         std::vector<CNetAddr> vaddr;
#    2336                 :            :         if (LookupHost(pszHostName, vaddr, 0, true))
#    2337                 :            :         {
#    2338                 :            :             for (const CNetAddr &addr : vaddr)
#    2339                 :            :             {
#    2340                 :            :                 if (AddLocal(addr, LOCAL_IF))
#    2341                 :            :                     LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
#    2342                 :            :             }
#    2343                 :            :         }
#    2344                 :            :     }
#    2345                 :            : #elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
#    2346                 :            :     // Get local host ip
#    2347                 :          0 :     struct ifaddrs* myaddrs;
#    2348         [ #  # ]:          0 :     if (getifaddrs(&myaddrs) == 0)
#    2349                 :          0 :     {
#    2350         [ #  # ]:          0 :         for (struct ifaddrs* ifa = myaddrs; ifa != nullptr; ifa = ifa->ifa_next)
#    2351                 :          0 :         {
#    2352         [ #  # ]:          0 :             if (ifa->ifa_addr == nullptr) continue;
#    2353         [ #  # ]:          0 :             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
#    2354         [ #  # ]:          0 :             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
#    2355         [ #  # ]:          0 :             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
#    2356         [ #  # ]:          0 :             if (ifa->ifa_addr->sa_family == AF_INET)
#    2357                 :          0 :             {
#    2358                 :          0 :                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
#    2359                 :          0 :                 CNetAddr addr(s4->sin_addr);
#    2360         [ #  # ]:          0 :                 if (AddLocal(addr, LOCAL_IF))
#    2361                 :          0 :                     LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
#    2362                 :          0 :             }
#    2363         [ #  # ]:          0 :             else if (ifa->ifa_addr->sa_family == AF_INET6)
#    2364                 :          0 :             {
#    2365                 :          0 :                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
#    2366                 :          0 :                 CNetAddr addr(s6->sin6_addr);
#    2367         [ #  # ]:          0 :                 if (AddLocal(addr, LOCAL_IF))
#    2368                 :          0 :                     LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
#    2369                 :          0 :             }
#    2370                 :          0 :         }
#    2371                 :          0 :         freeifaddrs(myaddrs);
#    2372                 :          0 :     }
#    2373                 :          0 : #endif
#    2374                 :          0 : }
#    2375                 :            : 
#    2376                 :            : void CConnman::SetNetworkActive(bool active)
#    2377                 :        805 : {
#    2378                 :        805 :     LogPrintf("%s: %s\n", __func__, active);
#    2379                 :            : 
#    2380         [ +  + ]:        805 :     if (fNetworkActive == active) {
#    2381                 :        795 :         return;
#    2382                 :        795 :     }
#    2383                 :            : 
#    2384                 :         10 :     fNetworkActive = active;
#    2385                 :            : 
#    2386                 :         10 :     uiInterface.NotifyNetworkActiveChanged(fNetworkActive);
#    2387                 :         10 : }
#    2388                 :            : 
#    2389                 :            : CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In, CAddrMan& addrman_in, bool network_active)
#    2390                 :            :     : addrman(addrman_in), nSeed0(nSeed0In), nSeed1(nSeed1In)
#    2391                 :        798 : {
#    2392                 :        798 :     SetTryNewOutboundPeer(false);
#    2393                 :            : 
#    2394                 :        798 :     Options connOptions;
#    2395                 :        798 :     Init(connOptions);
#    2396                 :        798 :     SetNetworkActive(network_active);
#    2397                 :        798 : }
#    2398                 :            : 
#    2399                 :            : NodeId CConnman::GetNewNodeId()
#    2400                 :        976 : {
#    2401                 :        976 :     return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
#    2402                 :        976 : }
#    2403                 :            : 
#    2404                 :            : 
#    2405                 :       1237 : bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) {
#    2406 [ +  + ][ -  + ]:       1237 :     if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) {
#    2407                 :          0 :         return false;
#    2408                 :          0 :     }
#    2409                 :       1237 :     bilingual_str strError;
#    2410         [ +  + ]:       1237 :     if (!BindListenPort(addr, strError, permissions)) {
#    2411 [ -  + ][ #  # ]:        486 :         if ((flags & BF_REPORT_ERROR) && clientInterface) {
#    2412                 :          0 :             clientInterface->ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR);
#    2413                 :          0 :         }
#    2414                 :        486 :         return false;
#    2415                 :        486 :     }
#    2416                 :            : 
#    2417 [ -  + ][ #  # ]:        751 :     if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !NetPermissions::HasFlag(permissions, NetPermissionFlags::NoBan)) {
#         [ #  # ][ #  # ]
#    2418                 :          0 :         AddLocal(addr, LOCAL_BIND);
#    2419                 :          0 :     }
#    2420                 :            : 
#    2421                 :        751 :     return true;
#    2422                 :        751 : }
#    2423                 :            : 
#    2424                 :            : bool CConnman::InitBinds(
#    2425                 :            :     const std::vector<CService>& binds,
#    2426                 :            :     const std::vector<NetWhitebindPermissions>& whiteBinds,
#    2427                 :            :     const std::vector<CService>& onion_binds)
#    2428                 :        618 : {
#    2429                 :        618 :     bool fBound = false;
#    2430         [ +  + ]:        618 :     for (const auto& addrBind : binds) {
#    2431                 :        616 :         fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR), NetPermissionFlags::None);
#    2432                 :        616 :     }
#    2433         [ +  + ]:        618 :     for (const auto& addrBind : whiteBinds) {
#    2434                 :          1 :         fBound |= Bind(addrBind.m_service, (BF_EXPLICIT | BF_REPORT_ERROR), addrBind.m_flags);
#    2435                 :          1 :     }
#    2436 [ +  + ][ +  + ]:        618 :     if (binds.empty() && whiteBinds.empty()) {
#    2437                 :          1 :         struct in_addr inaddr_any;
#    2438                 :          1 :         inaddr_any.s_addr = htonl(INADDR_ANY);
#    2439                 :          1 :         struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
#    2440                 :          1 :         fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::None);
#    2441         [ -  + ]:          1 :         fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::None);
#    2442                 :          1 :     }
#    2443                 :            : 
#    2444         [ +  + ]:        618 :     for (const auto& addr_bind : onion_binds) {
#    2445                 :        618 :         fBound |= Bind(addr_bind, BF_EXPLICIT | BF_DONT_ADVERTISE, NetPermissionFlags::None);
#    2446                 :        618 :     }
#    2447                 :            : 
#    2448                 :        618 :     return fBound;
#    2449                 :        618 : }
#    2450                 :            : 
#    2451                 :            : bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
#    2452                 :        618 : {
#    2453                 :        618 :     Init(connOptions);
#    2454                 :            : 
#    2455 [ +  - ][ -  + ]:        618 :     if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) {
#    2456         [ #  # ]:          0 :         if (clientInterface) {
#    2457                 :          0 :             clientInterface->ThreadSafeMessageBox(
#    2458                 :          0 :                 _("Failed to listen on any port. Use -listen=0 if you want this."),
#    2459                 :          0 :                 "", CClientUIInterface::MSG_ERROR);
#    2460                 :          0 :         }
#    2461                 :          0 :         return false;
#    2462                 :          0 :     }
#    2463                 :            : 
#    2464                 :        618 :     proxyType i2p_sam;
#    2465         [ +  + ]:        618 :     if (GetProxy(NET_I2P, i2p_sam)) {
#    2466                 :          2 :         m_i2p_sam_session = std::make_unique<i2p::sam::Session>(gArgs.GetDataDirNet() / "i2p_private_key",
#    2467                 :          2 :                                                                 i2p_sam.proxy, &interruptNet);
#    2468                 :          2 :     }
#    2469                 :            : 
#    2470         [ -  + ]:        618 :     for (const auto& strDest : connOptions.vSeedNodes) {
#    2471                 :          0 :         AddAddrFetch(strDest);
#    2472                 :          0 :     }
#    2473                 :            : 
#    2474         [ +  - ]:        618 :     if (clientInterface) {
#    2475                 :        618 :         clientInterface->InitMessage(_("Loading P2P addresses…").translated);
#    2476                 :        618 :     }
#    2477                 :            :     // Load addresses from peers.dat
#    2478                 :        618 :     int64_t nStart = GetTimeMillis();
#    2479                 :        618 :     {
#    2480                 :        618 :         CAddrDB adb;
#    2481         [ +  + ]:        618 :         if (adb.Read(addrman))
#    2482                 :        618 :             LogPrintf("Loaded %i addresses from peers.dat  %dms\n", addrman.size(), GetTimeMillis() - nStart);
#    2483                 :        618 :         else {
#    2484                 :        371 :             addrman.Clear(); // Addrman can be in an inconsistent state after failure, reset it
#    2485                 :        371 :             LogPrintf("Recreating peers.dat\n");
#    2486                 :        371 :             DumpAddresses();
#    2487                 :        371 :         }
#    2488                 :        618 :     }
#    2489                 :            : 
#    2490         [ +  + ]:        618 :     if (m_use_addrman_outgoing) {
#    2491                 :            :         // Load addresses from anchors.dat
#    2492                 :        617 :         m_anchors = ReadAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME);
#    2493         [ -  + ]:        617 :         if (m_anchors.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
#    2494                 :          0 :             m_anchors.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
#    2495                 :          0 :         }
#    2496                 :        617 :         LogPrintf("%i block-relay-only anchors will be tried for connections.\n", m_anchors.size());
#    2497                 :        617 :     }
#    2498                 :            : 
#    2499                 :        618 :     uiInterface.InitMessage(_("Starting network threads…").translated);
#    2500                 :            : 
#    2501                 :        618 :     fAddressesInitialized = true;
#    2502                 :            : 
#    2503         [ +  - ]:        618 :     if (semOutbound == nullptr) {
#    2504                 :            :         // initialize semaphore
#    2505                 :        618 :         semOutbound = std::make_unique<CSemaphore>(std::min(m_max_outbound, nMaxConnections));
#    2506                 :        618 :     }
#    2507         [ +  - ]:        618 :     if (semAddnode == nullptr) {
#    2508                 :            :         // initialize semaphore
#    2509                 :        618 :         semAddnode = std::make_unique<CSemaphore>(nMaxAddnode);
#    2510                 :        618 :     }
#    2511                 :            : 
#    2512                 :            :     //
#    2513                 :            :     // Start threads
#    2514                 :            :     //
#    2515                 :        618 :     assert(m_msgproc);
#    2516                 :        618 :     InterruptSocks5(false);
#    2517                 :        618 :     interruptNet.reset();
#    2518                 :        618 :     flagInterruptMsgProc = false;
#    2519                 :            : 
#    2520                 :        618 :     {
#    2521                 :        618 :         LOCK(mutexMsgProc);
#    2522                 :        618 :         fMsgProcWake = false;
#    2523                 :        618 :     }
#    2524                 :            : 
#    2525                 :            :     // Send and receive from sockets, accept connections
#    2526                 :        618 :     threadSocketHandler = std::thread(&util::TraceThread, "net", [this] { ThreadSocketHandler(); });
#    2527                 :            : 
#    2528         [ +  + ]:        618 :     if (!gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED))
#    2529                 :        618 :         LogPrintf("DNS seeding disabled\n");
#    2530                 :        618 :     else
#    2531                 :        618 :         threadDNSAddressSeed = std::thread(&util::TraceThread, "dnsseed", [this] { ThreadDNSAddressSeed(); });
#    2532                 :            : 
#    2533                 :            :     // Initiate manual connections
#    2534                 :        618 :     threadOpenAddedConnections = std::thread(&util::TraceThread, "addcon", [this] { ThreadOpenAddedConnections(); });
#    2535                 :            : 
#    2536 [ +  + ][ -  + ]:        618 :     if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
#    2537         [ #  # ]:          0 :         if (clientInterface) {
#    2538                 :          0 :             clientInterface->ThreadSafeMessageBox(
#    2539                 :          0 :                 _("Cannot provide specific connections and have addrman find outgoing connections at the same."),
#    2540                 :          0 :                 "", CClientUIInterface::MSG_ERROR);
#    2541                 :          0 :         }
#    2542                 :          0 :         return false;
#    2543                 :          0 :     }
#    2544 [ +  + ][ +  - ]:        618 :     if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
#    2545                 :        618 :         threadOpenConnections = std::thread(
#    2546                 :        618 :             &util::TraceThread, "opencon",
#    2547                 :        618 :             [this, connect = connOptions.m_specified_outgoing] { ThreadOpenConnections(connect); });
#    2548                 :        618 :     }
#    2549                 :            : 
#    2550                 :            :     // Process messages
#    2551                 :        618 :     threadMessageHandler = std::thread(&util::TraceThread, "msghand", [this] { ThreadMessageHandler(); });
#    2552                 :            : 
#    2553 [ +  + ][ +  + ]:        618 :     if (connOptions.m_i2p_accept_incoming && m_i2p_sam_session.get() != nullptr) {
#    2554                 :          1 :         threadI2PAcceptIncoming =
#    2555                 :          1 :             std::thread(&util::TraceThread, "i2paccept", [this] { ThreadI2PAcceptIncoming(); });
#    2556                 :          1 :     }
#    2557                 :            : 
#    2558                 :            :     // Dump network addresses
#    2559                 :        618 :     scheduler.scheduleEvery([this] { DumpAddresses(); }, DUMP_PEERS_INTERVAL);
#    2560                 :            : 
#    2561                 :        618 :     return true;
#    2562                 :        618 : }
#    2563                 :            : 
#    2564                 :            : class CNetCleanup
#    2565                 :            : {
#    2566                 :            : public:
#    2567                 :        690 :     CNetCleanup() {}
#    2568                 :            : 
#    2569                 :            :     ~CNetCleanup()
#    2570                 :          0 :     {
#    2571                 :            : #ifdef WIN32
#    2572                 :            :         // Shutdown Windows Sockets
#    2573                 :            :         WSACleanup();
#    2574                 :            : #endif
#    2575                 :          0 :     }
#    2576                 :            : };
#    2577                 :            : static CNetCleanup instance_of_cnetcleanup;
#    2578                 :            : 
#    2579                 :            : void CConnman::Interrupt()
#    2580                 :       1433 : {
#    2581                 :       1433 :     {
#    2582                 :       1433 :         LOCK(mutexMsgProc);
#    2583                 :       1433 :         flagInterruptMsgProc = true;
#    2584                 :       1433 :     }
#    2585                 :       1433 :     condMsgProc.notify_all();
#    2586                 :            : 
#    2587                 :       1433 :     interruptNet();
#    2588                 :       1433 :     InterruptSocks5(true);
#    2589                 :            : 
#    2590         [ +  + ]:       1433 :     if (semOutbound) {
#    2591         [ +  + ]:       7416 :         for (int i=0; i<m_max_outbound; i++) {
#    2592                 :       6798 :             semOutbound->post();
#    2593                 :       6798 :         }
#    2594                 :        618 :     }
#    2595                 :            : 
#    2596         [ +  + ]:       1433 :     if (semAddnode) {
#    2597         [ +  + ]:       5562 :         for (int i=0; i<nMaxAddnode; i++) {
#    2598                 :       4944 :             semAddnode->post();
#    2599                 :       4944 :         }
#    2600                 :        618 :     }
#    2601                 :       1433 : }
#    2602                 :            : 
#    2603                 :            : void CConnman::StopThreads()
#    2604                 :       1433 : {
#    2605         [ +  + ]:       1433 :     if (threadI2PAcceptIncoming.joinable()) {
#    2606                 :          1 :         threadI2PAcceptIncoming.join();
#    2607                 :          1 :     }
#    2608         [ +  + ]:       1433 :     if (threadMessageHandler.joinable())
#    2609                 :        618 :         threadMessageHandler.join();
#    2610         [ +  + ]:       1433 :     if (threadOpenConnections.joinable())
#    2611                 :        618 :         threadOpenConnections.join();
#    2612         [ +  + ]:       1433 :     if (threadOpenAddedConnections.joinable())
#    2613                 :        618 :         threadOpenAddedConnections.join();
#    2614         [ +  + ]:       1433 :     if (threadDNSAddressSeed.joinable())
#    2615                 :          1 :         threadDNSAddressSeed.join();
#    2616         [ +  + ]:       1433 :     if (threadSocketHandler.joinable())
#    2617                 :        618 :         threadSocketHandler.join();
#    2618                 :       1433 : }
#    2619                 :            : 
#    2620                 :            : void CConnman::StopNodes()
#    2621                 :       1433 : {
#    2622         [ +  + ]:       1433 :     if (fAddressesInitialized) {
#    2623                 :        618 :         DumpAddresses();
#    2624                 :        618 :         fAddressesInitialized = false;
#    2625                 :            : 
#    2626         [ +  + ]:        618 :         if (m_use_addrman_outgoing) {
#    2627                 :            :             // Anchor connections are only dumped during clean shutdown.
#    2628                 :        617 :             std::vector<CAddress> anchors_to_dump = GetCurrentBlockRelayOnlyConns();
#    2629         [ -  + ]:        617 :             if (anchors_to_dump.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
#    2630                 :          0 :                 anchors_to_dump.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
#    2631                 :          0 :             }
#    2632                 :        617 :             DumpAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME, anchors_to_dump);
#    2633                 :        617 :         }
#    2634                 :        618 :     }
#    2635                 :            : 
#    2636                 :            :     // Delete peer connections.
#    2637                 :       1433 :     std::vector<CNode*> nodes;
#    2638                 :       1433 :     WITH_LOCK(cs_vNodes, nodes.swap(vNodes));
#    2639         [ +  + ]:       1433 :     for (CNode* pnode : nodes) {
#    2640                 :        634 :         pnode->CloseSocketDisconnect();
#    2641                 :        634 :         DeleteNode(pnode);
#    2642                 :        634 :     }
#    2643                 :            : 
#    2644                 :            :     // Close listening sockets.
#    2645         [ +  + ]:       1433 :     for (ListenSocket& hListenSocket : vhListenSocket) {
#    2646         [ +  - ]:        751 :         if (hListenSocket.socket != INVALID_SOCKET) {
#    2647         [ -  + ]:        751 :             if (!CloseSocket(hListenSocket.socket)) {
#    2648                 :          0 :                 LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
#    2649                 :          0 :             }
#    2650                 :        751 :         }
#    2651                 :        751 :     }
#    2652                 :            : 
#    2653         [ -  + ]:       1433 :     for (CNode* pnode : vNodesDisconnected) {
#    2654                 :          0 :         DeleteNode(pnode);
#    2655                 :          0 :     }
#    2656                 :       1433 :     vNodesDisconnected.clear();
#    2657                 :       1433 :     vhListenSocket.clear();
#    2658                 :       1433 :     semOutbound.reset();
#    2659                 :       1433 :     semAddnode.reset();
#    2660                 :       1433 : }
#    2661                 :            : 
#    2662                 :            : void CConnman::DeleteNode(CNode* pnode)
#    2663                 :        976 : {
#    2664                 :        976 :     assert(pnode);
#    2665                 :        976 :     m_msgproc->FinalizeNode(*pnode);
#    2666                 :        976 :     delete pnode;
#    2667                 :        976 : }
#    2668                 :            : 
#    2669                 :            : CConnman::~CConnman()
#    2670                 :        798 : {
#    2671                 :        798 :     Interrupt();
#    2672                 :        798 :     Stop();
#    2673                 :        798 : }
#    2674                 :            : 
#    2675                 :            : std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
#    2676                 :        241 : {
#    2677                 :        241 :     std::vector<CAddress> addresses = addrman.GetAddr(max_addresses, max_pct, network);
#    2678         [ +  - ]:        241 :     if (m_banman) {
#    2679                 :        241 :         addresses.erase(std::remove_if(addresses.begin(), addresses.end(),
#    2680 [ -  + ][ -  + ]:      19828 :                         [this](const CAddress& addr){return m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr);}),
#    2681                 :        241 :                         addresses.end());
#    2682                 :        241 :     }
#    2683                 :        241 :     return addresses;
#    2684                 :        241 : }
#    2685                 :            : 
#    2686                 :            : std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct)
#    2687                 :        306 : {
#    2688                 :        306 :     auto local_socket_bytes = requestor.addrBind.GetAddrBytes();
#    2689                 :        306 :     uint64_t cache_id = GetDeterministicRandomizer(RANDOMIZER_ID_ADDRCACHE)
#    2690                 :        306 :         .Write(requestor.addr.GetNetwork())
#    2691                 :        306 :         .Write(local_socket_bytes.data(), local_socket_bytes.size())
#    2692                 :        306 :         .Finalize();
#    2693                 :        306 :     const auto current_time = GetTime<std::chrono::microseconds>();
#    2694                 :        306 :     auto r = m_addr_response_caches.emplace(cache_id, CachedAddrResponse{});
#    2695                 :        306 :     CachedAddrResponse& cache_entry = r.first->second;
#    2696         [ +  + ]:        306 :     if (cache_entry.m_cache_entry_expiration < current_time) { // If emplace() added new one it has expiration 0.
#    2697                 :        229 :         cache_entry.m_addrs_response_cache = GetAddresses(max_addresses, max_pct, /* network */ std::nullopt);
#    2698                 :            :         // Choosing a proper cache lifetime is a trade-off between the privacy leak minimization
#    2699                 :            :         // and the usefulness of ADDR responses to honest users.
#    2700                 :            :         //
#    2701                 :            :         // Longer cache lifetime makes it more difficult for an attacker to scrape
#    2702                 :            :         // enough AddrMan data to maliciously infer something useful.
#    2703                 :            :         // By the time an attacker scraped enough AddrMan records, most of
#    2704                 :            :         // the records should be old enough to not leak topology info by
#    2705                 :            :         // e.g. analyzing real-time changes in timestamps.
#    2706                 :            :         //
#    2707                 :            :         // It takes only several hundred requests to scrape everything from an AddrMan containing 100,000 nodes,
#    2708                 :            :         // so ~24 hours of cache lifetime indeed makes the data less inferable by the time
#    2709                 :            :         // most of it could be scraped (considering that timestamps are updated via
#    2710                 :            :         // ADDR self-announcements and when nodes communicate).
#    2711                 :            :         // We also should be robust to those attacks which may not require scraping *full* victim's AddrMan
#    2712                 :            :         // (because even several timestamps of the same handful of nodes may leak privacy).
#    2713                 :            :         //
#    2714                 :            :         // On the other hand, longer cache lifetime makes ADDR responses
#    2715                 :            :         // outdated and less useful for an honest requestor, e.g. if most nodes
#    2716                 :            :         // in the ADDR response are no longer active.
#    2717                 :            :         //
#    2718                 :            :         // However, the churn in the network is known to be rather low. Since we consider
#    2719                 :            :         // nodes to be "terrible" (see IsTerrible()) if the timestamps are older than 30 days,
#    2720                 :            :         // max. 24 hours of "penalty" due to cache shouldn't make any meaningful difference
#    2721                 :            :         // in terms of the freshness of the response.
#    2722                 :        229 :         cache_entry.m_cache_entry_expiration = current_time + std::chrono::hours(21) + GetRandMillis(std::chrono::hours(6));
#    2723                 :        229 :     }
#    2724                 :        306 :     return cache_entry.m_addrs_response_cache;
#    2725                 :        306 : }
#    2726                 :            : 
#    2727                 :            : bool CConnman::AddNode(const std::string& strNode)
#    2728                 :          2 : {
#    2729                 :          2 :     LOCK(cs_vAddedNodes);
#    2730         [ +  + ]:          2 :     for (const std::string& it : vAddedNodes) {
#    2731         [ +  - ]:          1 :         if (strNode == it) return false;
#    2732                 :          1 :     }
#    2733                 :            : 
#    2734                 :          2 :     vAddedNodes.push_back(strNode);
#    2735                 :          1 :     return true;
#    2736                 :          2 : }
#    2737                 :            : 
#    2738                 :            : bool CConnman::RemoveAddedNode(const std::string& strNode)
#    2739                 :          2 : {
#    2740                 :          2 :     LOCK(cs_vAddedNodes);
#    2741         [ +  + ]:          2 :     for(std::vector<std::string>::iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) {
#    2742         [ +  - ]:          1 :         if (strNode == *it) {
#    2743                 :          1 :             vAddedNodes.erase(it);
#    2744                 :          1 :             return true;
#    2745                 :          1 :         }
#    2746                 :          1 :     }
#    2747                 :          2 :     return false;
#    2748                 :          2 : }
#    2749                 :            : 
#    2750                 :            : size_t CConnman::GetNodeCount(ConnectionDirection flags) const
#    2751                 :        182 : {
#    2752                 :        182 :     LOCK(cs_vNodes);
#    2753         [ +  + ]:        182 :     if (flags == ConnectionDirection::Both) // Shortcut if we want total
#    2754                 :         64 :         return vNodes.size();
#    2755                 :            : 
#    2756                 :        118 :     int nNum = 0;
#    2757         [ +  + ]:        234 :     for (const auto& pnode : vNodes) {
#    2758 [ +  + ][ +  + ]:        234 :         if (flags & (pnode->IsInboundConn() ? ConnectionDirection::In : ConnectionDirection::Out)) {
#    2759                 :        117 :             nNum++;
#    2760                 :        117 :         }
#    2761                 :        234 :     }
#    2762                 :            : 
#    2763                 :        118 :     return nNum;
#    2764                 :        118 : }
#    2765                 :            : 
#    2766                 :            : void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats) const
#    2767                 :       5332 : {
#    2768                 :       5332 :     vstats.clear();
#    2769                 :       5332 :     LOCK(cs_vNodes);
#    2770                 :       5332 :     vstats.reserve(vNodes.size());
#    2771         [ +  + ]:       9658 :     for (CNode* pnode : vNodes) {
#    2772                 :       9658 :         vstats.emplace_back();
#    2773                 :       9658 :         pnode->copyStats(vstats.back(), addrman.m_asmap);
#    2774                 :       9658 :     }
#    2775                 :       5332 : }
#    2776                 :            : 
#    2777                 :            : bool CConnman::DisconnectNode(const std::string& strNode)
#    2778                 :          2 : {
#    2779                 :          2 :     LOCK(cs_vNodes);
#    2780         [ +  + ]:          2 :     if (CNode* pnode = FindNode(strNode)) {
#    2781 [ +  - ][ -  + ]:          1 :         LogPrint(BCLog::NET, "disconnect by address%s matched peer=%d; disconnecting\n", (fLogIPs ? strprintf("=%s", strNode) : ""), pnode->GetId());
#    2782                 :          1 :         pnode->fDisconnect = true;
#    2783                 :          1 :         return true;
#    2784                 :          1 :     }
#    2785                 :          1 :     return false;
#    2786                 :          1 : }
#    2787                 :            : 
#    2788                 :            : bool CConnman::DisconnectNode(const CSubNet& subnet)
#    2789                 :         30 : {
#    2790                 :         30 :     bool disconnected = false;
#    2791                 :         30 :     LOCK(cs_vNodes);
#    2792         [ +  + ]:         30 :     for (CNode* pnode : vNodes) {
#    2793         [ +  + ]:         17 :         if (subnet.Match(pnode->addr)) {
#    2794 [ +  - ][ -  + ]:         10 :             LogPrint(BCLog::NET, "disconnect by subnet%s matched peer=%d; disconnecting\n", (fLogIPs ? strprintf("=%s", subnet.ToString()) : ""), pnode->GetId());
#    2795                 :         10 :             pnode->fDisconnect = true;
#    2796                 :         10 :             disconnected = true;
#    2797                 :         10 :         }
#    2798                 :         17 :     }
#    2799                 :         30 :     return disconnected;
#    2800                 :         30 : }
#    2801                 :            : 
#    2802                 :            : bool CConnman::DisconnectNode(const CNetAddr& addr)
#    2803                 :         16 : {
#    2804                 :         16 :     return DisconnectNode(CSubNet(addr));
#    2805                 :         16 : }
#    2806                 :            : 
#    2807                 :            : bool CConnman::DisconnectNode(NodeId id)
#    2808                 :         32 : {
#    2809                 :         32 :     LOCK(cs_vNodes);
#    2810         [ +  - ]:         50 :     for(CNode* pnode : vNodes) {
#    2811         [ +  + ]:         50 :         if (id == pnode->GetId()) {
#    2812         [ +  - ]:         32 :             LogPrint(BCLog::NET, "disconnect by id peer=%d; disconnecting\n", pnode->GetId());
#    2813                 :         32 :             pnode->fDisconnect = true;
#    2814                 :         32 :             return true;
#    2815                 :         32 :         }
#    2816                 :         50 :     }
#    2817                 :         32 :     return false;
#    2818                 :         32 : }
#    2819                 :            : 
#    2820                 :            : void CConnman::RecordBytesRecv(uint64_t bytes)
#    2821                 :     130090 : {
#    2822                 :     130090 :     LOCK(cs_totalBytesRecv);
#    2823                 :     130090 :     nTotalBytesRecv += bytes;
#    2824                 :     130090 : }
#    2825                 :            : 
#    2826                 :            : void CConnman::RecordBytesSent(uint64_t bytes)
#    2827                 :     117505 : {
#    2828                 :     117505 :     LOCK(cs_totalBytesSent);
#    2829                 :     117505 :     nTotalBytesSent += bytes;
#    2830                 :            : 
#    2831                 :     117505 :     const auto now = GetTime<std::chrono::seconds>();
#    2832         [ +  + ]:     117505 :     if (nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME < now)
#    2833                 :        387 :     {
#    2834                 :            :         // timeframe expired, reset cycle
#    2835                 :        387 :         nMaxOutboundCycleStartTime = now;
#    2836                 :        387 :         nMaxOutboundTotalBytesSentInCycle = 0;
#    2837                 :        387 :     }
#    2838                 :            : 
#    2839                 :            :     // TODO, exclude peers with download permission
#    2840                 :     117505 :     nMaxOutboundTotalBytesSentInCycle += bytes;
#    2841                 :     117505 : }
#    2842                 :            : 
#    2843                 :            : uint64_t CConnman::GetMaxOutboundTarget() const
#    2844                 :          7 : {
#    2845                 :          7 :     LOCK(cs_totalBytesSent);
#    2846                 :          7 :     return nMaxOutboundLimit;
#    2847                 :          7 : }
#    2848                 :            : 
#    2849                 :            : std::chrono::seconds CConnman::GetMaxOutboundTimeframe() const
#    2850                 :          7 : {
#    2851                 :          7 :     return MAX_UPLOAD_TIMEFRAME;
#    2852                 :          7 : }
#    2853                 :            : 
#    2854                 :            : std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle() const
#    2855                 :       1109 : {
#    2856                 :       1109 :     LOCK(cs_totalBytesSent);
#    2857         [ +  + ]:       1109 :     if (nMaxOutboundLimit == 0)
#    2858                 :          7 :         return 0s;
#    2859                 :            : 
#    2860         [ -  + ]:       1102 :     if (nMaxOutboundCycleStartTime.count() == 0)
#    2861                 :          0 :         return MAX_UPLOAD_TIMEFRAME;
#    2862                 :            : 
#    2863                 :       1102 :     const std::chrono::seconds cycleEndTime = nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME;
#    2864                 :       1102 :     const auto now = GetTime<std::chrono::seconds>();
#    2865         [ -  + ]:       1102 :     return (cycleEndTime < now) ? 0s : cycleEndTime - now;
#    2866                 :       1102 : }
#    2867                 :            : 
#    2868                 :            : bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit) const
#    2869                 :      19411 : {
#    2870                 :      19411 :     LOCK(cs_totalBytesSent);
#    2871         [ +  + ]:      19411 :     if (nMaxOutboundLimit == 0)
#    2872                 :      18309 :         return false;
#    2873                 :            : 
#    2874         [ +  - ]:       1102 :     if (historicalBlockServingLimit)
#    2875                 :       1102 :     {
#    2876                 :            :         // keep a large enough buffer to at least relay each block once
#    2877                 :       1102 :         const std::chrono::seconds timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
#    2878                 :       1102 :         const uint64_t buffer = timeLeftInCycle / std::chrono::minutes{10} * MAX_BLOCK_SERIALIZED_SIZE;
#    2879 [ +  + ][ +  + ]:       1102 :         if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
#    2880                 :        823 :             return true;
#    2881                 :          0 :     }
#    2882         [ #  # ]:          0 :     else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
#    2883                 :          0 :         return true;
#    2884                 :            : 
#    2885                 :        279 :     return false;
#    2886                 :        279 : }
#    2887                 :            : 
#    2888                 :            : uint64_t CConnman::GetOutboundTargetBytesLeft() const
#    2889                 :          7 : {
#    2890                 :          7 :     LOCK(cs_totalBytesSent);
#    2891         [ +  - ]:          7 :     if (nMaxOutboundLimit == 0)
#    2892                 :          7 :         return 0;
#    2893                 :            : 
#    2894         [ #  # ]:          0 :     return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
#    2895                 :          0 : }
#    2896                 :            : 
#    2897                 :            : uint64_t CConnman::GetTotalBytesRecv() const
#    2898                 :          7 : {
#    2899                 :          7 :     LOCK(cs_totalBytesRecv);
#    2900                 :          7 :     return nTotalBytesRecv;
#    2901                 :          7 : }
#    2902                 :            : 
#    2903                 :            : uint64_t CConnman::GetTotalBytesSent() const
#    2904                 :          7 : {
#    2905                 :          7 :     LOCK(cs_totalBytesSent);
#    2906                 :          7 :     return nTotalBytesSent;
#    2907                 :          7 : }
#    2908                 :            : 
#    2909                 :            : ServiceFlags CConnman::GetLocalServices() const
#    2910                 :         59 : {
#    2911                 :         59 :     return nLocalServices;
#    2912                 :         59 : }
#    2913                 :            : 
#    2914                 :     107451 : unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
#    2915                 :            : 
#    2916                 :            : CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
#    2917                 :            :     : nTimeConnected(GetSystemTimeInSeconds()),
#    2918                 :            :       addr(addrIn),
#    2919                 :            :       addrBind(addrBindIn),
#    2920                 :            :       m_inbound_onion(inbound_onion),
#    2921                 :            :       nKeyedNetGroup(nKeyedNetGroupIn),
#    2922                 :            :       id(idIn),
#    2923                 :            :       nLocalHostNonce(nLocalHostNonceIn),
#    2924                 :            :       m_conn_type(conn_type_in),
#    2925                 :            :       nLocalServices(nLocalServicesIn)
#    2926                 :       1014 : {
#    2927         [ +  + ]:       1014 :     if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
#    2928                 :       1014 :     hSocket = hSocketIn;
#    2929         [ +  + ]:       1014 :     addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
#    2930         [ +  + ]:       1014 :     if (conn_type_in != ConnectionType::BLOCK_RELAY) {
#    2931                 :        999 :         m_tx_relay = std::make_unique<TxRelay>();
#    2932                 :        999 :     }
#    2933                 :            : 
#    2934         [ +  + ]:       1014 :     for (const std::string &msg : getAllNetMessageTypes())
#    2935                 :      34476 :         mapRecvBytesPerMsgCmd[msg] = 0;
#    2936                 :       1014 :     mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0;
#    2937                 :            : 
#    2938         [ +  + ]:       1014 :     if (fLogIPs) {
#    2939         [ +  - ]:          2 :         LogPrint(BCLog::NET, "Added connection to %s peer=%d\n", addrName, id);
#    2940                 :       1012 :     } else {
#    2941         [ +  - ]:       1012 :         LogPrint(BCLog::NET, "Added connection peer=%d\n", id);
#    2942                 :       1012 :     }
#    2943                 :            : 
#    2944                 :       1014 :     m_deserializer = std::make_unique<V1TransportDeserializer>(V1TransportDeserializer(Params(), GetId(), SER_NETWORK, INIT_PROTO_VERSION));
#    2945                 :       1014 :     m_serializer = std::make_unique<V1TransportSerializer>(V1TransportSerializer());
#    2946                 :       1014 : }
#    2947                 :            : 
#    2948                 :            : CNode::~CNode()
#    2949                 :       1014 : {
#    2950                 :       1014 :     CloseSocket(hSocket);
#    2951                 :       1014 : }
#    2952                 :            : 
#    2953                 :            : bool CConnman::NodeFullyConnected(const CNode* pnode)
#    2954                 :     100693 : {
#    2955 [ +  - ][ +  + ]:     100693 :     return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
#                 [ +  + ]
#    2956                 :     100693 : }
#    2957                 :            : 
#    2958                 :            : void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
#    2959                 :     117288 : {
#    2960                 :     117288 :     size_t nMessageSize = msg.data.size();
#    2961         [ +  - ]:     117288 :     LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n",  SanitizeString(msg.m_type), nMessageSize, pnode->GetId());
#    2962         [ +  + ]:     117288 :     if (gArgs.GetBoolArg("-capturemessages", false)) {
#    2963                 :         11 :         CaptureMessage(pnode->addr, msg.m_type, msg.data, /* incoming */ false);
#    2964                 :         11 :     }
#    2965                 :            : 
#    2966                 :            :     // make sure we use the appropriate network transport format
#    2967                 :     117288 :     std::vector<unsigned char> serializedHeader;
#    2968                 :     117288 :     pnode->m_serializer->prepareForTransport(msg, serializedHeader);
#    2969                 :     117288 :     size_t nTotalSize = nMessageSize + serializedHeader.size();
#    2970                 :            : 
#    2971                 :     117288 :     size_t nBytesSent = 0;
#    2972                 :     117288 :     {
#    2973                 :     117288 :         LOCK(pnode->cs_vSend);
#    2974                 :     117288 :         bool optimisticSend(pnode->vSendMsg.empty());
#    2975                 :            : 
#    2976                 :            :         //log total amount of bytes per message type
#    2977                 :     117288 :         pnode->mapSendBytesPerMsgCmd[msg.m_type] += nTotalSize;
#    2978                 :     117288 :         pnode->nSendSize += nTotalSize;
#    2979                 :            : 
#    2980         [ +  + ]:     117288 :         if (pnode->nSendSize > nSendBufferMaxSize) pnode->fPauseSend = true;
#    2981                 :     117288 :         pnode->vSendMsg.push_back(std::move(serializedHeader));
#    2982         [ +  + ]:     117288 :         if (nMessageSize) pnode->vSendMsg.push_back(std::move(msg.data));
#    2983                 :            : 
#    2984                 :            :         // If write queue empty, attempt "optimistic write"
#    2985         [ +  + ]:     117288 :         if (optimisticSend) nBytesSent = SocketSendData(*pnode);
#    2986                 :     117288 :     }
#    2987         [ +  + ]:     117288 :     if (nBytesSent) RecordBytesSent(nBytesSent);
#    2988                 :     117288 : }
#    2989                 :            : 
#    2990                 :            : bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
#    2991                 :        241 : {
#    2992                 :        241 :     CNode* found = nullptr;
#    2993                 :        241 :     LOCK(cs_vNodes);
#    2994         [ +  + ]:        372 :     for (auto&& pnode : vNodes) {
#    2995         [ +  + ]:        372 :         if(pnode->GetId() == id) {
#    2996                 :        239 :             found = pnode;
#    2997                 :        239 :             break;
#    2998                 :        239 :         }
#    2999                 :        372 :     }
#    3000 [ +  + ][ +  - ]:        241 :     return found != nullptr && NodeFullyConnected(found) && func(found);
#                 [ +  - ]
#    3001                 :        241 : }
#    3002                 :            : 
#    3003                 :            : std::chrono::microseconds CConnman::PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::seconds average_interval)
#    3004                 :       3174 : {
#    3005         [ +  + ]:       3174 :     if (m_next_send_inv_to_incoming.load() < now) {
#    3006                 :            :         // If this function were called from multiple threads simultaneously
#    3007                 :            :         // it would possible that both update the next send variable, and return a different result to their caller.
#    3008                 :            :         // This is not possible in practice as only the net processing thread invokes this function.
#    3009                 :       1938 :         m_next_send_inv_to_incoming = PoissonNextSend(now, average_interval);
#    3010                 :       1938 :     }
#    3011                 :       3174 :     return m_next_send_inv_to_incoming;
#    3012                 :       3174 : }
#    3013                 :            : 
#    3014                 :            : std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval)
#    3015                 :      11802 : {
#    3016                 :      11802 :     double unscaled = -log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */);
#    3017                 :      11802 :     return now + std::chrono::duration_cast<std::chrono::microseconds>(unscaled * average_interval + 0.5us);
#    3018                 :      11802 : }
#    3019                 :            : 
#    3020                 :            : CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const
#    3021                 :       2285 : {
#    3022                 :       2285 :     return CSipHasher(nSeed0, nSeed1).Write(id);
#    3023                 :       2285 : }
#    3024                 :            : 
#    3025                 :            : uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) const
#    3026                 :        976 : {
#    3027                 :        976 :     std::vector<unsigned char> vchNetGroup(ad.GetGroup(addrman.m_asmap));
#    3028                 :            : 
#    3029                 :        976 :     return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize();
#    3030                 :        976 : }
#    3031                 :            : 
#    3032                 :            : void CaptureMessage(const CAddress& addr, const std::string& msg_type, const Span<const unsigned char>& data, bool is_incoming)
#    3033                 :         16 : {
#    3034                 :            :     // Note: This function captures the message at the time of processing,
#    3035                 :            :     // not at socket receive/send time.
#    3036                 :            :     // This ensures that the messages are always in order from an application
#    3037                 :            :     // layer (processing) perspective.
#    3038                 :         16 :     auto now = GetTime<std::chrono::microseconds>();
#    3039                 :            : 
#    3040                 :            :     // Windows folder names can not include a colon
#    3041                 :         16 :     std::string clean_addr = addr.ToString();
#    3042                 :         16 :     std::replace(clean_addr.begin(), clean_addr.end(), ':', '_');
#    3043                 :            : 
#    3044                 :         16 :     fs::path base_path = gArgs.GetDataDirNet() / "message_capture" / clean_addr;
#    3045                 :         16 :     fs::create_directories(base_path);
#    3046                 :            : 
#    3047         [ +  + ]:         16 :     fs::path path = base_path / (is_incoming ? "msgs_recv.dat" : "msgs_sent.dat");
#    3048                 :         16 :     CAutoFile f(fsbridge::fopen(path, "ab"), SER_DISK, CLIENT_VERSION);
#    3049                 :            : 
#    3050                 :         16 :     ser_writedata64(f, now.count());
#    3051                 :         16 :     f.write(msg_type.data(), msg_type.length());
#    3052         [ +  + ]:         88 :     for (auto i = msg_type.length(); i < CMessageHeader::COMMAND_SIZE; ++i) {
#    3053                 :         72 :         f << '\0';
#    3054                 :         72 :     }
#    3055                 :         16 :     uint32_t size = data.size();
#    3056                 :         16 :     ser_writedata32(f, size);
#    3057                 :         16 :     f.write((const char*)data.data(), data.size());
#    3058                 :         16 : }

Generated by: LCOV version 1.14