LCOV - code coverage report
Current view: top level - src - net.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 1853 2361 78.5 %
Date: 2020-08-11 15:24:34 Functions: 110 125 88.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: 0 0 -

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

Generated by: LCOV version 1.14