LCOV - code coverage report
Current view: top level - src - net.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 1213 1523 79.6 %
Date: 2025-02-23 09:33:43 Functions: 116 132 87.9 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2015 The Bitcoin developers
       3             : // Copyright (c) 2014-2015 The Dash developers
       4             : // Copyright (c) 2015-2022 The PIVX Core developers
       5             : // Distributed under the MIT/X11 software license, see the accompanying
       6             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       7             : 
       8             : #if defined(HAVE_CONFIG_H)
       9             : #include "config/pivx-config.h"
      10             : #endif
      11             : 
      12             : #include "net.h"
      13             : 
      14             : #include "chainparams.h"
      15             : #include "clientversion.h"
      16             : #include "crypto/common.h"
      17             : #include "crypto/sha256.h"
      18             : #include "guiinterface.h"
      19             : #include "netaddress.h"
      20             : #include "netbase.h"
      21             : #include "netmessagemaker.h"
      22             : #include "optional.h"
      23             : #include "primitives/transaction.h"
      24             : #include "scheduler.h"
      25             : #include "tiertwo/net_masternodes.h"
      26             : 
      27             : #ifdef WIN32
      28             : #include <string.h>
      29             : #else
      30             : #include <fcntl.h>
      31             : #endif
      32             : 
      33             : #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
      34             : #include <ifaddrs.h>
      35             : #endif
      36             : 
      37             : #ifdef USE_POLL
      38             : #include <poll.h>
      39             : #endif
      40             : 
      41             : #include <cstdint>
      42             : #include <unordered_map>
      43             : 
      44             : #include <math.h>
      45             : 
      46             : // Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
      47             : #define DUMP_ADDRESSES_INTERVAL 900
      48             : 
      49             : // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
      50             : #define FEELER_SLEEP_WINDOW 1
      51             : 
      52             : #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
      53             : #define MSG_NOSIGNAL 0
      54             : #endif
      55             : 
      56             : // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
      57             : // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
      58             : #ifdef WIN32
      59             : #ifndef PROTECTION_LEVEL_UNRESTRICTED
      60             : #define PROTECTION_LEVEL_UNRESTRICTED 10
      61             : #endif
      62             : #ifndef IPV6_PROTECTION_LEVEL
      63             : #define IPV6_PROTECTION_LEVEL 23
      64             : #endif
      65             : #endif
      66             : 
      67             : /** Used to pass flags to the Bind() function */
      68             : enum BindFlags {
      69             :     BF_NONE         = 0,
      70             :     BF_EXPLICIT     = (1U << 0),
      71             :     BF_REPORT_ERROR = (1U << 1),
      72             :     BF_WHITELIST    = (1U << 2),
      73             : };
      74             : 
      75             : // The set of sockets cannot be modified while waiting
      76             : // The sleep time needs to be small to avoid new sockets stalling
      77             : static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
      78             : 
      79             : const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
      80             : 
      81             : constexpr const CConnman::CFullyConnectedOnly CConnman::FullyConnectedOnly;
      82             : constexpr const CConnman::CAllNodes CConnman::AllNodes;
      83             : 
      84             : static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
      85             : static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
      86             : //
      87             : // Global state variables
      88             : //
      89             : bool fDiscover = true;
      90             : bool fListen = true;
      91             : RecursiveMutex cs_mapLocalHost;
      92             : std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
      93             : static bool vfLimited[NET_MAX] = {};
      94             : std::string strSubVersion;
      95             : 
      96             : limitedmap<CInv, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
      97             : 
      98           0 : void CConnman::AddOneShot(const std::string& strDest)
      99             : {
     100           0 :     LOCK(cs_vOneShots);
     101           0 :     vOneShots.push_back(strDest);
     102           0 : }
     103             : 
     104        2154 : uint16_t GetListenPort()
     105             : {
     106        2154 :     return (uint16_t)(gArgs.GetArg("-port", Params().GetDefaultPort()));
     107             : }
     108             : 
     109             : // find 'best' local address for a particular peer
     110        1719 : bool GetLocal(CService& addr, const CNetAddr* paddrPeer)
     111             : {
     112        1719 :     if (!fListen)
     113             :         return false;
     114             : 
     115        1719 :     int nBestScore = -1;
     116        1719 :     int nBestReachability = -1;
     117        1719 :     {
     118        1719 :         LOCK(cs_mapLocalHost);
     119        1720 :         for (const auto& entry : mapLocalHost) {
     120           1 :             int nScore = entry.second.nScore;
     121           1 :             int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
     122           1 :             if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) {
     123           1 :                 addr = CService(entry.first, entry.second.nPort);
     124           1 :                 nBestReachability = nReachability;
     125           1 :                 nBestScore = nScore;
     126             :             }
     127             :         }
     128             :     }
     129        1719 :     return nBestScore >= 0;
     130             : }
     131             : 
     132             : //! Convert the serialized seeds into usable address objects.
     133         121 : static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
     134             : {
     135             :     // It'll only connect to one or two seed nodes because once it connects,
     136             :     // it'll get a pile of addresses with newer timestamps.
     137             :     // Seed nodes are given a random 'last seen time' of between one and two
     138             :     // weeks ago.
     139         121 :     const int64_t nOneWeek = 7 * 24 * 60 * 60;
     140         121 :     std::vector<CAddress> vSeedsOut;
     141         121 :     FastRandomContext rng;
     142         121 :     CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
     143         121 :     while (!s.eof()) {
     144           0 :         CService endpoint;
     145           0 :         s >> endpoint;
     146           0 :         CAddress addr{endpoint, NODE_NETWORK};
     147           0 :         addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
     148           0 :         LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToString());
     149           0 :         vSeedsOut.push_back(addr);
     150             :     }
     151         121 :     return vSeedsOut;
     152             : }
     153             : 
     154             : // get best local address for a particular peer as a CAddress
     155             : // Otherwise, return the unroutable 0.0.0.0 but filled in with
     156             : // the normal parameters, since the IP may be changed to a useful
     157             : // one by discovery.
     158        1458 : CAddress GetLocalAddress(const CNetAddr* paddrPeer, ServiceFlags nLocalServices)
     159             : {
     160        2916 :     CAddress ret(CService(CNetAddr(), GetListenPort()), nLocalServices);
     161        1458 :     CService addr;
     162        1458 :     if (GetLocal(addr, paddrPeer)) {
     163           1 :         ret = CAddress(addr, nLocalServices);
     164             :     }
     165        1458 :     ret.nTime = GetAdjustedTime();
     166        1458 :     return ret;
     167             : }
     168             : 
     169           0 : int GetnScore(const CService& addr)
     170             : {
     171           0 :     LOCK(cs_mapLocalHost);
     172           0 :     if (mapLocalHost.count(addr) == LOCAL_NONE)
     173           0 :         return 0;
     174           0 :     return mapLocalHost[addr].nScore;
     175             : }
     176             : 
     177             : // Is our peer's addrLocal potentially useful as an external IP source?
     178        1458 : bool IsPeerAddrLocalGood(CNode* pnode)
     179             : {
     180        1458 :     CService addrLocal = pnode->GetAddrLocal();
     181        1459 :     return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
     182        1459 :            IsReachable(addrLocal.GetNetwork());
     183             : }
     184             : 
     185             : // pushes our own address to a peer
     186        1240 : void AdvertiseLocal(CNode* pnode)
     187             : {
     188        1240 :     if (fListen && pnode->fSuccessfullyConnected) {
     189        2480 :         CAddress addrLocal = GetLocalAddress(&pnode->addr, pnode->GetLocalServices());
     190             :         // If discovery is enabled, sometimes give our peer the address it
     191             :         // tells us that it sees us as in case it has a better idea of our
     192             :         // address than we do.
     193        1240 :         FastRandomContext rng;
     194        1240 :         if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
     195           0 :              rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0)) {
     196           2 :             addrLocal.SetIP(pnode->GetAddrLocal());
     197             :         }
     198        1240 :         if (addrLocal.IsRoutable()) {
     199           1 :             LogPrintf("%s: advertising address %s\n", __func__, addrLocal.ToString());
     200           1 :             pnode->PushAddress(addrLocal, rng);
     201             :         }
     202             :     }
     203        1240 : }
     204             : 
     205             : // learn a new local address
     206          77 : bool AddLocal(const CService& addr, int nScore)
     207             : {
     208          77 :     if (!addr.IsRoutable())
     209             :         return false;
     210             : 
     211           1 :     if (!fDiscover && nScore < LOCAL_MANUAL)
     212             :         return false;
     213             : 
     214           1 :     if (!IsReachable(addr))
     215             :         return false;
     216             : 
     217           1 :     LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
     218             : 
     219           1 :     {
     220           1 :         LOCK(cs_mapLocalHost);
     221           1 :         bool fAlready = mapLocalHost.count(addr) > 0;
     222           1 :         LocalServiceInfo& info = mapLocalHost[addr];
     223           1 :         if (!fAlready || nScore >= info.nScore) {
     224           1 :             info.nScore = nScore + (fAlready ? 1 : 0);
     225           1 :             info.nPort = addr.GetPort();
     226             :         }
     227             :     }
     228             : 
     229           1 :     return true;
     230             : }
     231             : 
     232           0 : bool AddLocal(const CNetAddr& addr, int nScore)
     233             : {
     234           0 :     return AddLocal(CService(addr, GetListenPort()), nScore);
     235             : }
     236             : 
     237           1 : bool RemoveLocal(const CService& addr)
     238             : {
     239           1 :     LOCK(cs_mapLocalHost);
     240           1 :     LogPrintf("RemoveLocal(%s)\n", addr.ToString());
     241           1 :     mapLocalHost.erase(addr);
     242           2 :     return true;
     243             : }
     244             : 
     245         377 : void SetReachable(enum Network net, bool reachable)
     246             : {
     247         377 :     if (net == NET_UNROUTABLE || net == NET_INTERNAL)
     248           2 :         return;
     249         750 :     LOCK(cs_mapLocalHost);
     250         375 :     vfLimited[net] = !reachable;
     251             : }
     252             : 
     253        8103 : bool IsReachable(enum Network net)
     254             : {
     255        8103 :     LOCK(cs_mapLocalHost);
     256        8103 :     return !vfLimited[net];
     257             : }
     258             : 
     259         757 : bool IsReachable(const CNetAddr& addr)
     260             : {
     261         757 :     return IsReachable(addr.GetNetwork());
     262             : }
     263             : 
     264             : /** vote for a local address */
     265           0 : bool SeenLocal(const CService& addr)
     266             : {
     267           0 :     {
     268           0 :         LOCK(cs_mapLocalHost);
     269           0 :         if (mapLocalHost.count(addr) == 0)
     270           0 :             return false;
     271           0 :         mapLocalHost[addr].nScore++;
     272             :     }
     273           0 :     return true;
     274             : }
     275             : 
     276             : 
     277             : /** check whether a given address is potentially local */
     278         647 : bool IsLocal(const CService& addr)
     279             : {
     280         647 :     LOCK(cs_mapLocalHost);
     281        1941 :     return mapLocalHost.count(addr) > 0;
     282             : }
     283             : 
     284          12 : CNode* CConnman::FindNode(const CNetAddr& ip)
     285             : {
     286          24 :     LOCK(cs_vNodes);
     287          31 :     for (CNode* pnode : vNodes) {
     288          19 :         if (static_cast<CNetAddr>(pnode->addr) == ip) {
     289           0 :             return pnode;
     290             :         }
     291             :     }
     292          12 :     return nullptr;
     293             : }
     294             : 
     295           0 : CNode* CConnman::FindNode(const CSubNet& subNet)
     296             : {
     297           0 :     LOCK(cs_vNodes);
     298           0 :     for (CNode* pnode : vNodes) {
     299           0 :         if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
     300           0 :             return pnode;
     301             :         }
     302             :     }
     303           0 :     return nullptr;
     304             : }
     305             : 
     306         793 : CNode* CConnman::FindNode(const std::string& addrName)
     307             : {
     308        1586 :     LOCK(cs_vNodes);
     309        3880 :     for (CNode* pnode : vNodes) {
     310        3239 :         if (pnode->GetAddrName() == addrName) {
     311         152 :             return pnode;
     312             :         }
     313             :     }
     314         641 :     return nullptr;
     315             : }
     316             : 
     317          32 : CNode* CConnman::FindNode(const CService& addr)
     318             : {
     319          64 :     LOCK(cs_vNodes);
     320          32 :     const bool isRegTestNet = Params().IsRegTestNet();
     321          51 :     for (CNode* pnode : vNodes) {
     322          39 :         if (isRegTestNet) {
     323             :             //if using regtest, just check the IP
     324          39 :             if (static_cast<CNetAddr>(pnode->addr) == static_cast<CNetAddr>(addr))
     325          20 :                 return pnode;
     326             :         } else {
     327           0 :             if (pnode->addr == addr)
     328             :                 return pnode;
     329             :         }
     330             :     }
     331          12 :     return nullptr;
     332             : }
     333             : 
     334         714 : bool CConnman::CheckIncomingNonce(uint64_t nonce)
     335             : {
     336         714 :     LOCK(cs_vNodes);
     337        4811 :     for(CNode* pnode : vNodes) {
     338        4097 :         if (!pnode->fSuccessfullyConnected && !pnode->fInbound && pnode->GetLocalNonce() == nonce)
     339           0 :             return false;
     340             :     }
     341         714 :     return true;
     342             : }
     343             : 
     344         726 : CNode* CConnman::ConnectNode(CAddress addrConnect, const char* pszDest, bool fCountFailure, bool manual_connection)
     345             : {
     346         726 :     if (pszDest == nullptr) {
     347          32 :         if (IsLocal(addrConnect)) {
     348           0 :             LogPrintf("%s: cannot connect to local node\n", __func__);
     349           0 :             return nullptr;
     350             :         }
     351             : 
     352             :         // Look for an existing connection
     353          32 :         CNode* pnode = FindNode(static_cast<CService>(addrConnect));
     354          32 :         if (pnode) {
     355          20 :             LogPrintf("Failed to open new connection, already connected\n");
     356          20 :             return nullptr;
     357             :         }
     358             :     }
     359             : 
     360             :     /// debug print
     361        1400 :     LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n",
     362             :         pszDest ? pszDest : addrConnect.ToString(),
     363             :         pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0);
     364             : 
     365             :     // Resolve
     366         706 :     const int default_port = Params().GetDefaultPort();
     367         706 :     if (pszDest) {
     368        1388 :         std::vector<CService> resolved;
     369        1406 :         if (Lookup(pszDest, resolved,  default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
     370         690 :             addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
     371         690 :             if (!addrConnect.IsValid()) {
     372           0 :                 LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
     373           0 :                 return nullptr;
     374             :             }
     375             :         }
     376             :     }
     377             : 
     378             :     // Connect
     379         706 :     bool connected = false;
     380         706 :     SOCKET hSocket = INVALID_SOCKET;
     381        1432 :     proxyType proxy;
     382         706 :     if (addrConnect.IsValid()) {
     383         702 :         bool proxyConnectionFailed = false;
     384             : 
     385         702 :         if (GetProxy(addrConnect.GetNetwork(), proxy)) {
     386          11 :             hSocket = CreateSocket(proxy.proxy);
     387          11 :             if (hSocket == INVALID_SOCKET) {
     388           0 :                 return nullptr;
     389             :             }
     390          18 :             connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, &proxyConnectionFailed);
     391             :         } else {
     392             :             // no proxy needed (none set for target network)
     393         691 :             hSocket = CreateSocket(addrConnect);
     394         691 :             if (hSocket == INVALID_SOCKET) {
     395             :                 return nullptr;
     396             :             }
     397         691 :             connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout, manual_connection);
     398             :         }
     399         702 :         if (!proxyConnectionFailed) {
     400             :             // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
     401             :             // the proxy, mark this as an attempt.
     402         702 :             addrman.Attempt(addrConnect, fCountFailure);
     403             :         }
     404           4 :     } else if (pszDest && GetNameProxy(proxy)) {
     405           4 :         hSocket = CreateSocket(proxy.proxy);
     406           4 :         if (hSocket == INVALID_SOCKET) {
     407           0 :             return nullptr;
     408             :         }
     409           8 :         std::string host;
     410           4 :         int port = default_port;
     411           4 :         SplitHostPort(std::string(pszDest), port, host);
     412           4 :         connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, nullptr);
     413             :     }
     414         706 :     if (!connected) {
     415          13 :         CloseSocket(hSocket);
     416             :         return nullptr;
     417             :     }
     418             : 
     419             :     // Add node
     420         693 :     NodeId id = GetNewNodeId();
     421         693 :     uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
     422        1386 :     CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, pszDest ? pszDest : "", false);
     423         693 :     pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
     424         693 :     pnode->fWhitelisted = IsWhitelistedRange(addrConnect);
     425         693 :     pnode->AddRef();
     426             : 
     427             :     // We're making a new connection, harvest entropy from the time (and our peer count)
     428         693 :     RandAddEvent((uint32_t)id);
     429             : 
     430         693 :     return pnode;
     431             : }
     432             : 
     433         652 : void CConnman::DumpBanlist()
     434             : {
     435         652 :     SweepBanned(); // clean unused entries (if bantime has expired)
     436             : 
     437         652 :     if (!BannedSetIsDirty())
     438         355 :         return;
     439             : 
     440         297 :     int64_t nStart = GetTimeMillis();
     441             : 
     442         594 :     CBanDB bandb;
     443         594 :     banmap_t banmap;
     444         297 :     GetBanned(banmap);
     445         297 :     if (bandb.Write(banmap)) {
     446         297 :         SetBannedSetDirty(false);
     447             :     }
     448             : 
     449         297 :     LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat  %dms\n",
     450             :         banmap.size(), GetTimeMillis() - nStart);
     451             : }
     452             : 
     453        1839 : void CNode::CloseSocketDisconnect()
     454             : {
     455        1839 :     fDisconnect = true;
     456        1839 :     LOCK(cs_hSocket);
     457        1839 :     if (hSocket != INVALID_SOCKET) {
     458        1456 :         LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
     459        1456 :         CloseSocket(hSocket);
     460             :     }
     461        1839 : }
     462             : 
     463       27114 : bool CNode::DisconnectOldProtocol(int nVersionIn, int nVersionRequired)
     464             : {
     465       27114 :     fDisconnect = false;
     466       27114 :     if (nVersionIn < nVersionRequired) {
     467           1 :         LogPrintf("%s : peer=%d using obsolete version %i; disconnecting\n", __func__, id, nVersionIn);
     468           1 :         fDisconnect = true;
     469             :     }
     470       27114 :     return fDisconnect;
     471             : }
     472             : 
     473          11 : void CConnman::ClearBanned()
     474             : {
     475          11 :     {
     476          11 :         LOCK(cs_setBanned);
     477          11 :         setBanned.clear();
     478          11 :         setBannedIsDirty = true;
     479             :     }
     480          11 :     DumpBanlist(); // store banlist to Disk
     481          11 :     if(clientInterface)
     482           3 :         clientInterface->BannedListChanged();
     483          11 : }
     484             : 
     485         935 : bool CConnman::IsBanned(CNetAddr ip)
     486             : {
     487        1870 :     LOCK(cs_setBanned);
     488         941 :     for (const auto& it : setBanned) {
     489          21 :         CSubNet subNet = it.first;
     490          15 :         CBanEntry banEntry = it.second;
     491             : 
     492          15 :         if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) {
     493           9 :             return true;
     494             :         }
     495             :     }
     496         926 :     return false;
     497             : }
     498             : 
     499           9 : bool CConnman::IsBanned(CSubNet subnet)
     500             : {
     501          18 :     LOCK(cs_setBanned);
     502           9 :     banmap_t::iterator i = setBanned.find(subnet);
     503           9 :     if (i != setBanned.end()) {
     504           0 :         CBanEntry banEntry = (*i).second;
     505           0 :         if (GetTime() < banEntry.nBanUntil) {
     506           0 :             return true;
     507             :         }
     508             :     }
     509             :     return false;
     510             : }
     511             : 
     512           8 : void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch)
     513             : {
     514           8 :     CSubNet subNet(addr);
     515           8 :     Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
     516           8 : }
     517             : 
     518          17 : void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch)
     519             : {
     520          17 :     CBanEntry banEntry(GetTime());
     521          17 :     banEntry.banReason = banReason;
     522          17 :     if (bantimeoffset <= 0)
     523             :     {
     524          13 :         bantimeoffset = gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME); // Default 24-hour ban
     525          13 :         sinceUnixEpoch = false;
     526             :     }
     527          17 :     banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
     528             : 
     529          17 :     {
     530          17 :         LOCK(cs_setBanned);
     531          17 :         if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) {
     532          17 :             setBanned[subNet] = banEntry;
     533          17 :             setBannedIsDirty = true;
     534             :         }
     535             :         else
     536           0 :             return;
     537             :     }
     538          17 :     if(clientInterface)
     539           6 :         clientInterface->BannedListChanged();
     540          17 :     {
     541          17 :         LOCK(cs_vNodes);
     542          19 :         for (CNode* pnode : vNodes) {
     543           2 :             if (subNet.Match(static_cast<CNetAddr>(pnode->addr)))
     544           2 :                 pnode->fDisconnect = true;
     545             :         }
     546             :     }
     547          17 :     if(banReason == BanReasonManuallyAdded)
     548          13 :         DumpBanlist(); //store banlist to disk immediately if user requested ban
     549             : }
     550             : 
     551           2 : bool CConnman::Unban(const CNetAddr &addr)
     552             : {
     553           2 :     CSubNet subNet(addr);
     554           2 :     return Unban(subNet);
     555             : }
     556             : 
     557           4 : bool CConnman::Unban(const CSubNet &subNet)
     558             : {
     559           4 :     {
     560           4 :         LOCK(cs_setBanned);
     561           4 :         if (!setBanned.erase(subNet))
     562           2 :             return false;
     563           3 :         setBannedIsDirty = true;
     564             :     }
     565           3 :     if(clientInterface)
     566           1 :         clientInterface->BannedListChanged();
     567           3 :     DumpBanlist(); //store banlist to disk immediately
     568           3 :     return true;
     569             : }
     570             : 
     571         316 : void CConnman::GetBanned(banmap_t &banMap)
     572             : {
     573         316 :     LOCK(cs_setBanned);
     574             :     // Sweep the banlist so expired bans are not returned
     575         316 :     SweepBanned();
     576         316 :     banMap = setBanned; //create a thread safe copy
     577         316 : }
     578             : 
     579          86 : void CConnman::SetBanned(const banmap_t &banMap)
     580             : {
     581          86 :     LOCK(cs_setBanned);
     582          86 :     setBanned = banMap;
     583          86 :     setBannedIsDirty = true;
     584          86 : }
     585             : 
     586        1054 : void CConnman::SweepBanned()
     587             : {
     588        1054 :     int64_t now = GetTime();
     589             : 
     590        1054 :     bool notifyUI = false;
     591        1054 :     {
     592        1054 :         LOCK(cs_setBanned);
     593        1054 :         banmap_t::iterator it = setBanned.begin();
     594        1122 :         while(it != setBanned.end())
     595             :         {
     596         136 :             CSubNet subNet = (*it).first;
     597          68 :             CBanEntry banEntry = (*it).second;
     598          68 :             if(now > banEntry.nBanUntil)
     599             :             {
     600           1 :                 setBanned.erase(it++);
     601           1 :                 setBannedIsDirty = true;
     602           1 :                 notifyUI = true;
     603           2 :                 LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString());
     604             :             }
     605             :             else
     606          68 :                 ++it;
     607             :         }
     608             :     }
     609             :     // update UI
     610        1054 :     if(notifyUI) {
     611           1 :         uiInterface.BannedListChanged();
     612             :     }
     613        1054 : }
     614             : 
     615         652 : bool CConnman::BannedSetIsDirty()
     616             : {
     617         652 :     LOCK(cs_setBanned);
     618         652 :     return setBannedIsDirty;
     619             : }
     620             : 
     621         652 : void CConnman::SetBannedSetDirty(bool dirty)
     622             : {
     623         652 :     LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag
     624         652 :     setBannedIsDirty = dirty;
     625         652 : }
     626             : 
     627             : 
     628        1484 : bool CConnman::IsWhitelistedRange(const CNetAddr& addr)
     629             : {
     630        1484 :     for (const CSubNet& subnet : vWhitelistedRange) {
     631         184 :         if (subnet.Match(addr))
     632         184 :             return true;
     633             :     }
     634        1300 :     return false;
     635             : }
     636             : 
     637      112100 : std::string CNode::GetAddrName() const {
     638      112100 :     LOCK(cs_addrName);
     639      336300 :     return addrName;
     640             : }
     641             : 
     642           0 : void CNode::MaybeSetAddrName(const std::string& addrNameIn) {
     643           0 :     LOCK(cs_addrName);
     644           0 :     if (addrName.empty()) {
     645           0 :         addrName = addrNameIn;
     646             :     }
     647           0 : }
     648             : 
     649       62832 : CService CNode::GetAddrLocal() const {
     650       62832 :     LOCK(cs_addrLocal);
     651       62832 :     return addrLocal;
     652             : }
     653             : 
     654        1363 : void CNode::SetAddrLocal(const CService& addrLocalIn) {
     655        1363 :     LOCK(cs_addrLocal);
     656        1363 :     if (addrLocal.IsValid()) {
     657           0 :         error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToString(), addrLocalIn.ToString());
     658             :     } else {
     659        2726 :         addrLocal = addrLocalIn;
     660             :     }
     661        1363 : }
     662             : 
     663             : #undef X
     664             : #define X(name) stats.name = name
     665       61373 : void CNode::copyStats(CNodeStats& stats, const std::vector<bool>& m_asmap)
     666             : {
     667       61373 :     stats.nodeid = this->GetId();
     668       61373 :     X(nServices);
     669       61373 :     stats.m_mapped_as = addr.GetMappedAS(m_asmap);
     670       61373 :     X(nLastSend);
     671       61373 :     X(nLastRecv);
     672       61373 :     X(nTimeConnected);
     673       61373 :     X(nTimeOffset);
     674       61373 :     stats.addrName = GetAddrName();
     675       61373 :     X(nVersion);
     676       61373 :     {
     677       61373 :         LOCK(cs_SubVer);
     678       61373 :         X(cleanSubVer);
     679             :     }
     680       61373 :     X(fInbound);
     681       61373 :     X(fAddnode);
     682       61373 :     X(nStartingHeight);
     683       61373 :     {
     684       61373 :         LOCK(cs_vSend);
     685       61373 :         X(mapSendBytesPerMsgCmd);
     686       61373 :         X(nSendBytes);
     687             :     }
     688       61373 :     {
     689       61373 :         LOCK(cs_vRecv);
     690       61373 :         X(mapRecvBytesPerMsgCmd);
     691       61373 :         X(nRecvBytes);
     692             :     }
     693       61373 :     X(fWhitelisted);
     694       61373 :     X(m_masternode_connection);
     695       61373 :     X(m_masternode_iqr_connection);
     696       61373 :     X(m_masternode_probe_connection);
     697       61373 :     {
     698       61373 :         LOCK(cs_mnauth);
     699       61373 :         X(verifiedProRegTxHash);
     700       61373 :         X(verifiedPubKeyHash);
     701             :     }
     702             : 
     703             :     // It is common for nodes with good ping times to suddenly become lagged,
     704             :     // due to a new block arriving or other large transfer.
     705             :     // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
     706             :     // since pingtime does not update until the ping is complete, which might take a while.
     707             :     // So, if a ping is taking an unusually long time in flight,
     708             :     // the caller can immediately detect that this is happening.
     709       61373 :     int64_t nPingUsecWait = 0;
     710       61373 :     if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
     711         810 :         nPingUsecWait = GetTimeMicros() - nPingUsecStart;
     712             :     }
     713             : 
     714             :     // Raw ping time is in microseconds, but show it to user as whole seconds (PIVX users should be well used to small numbers with many decimal places by now :)
     715       61373 :     stats.dPingTime = (((double)nPingUsecTime) / 1e6);
     716       61373 :     stats.dPingWait = (((double)nPingUsecWait) / 1e6);
     717             : 
     718             :     // Leave string empty if addrLocal invalid (not filled in yet)
     719       61373 :     CService addrLocalUnlocked = GetAddrLocal();
     720       61373 :     stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
     721       61373 : }
     722             : #undef X
     723             : 
     724      344736 : bool CNode::ReceiveMsgBytes(const char* pch, unsigned int nBytes, bool& complete)
     725             : {
     726      344736 :     complete = false;
     727      344736 :     int64_t nTimeMicros = GetTimeMicros();
     728      689472 :     LOCK(cs_vRecv);
     729      344736 :     nLastRecv = nTimeMicros / 1000000;
     730      344736 :     nRecvBytes += nBytes;
     731     1101100 :     while (nBytes > 0) {
     732             :         // get current incomplete message, or create a new one
     733      756365 :         if (vRecvMsg.empty() ||
     734      514249 :             vRecvMsg.back().complete())
     735      758312 :             vRecvMsg.emplace_back(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION);
     736             : 
     737      756365 :         CNetMessage& msg = vRecvMsg.back();
     738             : 
     739             :         // absorb network data
     740      756365 :         int handled;
     741      756365 :         if (!msg.in_data)
     742      379156 :             handled = msg.readHeader(pch, nBytes);
     743             :         else
     744      377209 :             handled = msg.readData(pch, nBytes);
     745             : 
     746      756365 :         if (handled < 0)
     747             :             return false;
     748             : 
     749      756365 :         if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
     750           1 :             LogPrint(BCLog::NET, "Oversized message from peer=%i, disconnecting\n", GetId());
     751           1 :             return false;
     752             :         }
     753             : 
     754      756364 :         pch += handled;
     755      756364 :         nBytes -= handled;
     756             : 
     757     1857460 :         if (msg.complete()) {
     758             : 
     759             :             // Store received bytes per message command
     760             :             // to prevent a memory DOS, only allow valid commands
     761      758280 :             mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.hdr.pchCommand);
     762      379140 :             if (i == mapRecvBytesPerMsgCmd.end())
     763         191 :                 i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER);
     764      379140 :             assert(i != mapRecvBytesPerMsgCmd.end());
     765      379140 :             i->second += msg.hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
     766             : 
     767      379140 :             msg.nTime = nTimeMicros;
     768      379140 :             complete = true;
     769             :         }
     770             :     }
     771             : 
     772             :     return true;
     773             : }
     774             : 
     775        1366 : void CNode::SetSendVersion(int nVersionIn)
     776             : {
     777             :     // Send version may only be changed in the version message, and
     778             :     // only one version message is allowed per session. We can therefore
     779             :     // treat this value as const and even atomic as long as it's only used
     780             :     // once a version message has been successfully processed. Any attempt to
     781             :     // set this twice is an error.
     782        1366 :     if (nSendVersion != 0) {
     783           0 :         error("Send version already set for node: %i. Refusing to change from %i to %i", id, nSendVersion, nVersionIn);
     784             :     } else {
     785        1366 :         nSendVersion = nVersionIn;
     786             :     }
     787        1366 : }
     788             : 
     789     2908617 : int CNode::GetSendVersion() const
     790             : {
     791             :     // The send version should always be explicitly set to
     792             :     // INIT_PROTO_VERSION rather than using this value until SetSendVersion
     793             :     // has been called.
     794     2908617 :     if (nSendVersion == 0) {
     795           0 :         error("Requesting unset send version for node: %i. Using %i", id, INIT_PROTO_VERSION);
     796           0 :         return INIT_PROTO_VERSION;
     797             :     }
     798             :     return nSendVersion;
     799             : }
     800             : 
     801      379156 : int CNetMessage::readHeader(const char* pch, unsigned int nBytes)
     802             : {
     803             :     // copy data to temporary parsing buffer
     804      379156 :     unsigned int nRemaining = 24 - nHdrPos;
     805      379156 :     unsigned int nCopy = std::min(nRemaining, nBytes);
     806             : 
     807      379156 :     memcpy(&hdrbuf[nHdrPos], pch, nCopy);
     808      379156 :     nHdrPos += nCopy;
     809             : 
     810             :     // if header incomplete, exit
     811      379156 :     if (nHdrPos < 24)
     812           0 :         return nCopy;
     813             : 
     814             :     // deserialize to CMessageHeader
     815      379156 :     try {
     816      379156 :         hdrbuf >> hdr;
     817           0 :     } catch (const std::exception&) {
     818           0 :         return -1;
     819             :     }
     820             : 
     821             :     // reject messages larger than MAX_SIZE
     822      379156 :     if (hdr.nMessageSize > MAX_SIZE)
     823             :         return -1;
     824             : 
     825             :     // switch state to reading message data
     826      379156 :     in_data = true;
     827             : 
     828      379156 :     return nCopy;
     829             : }
     830             : 
     831      377209 : int CNetMessage::readData(const char* pch, unsigned int nBytes)
     832             : {
     833      377209 :     unsigned int nRemaining = hdr.nMessageSize - nDataPos;
     834      377209 :     unsigned int nCopy = std::min(nRemaining, nBytes);
     835             : 
     836      377209 :     if (vRecv.size() < nDataPos + nCopy) {
     837             :         // Allocate up to 256 KiB ahead, but never more than the total message size.
     838      375454 :         vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
     839             :     }
     840             : 
     841      377209 :     hasher.Write((const unsigned char*)pch, nCopy);
     842      377209 :     memcpy(&vRecv[nDataPos], pch, nCopy);
     843      377209 :     nDataPos += nCopy;
     844             : 
     845      377209 :     return nCopy;
     846             : }
     847             : 
     848      378828 : const uint256& CNetMessage::GetMessageHash() const
     849             : {
     850      378828 :     assert(complete());
     851    12501300 :     if (data_hash.IsNull())
     852      378828 :         hasher.Finalize(data_hash.begin());
     853      378828 :     return data_hash;
     854             : }
     855             : 
     856             : // requires LOCK(cs_vSend)
     857      288071 : size_t CConnman::SocketSendData(CNode* pnode)
     858             : {
     859      288071 :     auto it = pnode->vSendMsg.begin();
     860      288071 :     size_t nSentSize = 0;
     861             : 
     862      942008 :     while (it != pnode->vSendMsg.end()) {
     863      653981 :         const auto& data = *it;
     864      653981 :         assert(data.size() > pnode->nSendOffset);
     865      653981 :         int nBytes = 0;
     866      653981 :         {
     867      653981 :             LOCK(pnode->cs_hSocket);
     868      653981 :             if (pnode->hSocket == INVALID_SOCKET)
     869             :                 break;
     870      653981 :             nBytes = send(pnode->hSocket, reinterpret_cast<const char*>(data.data()) + pnode->nSendOffset, data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
     871             :         }
     872      653981 :         if (nBytes > 0) {
     873      653937 :             pnode->nLastSend = GetSystemTimeInSeconds();
     874      653937 :             pnode->nSendBytes += nBytes;
     875      653937 :             pnode->nSendOffset += nBytes;
     876      653937 :             nSentSize += nBytes;
     877      653937 :             if (pnode->nSendOffset == data.size()) {
     878      653937 :                 pnode->nSendOffset = 0;
     879      653937 :                 pnode->nSendSize -= data.size();
     880      653937 :                 pnode->fPauseSend = pnode->nSendSize > nSendBufferMaxSize;
     881      654548 :                 it++;
     882             :             } else {
     883             :                 // could not send full message; stop sending more
     884             :                 break;
     885             :             }
     886             :         } else {
     887          44 :             if (nBytes < 0) {
     888             :                 // error
     889          44 :                 int nErr = WSAGetLastError();
     890          44 :                 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) {
     891          44 :                     LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
     892          44 :                     pnode->CloseSocketDisconnect();
     893             :                 }
     894             :             }
     895             :             // couldn't send anything at all
     896             :             break;
     897             :         }
     898             :     }
     899             : 
     900      288071 :     if (it == pnode->vSendMsg.end()) {
     901      288027 :         assert(pnode->nSendOffset == 0);
     902      288027 :         assert(pnode->nSendSize == 0);
     903             :     }
     904      288071 :     pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
     905      288071 :     return nSentSize;
     906             : }
     907             : 
     908           2 : void CheckOffsetDisconnectedPeers(const CNetAddr& ip)
     909             : {
     910           2 :     int nConnections = 0;
     911           2 :     if (g_connman) {
     912           2 :         g_connman->ForEachNode([&nConnections](CNode* pnode) {
     913          10 :             if (pnode->fSuccessfullyConnected)
     914          10 :                 nConnections++;
     915          10 :             if (nConnections == ENOUGH_CONNECTIONS)
     916             :                 return;
     917             :         });
     918             :     }
     919             : 
     920             :     // Not enough connections. Insert peer.
     921           2 :     static std::set<CNetAddr> setOffsetDisconnectedPeers;
     922           2 :     setOffsetDisconnectedPeers.insert(ip);
     923           2 :     if (setOffsetDisconnectedPeers.size() >= MAX_TIMEOFFSET_DISCONNECTIONS) {
     924             :         // clear the set
     925           0 :         setOffsetDisconnectedPeers.clear();
     926             :         // Trigger the warning
     927           0 :         std::string strWarn1 = _("Peers are being disconnected due time differences.");
     928           0 :         std::string strWarn2 = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong %s will not work properly."), PACKAGE_NAME);
     929             : 
     930           0 :         LogPrintf("*** Warning: %s %s\n", strWarn1, strWarn2);
     931             : 
     932           0 :         static int64_t nLastGUINotif = 0;
     933           0 :         int64_t now = GetTime();
     934           0 :         if (nLastGUINotif + 40 < now) { // Notify the GUI if needed.
     935           0 :             nLastGUINotif = now;
     936           0 :             uiInterface.ThreadSafeMessageBox(strprintf("%s\n\n%s", strWarn1, strWarn2), _("Warning"), CClientUIInterface::MSG_ERROR);
     937             :         }
     938             :     }
     939           2 : }
     940             : 
     941           0 : struct NodeEvictionCandidate
     942             : {
     943             :     NodeId id;
     944             :     int64_t nTimeConnected;
     945             :     int64_t nMinPingUsecTime;
     946             :     CAddress addr;
     947             :     uint64_t nKeyedNetGroup;
     948             : };
     949             : 
     950           0 : static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
     951             : {
     952           0 :     return a.nMinPingUsecTime > b.nMinPingUsecTime;
     953             : }
     954             : 
     955           0 : static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
     956             : {
     957           0 :     return a.nTimeConnected > b.nTimeConnected;
     958             : }
     959             : 
     960           0 : static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
     961           0 :     return a.nKeyedNetGroup < b.nKeyedNetGroup;
     962             : };
     963             : 
     964             : /** Try to find a connection to evict when the node is full.
     965             :  *  Extreme care must be taken to avoid opening the node to attacker
     966             :  *   triggered network partitioning.
     967             :  *  The strategy used here is to protect a small number of peers
     968             :  *   for each of several distinct characteristics which are difficult
     969             :  *   to forge.  In order to partition a node the attacker must be
     970             :  *   simultaneously better at all of them than honest peers.
     971             :  */
     972           0 : bool CConnman::AttemptToEvictConnection(bool fPreferNewConnection)
     973             : {
     974           0 :     std::vector<NodeEvictionCandidate> vEvictionCandidates;
     975           0 :     {
     976           0 :         LOCK(cs_vNodes);
     977             : 
     978           0 :         for (const CNode* node : vNodes) {
     979           0 :             if (node->fWhitelisted)
     980           0 :                 continue;
     981           0 :             if (!node->fInbound)
     982           0 :                 continue;
     983           0 :             if (node->fDisconnect)
     984           0 :                 continue;
     985             : 
     986             :             // Protect verified MN-only connections
     987           0 :             if (fMasterNode) {
     988             :                 // This handles eviction protected nodes. Nodes are always protected for a short time after the connection
     989             :                 // was accepted. This short time is meant for the VERSION/VERACK exchange and the possible MNAUTH that might
     990             :                 // follow when the incoming connection is from another masternode. When a message other than MNAUTH
     991             :                 // is received after VERSION/VERACK, the protection is lifted immediately.
     992           0 :                 bool isProtected = GetSystemTimeInSeconds() - node->nTimeConnected < INBOUND_EVICTION_PROTECTION_TIME;
     993           0 :                 if (node->fFirstMessageReceived && !node->fFirstMessageIsMNAUTH) {
     994             :                     isProtected = false;
     995             :                 }
     996             :                 // if MNAUTH was valid, the node is always protected (and at the same time not accounted when
     997             :                 // checking incoming connection limits)
     998           0 :                 if (!node->verifiedProRegTxHash.IsNull()) {
     999             :                     isProtected = true;
    1000             :                 }
    1001           0 :                 if (isProtected) {
    1002           0 :                     continue;
    1003             :                 }
    1004             :             }
    1005             : 
    1006           0 :             NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->nKeyedNetGroup};
    1007           0 :             vEvictionCandidates.push_back(candidate);
    1008             :         }
    1009             :     }
    1010             : 
    1011           0 :     if (vEvictionCandidates.empty()) return false;
    1012             : 
    1013             :     // Protect connections with certain characteristics
    1014             : 
    1015             :     // Deterministically select 4 peers to protect by netgroup.
    1016             :     // An attacker cannot predict which netgroups will be protected
    1017           0 :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNetGroupKeyed);
    1018           0 :     vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
    1019             : 
    1020           0 :     if (vEvictionCandidates.empty()) return false;
    1021             : 
    1022             :     // Protect the 8 nodes with the lowest minimum ping time.
    1023             :     // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
    1024           0 :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime);
    1025           0 :     vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
    1026             : 
    1027           0 :     if (vEvictionCandidates.empty()) return false;
    1028             : 
    1029             :     // Protect the half of the remaining nodes which have been connected the longest.
    1030             :     // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
    1031           0 :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
    1032           0 :     vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast<int>(vEvictionCandidates.size() / 2), vEvictionCandidates.end());
    1033             : 
    1034           0 :     if (vEvictionCandidates.empty()) return false;
    1035             : 
    1036             :     // Identify the network group with the most connections and youngest member.
    1037             :     // (vEvictionCandidates is already sorted by reverse connect time)
    1038           0 :     uint64_t naMostConnections;
    1039           0 :     unsigned int nMostConnections = 0;
    1040           0 :     int64_t nMostConnectionsTime = 0;
    1041           0 :     std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapAddrCounts;
    1042           0 :     for (const NodeEvictionCandidate& node : vEvictionCandidates) {
    1043           0 :         mapAddrCounts[node.nKeyedNetGroup].push_back(node);
    1044           0 :         int64_t grouptime = mapAddrCounts[node.nKeyedNetGroup][0].nTimeConnected;
    1045           0 :         size_t groupsize = mapAddrCounts[node.nKeyedNetGroup].size();
    1046           0 :         if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
    1047           0 :             nMostConnections = groupsize;
    1048           0 :             nMostConnectionsTime = grouptime;
    1049           0 :             naMostConnections = node.nKeyedNetGroup;
    1050             :         }
    1051             :     }
    1052             : 
    1053             :     // Reduce to the network group with the most connections
    1054           0 :     vEvictionCandidates = std::move(mapAddrCounts[naMostConnections]);
    1055             : 
    1056             :     // Do not disconnect peers if there is only 1 connection from their network group
    1057           0 :     if (vEvictionCandidates.size() <= 1)
    1058             :         // unless we prefer the new connection (for whitelisted peers)
    1059           0 :         if (!fPreferNewConnection)
    1060             :             return false;
    1061             : 
    1062             :     // Disconnect from the network group with the most connections
    1063           0 :     NodeId evicted = vEvictionCandidates.front().id;
    1064           0 :     LOCK(cs_vNodes);
    1065           0 :     for (CNode* pnode : vNodes) {
    1066           0 :         if (pnode->GetId() == evicted) {
    1067           0 :             pnode->fDisconnect = true;
    1068           0 :             return true;
    1069             :         }
    1070             :     }
    1071           0 :     return false;
    1072             : }
    1073             : 
    1074         791 : void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
    1075         791 :     struct sockaddr_storage sockaddr;
    1076         791 :     socklen_t len = sizeof(sockaddr);
    1077         791 :     SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
    1078        1554 :     CAddress addr;
    1079         791 :     int nInbound = 0;
    1080         791 :     int nVerifiedInboundMasternodes = 0;
    1081             : 
    1082         791 :     if (hSocket != INVALID_SOCKET)
    1083         791 :         if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
    1084           0 :             LogPrintf("Warning: Unknown socket family\n");
    1085             : 
    1086         791 :     bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr);
    1087         791 :     {
    1088         791 :         LOCK(cs_vNodes);
    1089        4729 :         for (const CNode* pnode : vNodes) {
    1090        3938 :             if (pnode->fInbound) {
    1091        1881 :                 nInbound++;
    1092        3762 :                 if (!pnode->verifiedProRegTxHash.IsNull()) {
    1093          58 :                     nVerifiedInboundMasternodes++;
    1094             :                 }
    1095             :             }
    1096             :         }
    1097             :     }
    1098             : 
    1099         791 :     if (hSocket == INVALID_SOCKET) {
    1100           0 :         int nErr = WSAGetLastError();
    1101           0 :         if (nErr != WSAEWOULDBLOCK)
    1102           0 :             LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
    1103          28 :         return;
    1104             :     }
    1105             : 
    1106         791 :     if (!fNetworkActive) {
    1107          28 :         LogPrintf("connection from %s dropped: not accepting new connections\n", addr.ToString());
    1108          28 :         CloseSocket(hSocket);
    1109             :         return;
    1110             :     }
    1111             : 
    1112         763 :     if (!IsSelectableSocket(hSocket)) {
    1113             :         LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString());
    1114             :         CloseSocket(hSocket);
    1115             :         return;
    1116             :     }
    1117             : 
    1118        1526 :     if (IsBanned(addr) && !whitelisted) {
    1119           0 :         LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
    1120           0 :         CloseSocket(hSocket);
    1121             :         return;
    1122             :     }
    1123             : 
    1124             :     // TODO: pending review.
    1125             :     // Evict connections until we are below nMaxInbound. In case eviction protection resulted in nodes to not be evicted
    1126             :     // before, they might get evicted in batches now (after the protection timeout).
    1127             :     // We don't evict verified MN connections and also don't take them into account when checking limits. We can do this
    1128             :     // because we know that such connections are naturally limited by the total number of MNs, so this is not usable
    1129             :     // for attacks.
    1130         763 :     while (nInbound - nVerifiedInboundMasternodes >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS) {
    1131           0 :         if (!AttemptToEvictConnection(whitelisted)) {
    1132             :             // No connection to evict, disconnect the new connection
    1133           0 :             LogPrint(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
    1134           0 :             CloseSocket(hSocket);
    1135             :             return;
    1136             :         }
    1137           0 :         nInbound--;
    1138             :     }
    1139             : 
    1140         763 :     NodeId id = GetNewNodeId();
    1141         763 :     uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
    1142             : 
    1143         763 :     CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, "", true);
    1144         763 :     pnode->AddRef();
    1145         763 :     pnode->fWhitelisted = whitelisted;
    1146         763 :     m_msgproc->InitializeNode(pnode);
    1147             : 
    1148        1514 :     LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
    1149             : 
    1150         763 :     {
    1151         763 :         LOCK(cs_vNodes);
    1152         763 :         vNodes.push_back(pnode);
    1153             :     }
    1154             : 
    1155             :     // We received a new connection, harvest entropy from the time (and our peer count)
    1156         763 :     RandAddEvent((uint32_t)id);
    1157             : }
    1158             : 
    1159     1049560 : void CConnman::DisconnectNodes()
    1160             : {
    1161     1049560 :     {
    1162     1049560 :         LOCK(cs_vNodes);
    1163             : 
    1164     1049560 :         if (!fNetworkActive) {
    1165             :             // Disconnect any connected nodes
    1166        1775 :             for (CNode* pnode : vNodes) {
    1167          80 :                 if (!pnode->fDisconnect) {
    1168          80 :                     LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
    1169          80 :                     pnode->fDisconnect = true;
    1170             :                 }
    1171             :             }
    1172             :         }
    1173             : 
    1174             :         // Disconnect unused nodes
    1175     2099120 :         std::vector<CNode*> vNodesCopy = vNodes;
    1176     9330120 :         for (CNode* pnode : vNodesCopy) {
    1177     8280560 :             if (pnode->fDisconnect) {
    1178             :                 // remove from vNodes
    1179         676 :                 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
    1180             : 
    1181             :                 // release outbound grant (if any)
    1182         676 :                 pnode->grantOutbound.Release();
    1183             : 
    1184             :                 // close socket and cleanup
    1185         676 :                 pnode->CloseSocketDisconnect();
    1186             : 
    1187             :                 // hold in disconnected pool until all refs are released
    1188         676 :                 pnode->Release();
    1189     8280560 :                 vNodesDisconnected.push_back(pnode);
    1190             :             }
    1191             :         }
    1192             :     }
    1193     1049560 :     {
    1194             :         // Delete disconnected nodes
    1195     1049560 :         std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
    1196     1050740 :         for (CNode* pnode : vNodesDisconnectedCopy) {
    1197             :             // wait until threads are done using it
    1198        1175 :             if (pnode->GetRefCount() <= 0) {
    1199         676 :                 bool fDelete = false;
    1200         676 :                 {
    1201         676 :                     TRY_LOCK(pnode->cs_inventory, lockInv);
    1202         676 :                     if (lockInv) {
    1203        1352 :                         TRY_LOCK(pnode->cs_vSend, lockSend);
    1204         676 :                         if (lockSend) {
    1205         676 :                             fDelete = true;
    1206             :                         }
    1207             :                     }
    1208             :                 }
    1209         676 :                 if (fDelete) {
    1210         676 :                     vNodesDisconnected.remove(pnode);
    1211         676 :                     DeleteNode(pnode);
    1212             :                 }
    1213             :             }
    1214             :         }
    1215             :     }
    1216     1049560 : }
    1217             : 
    1218     1049560 : void CConnman::NotifyNumConnectionsChanged()
    1219             : {
    1220     1049560 :     size_t vNodesSize;
    1221     1049560 :     {
    1222     1049560 :         LOCK(cs_vNodes);
    1223     1049560 :         vNodesSize = vNodes.size();
    1224             :     }
    1225     1049560 :     if (vNodesSize != nPrevNodeCount) {
    1226        1882 :         nPrevNodeCount = vNodesSize;
    1227        1882 :         if (clientInterface)
    1228        1882 :             clientInterface->NotifyNumConnectionsChanged((int)vNodesSize);
    1229             :     }
    1230     1049560 : }
    1231             : 
    1232     8280560 : void CConnman::InactivityCheck(CNode* pnode)
    1233             : {
    1234     8280560 :     int64_t nTime = GetSystemTimeInSeconds();
    1235     8280560 :     if (nTime - pnode->nTimeConnected > 60) {
    1236     2881300 :         if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) {
    1237           2 :             LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
    1238           2 :             pnode->fDisconnect = true;
    1239     2881300 :         } else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) {
    1240           0 :             LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
    1241           0 :             pnode->fDisconnect = true;
    1242     2881300 :         } else if (nTime - pnode->nLastRecv > TIMEOUT_INTERVAL) {
    1243           0 :             LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
    1244           0 :             pnode->fDisconnect = true;
    1245     2881300 :         } else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros()) {
    1246           0 :             LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
    1247           0 :             pnode->fDisconnect = true;
    1248     2881300 :         } else if (!pnode->fSuccessfullyConnected) {
    1249           1 :             LogPrint(BCLog::NET, "version handshake timeout from %d\n", pnode->GetId());
    1250           1 :             pnode->fDisconnect = true;
    1251             :         }
    1252             :     }
    1253     8280560 : }
    1254             : 
    1255     1049560 : bool CConnman::GenerateSelectSet(std::set<SOCKET>& recv_set, std::set<SOCKET>& send_set, std::set<SOCKET>& error_set)
    1256             : {
    1257     2099070 :     for (const ListenSocket& hListenSocket : vhListenSocket) {
    1258     1049510 :         recv_set.insert(hListenSocket.socket);
    1259             :     }
    1260             : 
    1261     1049560 :     {
    1262     1049560 :         LOCK(cs_vNodes);
    1263     9329450 :         for (CNode* pnode: vNodes) {
    1264             :             // Implement the following logic:
    1265             :             // * If there is data to send, select() for sending data. As this only
    1266             :             //   happens when optimistic write failed, we choose to first drain the
    1267             :             //   write buffer in this case before receiving more. This avoids
    1268             :             //   needlessly queueing received data, if the remote peer is not themselves
    1269             :             //   receiving data. This means properly utilizing TCP flow control signalling.
    1270             :             // * Otherwise, if there is space left in the receive buffer, select() for
    1271             :             //   receiving data.
    1272             :             // * Hand off all complete messages to the processor, to be handled without
    1273             :             //   blocking here.
    1274             : 
    1275     8279890 :             bool select_recv = !pnode->fPauseRecv;
    1276     8279890 :             bool select_send;
    1277     8279890 :             {
    1278     8279890 :                 LOCK(pnode->cs_vSend);
    1279     8279890 :                 select_send = !pnode->vSendMsg.empty();
    1280             :             }
    1281             : 
    1282    16271700 :             LOCK(pnode->cs_hSocket);
    1283     8279890 :             if (pnode->hSocket == INVALID_SOCKET)
    1284      288071 :                 continue;
    1285             : 
    1286     8279890 :             error_set.insert(pnode->hSocket);
    1287     8279890 :             if (select_send) {
    1288      288071 :                 send_set.insert(pnode->hSocket);
    1289      288071 :                 continue;
    1290             :             }
    1291     7991820 :             if (select_recv) {
    1292    15983600 :                 recv_set.insert(pnode->hSocket);
    1293             :             }
    1294             :         }
    1295             :     }
    1296             : 
    1297             : #ifdef USE_WAKEUP_PIPE
    1298             :     // We add a pipe to the read set so that the select() call can be woken up from the outside
    1299             :     // This is done when data is added to send buffers (vSendMsg) or when new peers are added
    1300             :     // This is currently only implemented for POSIX compliant systems. This means that Windows will fall back to
    1301             :     // timing out after 50ms and then trying to send. This is ok as we assume that heavy-load daemons are usually
    1302             :     // run on Linux and friends.
    1303     1049560 :     recv_set.insert(wakeupPipe[0]);
    1304             : #endif
    1305             : 
    1306     1049560 :     return !recv_set.empty() || !send_set.empty() || !error_set.empty();
    1307             : }
    1308             : 
    1309             : #ifdef USE_POLL
    1310     1049560 : void CConnman::SocketEvents(std::set<SOCKET>& recv_set, std::set<SOCKET>& send_set, std::set<SOCKET>& error_set)
    1311             : {
    1312     2098770 :     std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
    1313     1049560 :     if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
    1314           0 :         interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
    1315         355 :         return;
    1316             :     }
    1317             : 
    1318     2098770 :     std::unordered_map<SOCKET, struct pollfd> pollfds;
    1319    11140400 :     for (SOCKET socket_id : recv_select_set) {
    1320    10090900 :         pollfds[socket_id].fd = socket_id;
    1321    10090900 :         pollfds[socket_id].events |= POLLIN;
    1322             :     }
    1323             : 
    1324     1337630 :     for (SOCKET socket_id : send_select_set) {
    1325      288071 :         pollfds[socket_id].fd = socket_id;
    1326      288071 :         pollfds[socket_id].events |= POLLOUT;
    1327             :     }
    1328             : 
    1329     9329450 :     for (SOCKET socket_id : error_select_set) {
    1330     8279890 :         pollfds[socket_id].fd = socket_id;
    1331             :         // These flags are ignored, but we set them for clarity
    1332     8279890 :         pollfds[socket_id].events |= POLLERR|POLLHUP;
    1333             :     }
    1334             : 
    1335     2098770 :     std::vector<struct pollfd> vpollfds;
    1336     1049560 :     vpollfds.reserve(pollfds.size());
    1337    11428500 :     for (auto it : pollfds) {
    1338    10379000 :         vpollfds.push_back(std::move(it.second));
    1339             :     }
    1340             : 
    1341     1049560 :     wakeupSelectNeeded = true;
    1342     1049560 :     int r = poll(vpollfds.data(), vpollfds.size(), SELECT_TIMEOUT_MILLISECONDS);
    1343     1049560 :     wakeupSelectNeeded = false;
    1344     1049560 :     if (r < 0) {
    1345         355 :         return;
    1346             :     }
    1347             : 
    1348     1049560 :     if (interruptNet) return;
    1349             : 
    1350    11426700 :     for (struct pollfd pollfd_entry : vpollfds) {
    1351    10377500 :         if (pollfd_entry.revents & POLLIN)            recv_set.insert(pollfd_entry.fd);
    1352    10377500 :         if (pollfd_entry.revents & POLLOUT)           send_set.insert(pollfd_entry.fd);
    1353    10377500 :         if (pollfd_entry.revents & (POLLERR|POLLHUP)) error_set.insert(pollfd_entry.fd);
    1354             :     }
    1355             : }
    1356             : #else
    1357             : void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
    1358             : {
    1359             :     std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
    1360             :     if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
    1361             :         interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
    1362             :         return;
    1363             :     }
    1364             : 
    1365             :     //
    1366             :     // Find which sockets have data to receive
    1367             :     //
    1368             :     struct timeval timeout;
    1369             :     timeout.tv_sec  = 0;
    1370             :     timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend
    1371             : 
    1372             :     fd_set fdsetRecv;
    1373             :     fd_set fdsetSend;
    1374             :     fd_set fdsetError;
    1375             :     FD_ZERO(&fdsetRecv);
    1376             :     FD_ZERO(&fdsetSend);
    1377             :     FD_ZERO(&fdsetError);
    1378             :     SOCKET hSocketMax = 0;
    1379             : 
    1380             :     for (SOCKET hSocket : recv_select_set) {
    1381             :         FD_SET(hSocket, &fdsetRecv);
    1382             :         hSocketMax = std::max(hSocketMax, hSocket);
    1383             :     }
    1384             : 
    1385             :     for (SOCKET hSocket : send_select_set) {
    1386             :         FD_SET(hSocket, &fdsetSend);
    1387             :         hSocketMax = std::max(hSocketMax, hSocket);
    1388             :     }
    1389             : 
    1390             :     for (SOCKET hSocket : error_select_set) {
    1391             :         FD_SET(hSocket, &fdsetError);
    1392             :         hSocketMax = std::max(hSocketMax, hSocket);
    1393             :     }
    1394             : 
    1395             :     wakeupSelectNeeded = true;
    1396             :     int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
    1397             :     wakeupSelectNeeded = false;
    1398             : 
    1399             :     if (interruptNet)
    1400             :         return;
    1401             : 
    1402             :     if (nSelect == SOCKET_ERROR) {
    1403             :         int nErr = WSAGetLastError();
    1404             :         LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
    1405             :         for (unsigned int i = 0; i <= hSocketMax; i++)
    1406             :             FD_SET(i, &fdsetRecv);
    1407             :         FD_ZERO(&fdsetSend);
    1408             :         FD_ZERO(&fdsetError);
    1409             :         if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)))
    1410             :             return;
    1411             :     }
    1412             : 
    1413             :     for (SOCKET hSocket : recv_select_set) {
    1414             :         if (FD_ISSET(hSocket, &fdsetRecv)) {
    1415             :             recv_set.insert(hSocket);
    1416             :         }
    1417             :     }
    1418             : 
    1419             :     for (SOCKET hSocket : send_select_set) {
    1420             :         if (FD_ISSET(hSocket, &fdsetSend)) {
    1421             :             send_set.insert(hSocket);
    1422             :         }
    1423             :     }
    1424             : 
    1425             :     for (SOCKET hSocket : error_select_set) {
    1426             :         if (FD_ISSET(hSocket, &fdsetError)) {
    1427             :             error_set.insert(hSocket);
    1428             :         }
    1429             :     }
    1430             : }
    1431             : #endif
    1432             : 
    1433     1049560 : void CConnman::SocketHandler()
    1434             : {
    1435     2098770 :     std::set<SOCKET> recv_set, send_set, error_set;
    1436     1049560 :     SocketEvents(recv_set, send_set, error_set);
    1437             : 
    1438             : #ifdef USE_WAKEUP_PIPE
    1439             :     // drain the wakeup pipe
    1440     1892880 :     if (recv_set.count(wakeupPipe[0])) {
    1441      206240 :         LogPrint(BCLog::NET, "woke up select()\n");
    1442      412480 :         char buf[128];
    1443      412480 :         while (true) {
    1444      412480 :             int r = read(wakeupPipe[0], buf, sizeof(buf));
    1445      412480 :             if (r <= 0) {
    1446             :                 break;
    1447             :             }
    1448             :         }
    1449             :     }
    1450             : #endif
    1451             : 
    1452     1049920 :     if (interruptNet) return;
    1453             : 
    1454             :     //
    1455             :     // Accept new connections
    1456             :     //
    1457     2098370 :     for (const ListenSocket& hListenSocket : vhListenSocket) {
    1458     2097530 :         if (hListenSocket.socket != INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0) {
    1459         791 :             AcceptConnection(hListenSocket);
    1460             :         }
    1461             :     }
    1462             : 
    1463             :     //
    1464             :     // Service each socket
    1465             :     //
    1466     2098410 :     std::vector<CNode*> vNodesCopy = CopyNodeVector();
    1467             : 
    1468     9329770 :     for (CNode* pnode : vNodesCopy) {
    1469     8280560 :         if (interruptNet)
    1470           0 :             return;
    1471             : 
    1472             :         //
    1473             :         // Receive
    1474             :         //
    1475     8280560 :         bool recvSet = false;
    1476     8280560 :         bool sendSet = false;
    1477     8280560 :         bool errorSet = false;
    1478     8280560 :         {
    1479     8280560 :             LOCK(pnode->cs_hSocket);
    1480     8280560 :             if (pnode->hSocket == INVALID_SOCKET)
    1481           0 :                 continue;
    1482     8280560 :             recvSet = recv_set.count(pnode->hSocket) > 0;
    1483     8280560 :             sendSet = send_set.count(pnode->hSocket) > 0;
    1484    16561100 :             errorSet = error_set.count(pnode->hSocket) > 0;
    1485             :         }
    1486     8280560 :         if (recvSet || errorSet) {
    1487             :             // typical socket buffer is 8K-64K
    1488      345074 :             char pchBuf[0x10000];
    1489      345074 :             int nBytes = 0;
    1490      345074 :             {
    1491      345074 :                 LOCK(pnode->cs_hSocket);
    1492      345074 :                 if (pnode->hSocket == INVALID_SOCKET)
    1493           0 :                     continue;
    1494      345074 :                 nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
    1495             :             }
    1496      345074 :             if (nBytes > 0) {
    1497      344736 :                 bool notify = false;
    1498      344736 :                 if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
    1499           1 :                     pnode->CloseSocketDisconnect();
    1500      344736 :                 RecordBytesRecv(nBytes);
    1501      344736 :                 if (notify) {
    1502      242881 :                     size_t nSizeAdded = 0;
    1503      242881 :                     auto it(pnode->vRecvMsg.begin());
    1504      622021 :                     for (; it != pnode->vRecvMsg.end(); ++it) {
    1505      379921 :                         if (!it->complete())
    1506             :                             break;
    1507      379140 :                         nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE;
    1508             :                     }
    1509      242881 :                     {
    1510      242881 :                         LOCK(pnode->cs_vProcessMsg);
    1511      242881 :                         pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
    1512      242881 :                         pnode->nProcessQueueSize += nSizeAdded;
    1513      242881 :                         pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
    1514             :                     }
    1515      242881 :                     WakeMessageHandler();
    1516             :                 }
    1517         338 :             } else if (nBytes == 0) {
    1518             :                 // socket closed gracefully
    1519         331 :                 if (!pnode->fDisconnect)
    1520         331 :                     LogPrint(BCLog::NET, "socket closed\n");
    1521         331 :                 pnode->CloseSocketDisconnect();
    1522           7 :             } else if (nBytes < 0) {
    1523             :                 // error
    1524           7 :                 int nErr = WSAGetLastError();
    1525           7 :                 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) {
    1526           7 :                     if (!pnode->fDisconnect)
    1527          14 :                         LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
    1528           7 :                     pnode->CloseSocketDisconnect();
    1529             :                 }
    1530             :             }
    1531             :         }
    1532             : 
    1533             :         //
    1534             :         // Send
    1535             :         //
    1536     8280560 :         if (sendSet) {
    1537      576142 :             LOCK(pnode->cs_vSend);
    1538      288071 :             size_t nBytes = SocketSendData(pnode);
    1539      288071 :             if (nBytes)
    1540      288071 :                 RecordBytesSent(nBytes);
    1541             :         }
    1542             : 
    1543     8280560 :         InactivityCheck(pnode);
    1544             :     }
    1545     1049210 :     ReleaseNodeVector(vNodesCopy);
    1546             : }
    1547             : 
    1548         355 : void CConnman::ThreadSocketHandler()
    1549             : {
    1550     1049920 :     while (!interruptNet) {
    1551     1049560 :         DisconnectNodes();
    1552     1049560 :         NotifyNumConnectionsChanged();
    1553     1049560 :         SocketHandler();
    1554             :     }
    1555         355 : }
    1556             : 
    1557      242881 : void CConnman::WakeMessageHandler()
    1558             : {
    1559      242881 :     {
    1560      242881 :         std::lock_guard<std::mutex> lock(mutexMsgProc);
    1561      242881 :         fMsgProcWake = true;
    1562             :     }
    1563      242881 :     condMsgProc.notify_one();
    1564      242881 : }
    1565             : 
    1566      206411 : void CConnman::WakeSelect()
    1567             : {
    1568             : #ifdef USE_WAKEUP_PIPE
    1569      206411 :     if (wakeupPipe[1] == -1) {
    1570           0 :         return;
    1571             :     }
    1572             : 
    1573      206411 :     LogPrint(BCLog::NET, "waking up select()\n");
    1574             : 
    1575      206411 :     char buf[1];
    1576      206411 :     if (write(wakeupPipe[1], buf, 1) != 1) {
    1577           0 :         LogPrint(BCLog::NET, "write to wakeupPipe failed\n");
    1578             :     }
    1579             : #endif
    1580             : 
    1581      206411 :     wakeupSelectNeeded = false;
    1582             : }
    1583             : 
    1584           0 : static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredServiceBits)
    1585             : {
    1586             :     //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK)
    1587           0 :     if (!data.supportsServiceBitsFiltering || *requiredServiceBits == NODE_NETWORK) {
    1588           0 :         *requiredServiceBits = NODE_NETWORK;
    1589           0 :         return data.host;
    1590             :     }
    1591             : 
    1592           0 :     return strprintf("x%x.%s", *requiredServiceBits, data.host);
    1593             : }
    1594             : 
    1595             : 
    1596         355 : void CConnman::ThreadDNSAddressSeed()
    1597             : {
    1598             :     // goal: only query DNS seeds if address need is acute
    1599         710 :     if ((addrman.size() > 0) &&
    1600         355 :         (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) {
    1601           0 :         if (!interruptNet.sleep_for(std::chrono::seconds(11)))
    1602           0 :             return;
    1603             : 
    1604           0 :         LOCK(cs_vNodes);
    1605           0 :         int nRelevant = 0;
    1606           0 :         for (auto pnode : vNodes) {
    1607           0 :             nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->fAddnode && !pnode->fInbound && !pnode->m_masternode_probe_connection;
    1608             :         }
    1609           0 :         if (nRelevant >= 2) {
    1610           0 :             LogPrintf("P2P peers available. Skipped DNS seeding.\n");
    1611           0 :             return;
    1612             :         }
    1613             :     }
    1614             : 
    1615         355 :     const std::vector<CDNSSeedData>& vSeeds = Params().DNSSeeds();
    1616         355 :     int found = 0;
    1617             : 
    1618         355 :     LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
    1619             : 
    1620         355 :     for (const CDNSSeedData& seed : vSeeds) {
    1621           0 :         if (interruptNet) {
    1622           0 :             return;
    1623             :         }
    1624           0 :         if (HaveNameProxy()) {
    1625           0 :             AddOneShot(seed.host);
    1626             :         } else {
    1627           0 :             std::vector<CNetAddr> vIPs;
    1628           0 :             std::vector<CAddress> vAdd;
    1629           0 :             ServiceFlags requiredServiceBits = nRelevantServices;
    1630           0 :             std::string host = GetDNSHost(seed, &requiredServiceBits);
    1631           0 :             CNetAddr resolveSource;
    1632           0 :             if (!resolveSource.SetInternal(host)) {
    1633           0 :                 continue;
    1634             :             }
    1635           0 :             if (LookupHost(host, vIPs, 0, true)) {
    1636           0 :                 for (CNetAddr& ip : vIPs) {
    1637           0 :                     int nOneDay = 24*3600;
    1638           0 :                     CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
    1639           0 :                     addr.nTime = GetTime() - 3 * nOneDay - GetRand(4 * nOneDay); // use a random age between 3 and 7 days old
    1640           0 :                     vAdd.push_back(addr);
    1641           0 :                     found++;
    1642             :                 }
    1643           0 :                 addrman.Add(vAdd, resolveSource);
    1644             :             }
    1645             :         }
    1646             :     }
    1647             : 
    1648         355 :     LogPrintf("%d addresses found from DNS seeds\n", found);
    1649             : }
    1650             : 
    1651             : 
    1652             : 
    1653             : 
    1654             : 
    1655             : 
    1656             : 
    1657             : 
    1658             : 
    1659             : 
    1660             : 
    1661             : 
    1662         626 : void CConnman::DumpAddresses()
    1663             : {
    1664         626 :     int64_t nStart = GetTimeMillis();
    1665             : 
    1666         626 :     CAddrDB adb;
    1667         626 :     adb.Write(addrman);
    1668             : 
    1669         626 :     LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat  %dms\n",
    1670             :         addrman.size(), GetTimeMillis() - nStart);
    1671         626 : }
    1672             : 
    1673         356 : void CConnman::DumpData()
    1674             : {
    1675         356 :     DumpAddresses();
    1676         356 :     DumpBanlist();
    1677         356 : }
    1678             : 
    1679       38128 : void CConnman::ProcessOneShot()
    1680             : {
    1681       38128 :     std::string strDest;
    1682       38128 :     {
    1683       38128 :         LOCK(cs_vOneShots);
    1684       38128 :         if (vOneShots.empty())
    1685       76256 :             return;
    1686           0 :         strDest = vOneShots.front();
    1687           0 :         vOneShots.pop_front();
    1688             :     }
    1689           0 :     CAddress addr;
    1690           0 :     CSemaphoreGrant grant(*semOutbound, true);
    1691           0 :     if (grant) {
    1692           0 :         OpenNetworkConnection(addr, false, &grant, strDest.c_str(), true);
    1693             :     }
    1694             : }
    1695             : 
    1696         355 : void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
    1697             : {
    1698             :     // Connect to specific addresses
    1699         355 :     if (!connect.empty()) {
    1700           0 :         for (int64_t nLoop = 0;; nLoop++) {
    1701           0 :             ProcessOneShot();
    1702           0 :             for (const std::string& strAddr : connect) {
    1703           0 :                 CAddress addr(CService(), NODE_NONE);
    1704           0 :                 OpenNetworkConnection(addr, false, nullptr, strAddr.c_str());
    1705           0 :                 for (int i = 0; i < 10 && i < nLoop; i++) {
    1706           0 :                     if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
    1707           0 :                         return;
    1708             :                 }
    1709             :             }
    1710           0 :             if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
    1711             :                 return;
    1712           0 :         }
    1713             :     }
    1714             : 
    1715             :     // Initiate network connections
    1716         355 :     int64_t nStart = GetTime();
    1717             : 
    1718             :     // Minimum time before next feeler connection (in microseconds).
    1719         355 :     int64_t nNextFeeler = PoissonNextSend(nStart * 1000 * 1000, FEELER_INTERVAL);
    1720       38132 :     while (!interruptNet) {
    1721       38128 :         ProcessOneShot();
    1722             : 
    1723       38128 :         if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
    1724         351 :             return;
    1725             : 
    1726       75554 :         CSemaphoreGrant grant(*semOutbound);
    1727       37777 :         if (interruptNet)
    1728         351 :             return;
    1729             : 
    1730             :         // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
    1731       37777 :         if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
    1732       25041 :             static bool done = false;
    1733       25041 :             if (!done) {
    1734         121 :                 LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
    1735         242 :                 CNetAddr local;
    1736         121 :                 local.SetInternal("fixedseeds");
    1737         121 :                 addrman.Add(ConvertSeeds(Params().FixedSeeds()), local);
    1738         121 :                 done = true;
    1739             :             }
    1740             :         }
    1741             : 
    1742             :         //
    1743             :         // Choose an address to connect to based on most recently seen
    1744             :         //
    1745       75554 :         CAddress addrConnect;
    1746             : 
    1747             :         // Only connect out to one peer per network group (/16 for IPv4).
    1748             :         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
    1749       37777 :         int nOutbound = 0;
    1750       75554 :         std::set<std::vector<unsigned char> > setConnected;
    1751       37777 :         {
    1752       37777 :             LOCK(cs_vNodes);
    1753      222106 :             for (const CNode* pnode : vNodes) {
    1754      184329 :                 if (!pnode->fInbound && !pnode->fAddnode && !pnode->m_masternode_connection) {
    1755             :                     // Netgroups for inbound and addnode peers are not excluded because our goal here
    1756             :                     // is to not use multiple of our limited outbound slots on a single netgroup
    1757             :                     // but inbound and addnode peers do not use our outbound slots. Inbound peers
    1758             :                     // also have the added issue that they're attacker controlled and could be used
    1759             :                     // to prevent us from connecting to particular hosts if we used them here.
    1760      172416 :                     setConnected.insert(pnode->addr.GetGroup(addrman.m_asmap));
    1761       86208 :                     nOutbound++;
    1762             :                 }
    1763             :             }
    1764             :         }
    1765             : 
    1766             :         // Feeler Connections
    1767             :         //
    1768             :         // Design goals:
    1769             :         //  * Increase the number of connectable addresses in the tried table.
    1770             :         //
    1771             :         // Method:
    1772             :         //  * Choose a random address from new and attempt to connect to it if we can connect
    1773             :         //    successfully it is added to tried.
    1774             :         //  * Start attempting feeler connections only after node finishes making outbound
    1775             :         //    connections.
    1776             :         //  * Only make a feeler connection once every few minutes.
    1777             :         //
    1778       37777 :         bool fFeeler = false;
    1779       37777 :         if (nOutbound >= nMaxOutbound) {
    1780           0 :             int64_t nTime = GetTimeMicros(); // The current time right now (in microseconds).
    1781           0 :             if (nTime > nNextFeeler) {
    1782           0 :                 nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
    1783           0 :                 fFeeler = true;
    1784             :             } else {
    1785           0 :                 continue;
    1786             :             }
    1787             :         }
    1788             : 
    1789       37777 :         addrman.ResolveCollisions();
    1790             : 
    1791       37777 :         int64_t nANow = GetAdjustedTime();
    1792             :         int nTries = 0;
    1793       38365 :         while (!interruptNet) {
    1794       38365 :             CAddrInfo addr = addrman.SelectTriedCollision();
    1795             : 
    1796             :             // SelectTriedCollision returns an invalid address if it is empty.
    1797       38365 :             if (!fFeeler || !addr.IsValid()) {
    1798       38365 :                 addr = addrman.Select(fFeeler);
    1799             :             }
    1800             : 
    1801             :             // Require outbound connections, other than feelers, to be to distinct network groups
    1802      115095 :             if (!fFeeler && setConnected.count(addr.GetGroup(addrman.m_asmap))) {
    1803             :                 break;
    1804             :             }
    1805             : 
    1806             :             // if we selected an invalid or local address, restart
    1807        9829 :             if (!addr.IsValid() || IsLocal(addr)) {
    1808             :                 break;
    1809             :             }
    1810             : 
    1811             :             // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
    1812             :             // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
    1813             :             // already-connected network ranges, ...) before trying new addrman addresses.
    1814         600 :             nTries++;
    1815         600 :             if (nTries > 100)
    1816             :                 break;
    1817             : 
    1818         600 :             if (!IsReachable(addr))
    1819         588 :                 continue;
    1820             : 
    1821             :             // only connect to full nodes
    1822         600 :             if ((addr.nServices & REQUIRED_SERVICES) != REQUIRED_SERVICES)
    1823           0 :                 continue;
    1824             : 
    1825             :             // only consider very recently tried nodes after 30 failed attempts
    1826         600 :             if (nANow - addr.nLastTry < 600 && nTries < 30)
    1827         261 :                 continue;
    1828             : 
    1829             :             // do not allow non-default ports, unless after 50 invalid addresses selected already
    1830         339 :             if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
    1831         327 :                 continue;
    1832             : 
    1833       37789 :             addrConnect = addr;
    1834             :             break;
    1835             :         }
    1836             : 
    1837       37777 :         if (addrConnect.IsValid()) {
    1838          12 :             if (fFeeler) {
    1839             :                 // Add small amount of random noise before connection to avoid synchronization.
    1840           0 :                 int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000);
    1841           0 :                 if (!interruptNet.sleep_for(std::chrono::milliseconds(randsleep)))
    1842           0 :                     return;
    1843           0 :                 LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString());
    1844             :             }
    1845             : 
    1846          24 :             OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant, nullptr, false, fFeeler);
    1847             :         }
    1848             :     }
    1849             : }
    1850             : 
    1851        9713 : std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo()
    1852             : {
    1853        9713 :     std::vector<AddedNodeInfo> ret;
    1854             : 
    1855        9713 :     std::list<std::string> lAddresses(0);
    1856        9713 :     {
    1857        9713 :         LOCK(cs_vAddedNodes);
    1858        9713 :         ret.reserve(vAddedNodes.size());
    1859        9713 :         std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), std::back_inserter(lAddresses));
    1860             :     }
    1861             : 
    1862             : 
    1863             :     // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
    1864       19426 :     std::map<CService, bool> mapConnected;
    1865        9713 :     std::map<std::string, std::pair<bool, CService> > mapConnectedByName;
    1866        9713 :     {
    1867        9713 :         LOCK(cs_vNodes);
    1868       55741 :         for (const CNode* pnode : vNodes) {
    1869       46028 :             if (pnode->addr.IsValid()) {
    1870       46028 :                 mapConnected[pnode->addr] = pnode->fInbound;
    1871             :             }
    1872       92056 :             std::string addrName = pnode->GetAddrName();
    1873       46028 :             if (!addrName.empty()) {
    1874       46028 :                 mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->fInbound, static_cast<const CService&>(pnode->addr));
    1875             :             }
    1876             :         }
    1877             :     }
    1878             : 
    1879        9716 :     for (const std::string& strAddNode : lAddresses) {
    1880           6 :         CService service(LookupNumeric(strAddNode, Params().GetDefaultPort()));
    1881           6 :         AddedNodeInfo addedNode{strAddNode, CService(), false, false};
    1882           3 :         if (service.IsValid()) {
    1883             :             // strAddNode is an IP:port
    1884           3 :             auto it = mapConnected.find(service);
    1885           3 :             if (it != mapConnected.end()) {
    1886           0 :                 addedNode.resolvedAddress = service;
    1887           0 :                 addedNode.fConnected = true;
    1888           0 :                 addedNode.fInbound = it->second;
    1889             :             }
    1890             :         } else {
    1891             :             // strAddNode is a name
    1892           0 :             auto it = mapConnectedByName.find(strAddNode);
    1893           0 :             if (it != mapConnectedByName.end()) {
    1894           0 :                 addedNode.resolvedAddress = it->second.second;
    1895           0 :                 addedNode.fConnected = true;
    1896           0 :                 addedNode.fInbound = it->second.first;
    1897             :             }
    1898             :         }
    1899           3 :         ret.emplace_back(std::move(addedNode));
    1900             :     }
    1901             : 
    1902       19426 :     return ret;
    1903             : }
    1904             : 
    1905         355 : void CConnman::ThreadOpenAddedConnections()
    1906             : {
    1907        9710 :     while (true) {
    1908        9710 :         CSemaphoreGrant grant(*semAddnode);
    1909       19065 :         std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
    1910        9710 :         bool tried = false;
    1911        9711 :         for (const AddedNodeInfo& info : vInfo) {
    1912           1 :             if (!info.fConnected) {
    1913           1 :                 if (!grant.TryAcquire()) {
    1914             :                     // If we've used up our semaphore and need a new one, lets not wait here since while we are waiting
    1915             :                     // the addednodeinfo state might change.
    1916             :                     break;
    1917             :                 }
    1918           1 :                 tried = true;
    1919           3 :                 CAddress addr(CService(), NODE_NONE);
    1920           1 :                 OpenNetworkConnection(addr, false, &grant, info.strAddedNode.c_str(), false, false, true);
    1921           1 :                 if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
    1922           0 :                     return;
    1923             :             }
    1924             :         }
    1925             :         // Retry every 60 seconds if a connection was attempted, otherwise two seconds
    1926       19419 :         if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)))
    1927             :             return;
    1928             :     }
    1929             : }
    1930             : 
    1931             : // if successful, this moves the passed grant to the constructed node
    1932         748 : void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* pszDest, bool fOneShot, bool fFeeler, bool fAddnode, bool masternode_connection, bool masternode_probe_connection)
    1933             : {
    1934             :     //
    1935             :     // Initiate outbound network connection
    1936             :     //
    1937         748 :     if (interruptNet || !fNetworkActive) {
    1938          55 :         return;
    1939             :     }
    1940         748 :     if (!pszDest) {
    1941          24 :         if (IsLocal(addrConnect) ||
    1942          60 :             FindNode(static_cast<CNetAddr>(addrConnect)) || IsBanned(addrConnect) ||
    1943          36 :             FindNode(addrConnect.ToStringIPPort()))
    1944             :             return;
    1945             :     } else {
    1946         736 :         CNode* pnode = FindNode(pszDest);
    1947         736 :         if (pnode) {
    1948             :             // If this is a mnauth connection and the node is already connected normally,
    1949             :             // disconnect it and open a new connection
    1950         128 :             if (masternode_connection && !pnode->m_masternode_connection) {
    1951          86 :                 pnode->fDisconnect = true;
    1952             :             } else {
    1953          42 :                 return;
    1954             :             }
    1955             :         }
    1956             :     }
    1957             : 
    1958         706 :     CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, fAddnode);
    1959             : 
    1960         706 :     if (!pnode)
    1961             :         return;
    1962         693 :     if (grantOutbound)
    1963           0 :         grantOutbound->MoveTo(pnode->grantOutbound);
    1964         693 :     if (fOneShot)
    1965           0 :         pnode->fOneShot = true;
    1966         693 :     if (fFeeler)
    1967           0 :         pnode->fFeeler = true;
    1968         693 :     if (fAddnode)
    1969           0 :         pnode->fAddnode = true;
    1970         693 :     if (masternode_connection)
    1971         132 :         pnode->m_masternode_connection = true;
    1972         693 :     if (masternode_probe_connection)
    1973          49 :         pnode->m_masternode_probe_connection = true;
    1974             : 
    1975         693 :     m_msgproc->InitializeNode(pnode);
    1976         693 :     {
    1977        1386 :         LOCK(cs_vNodes);
    1978         693 :         vNodes.push_back(pnode);
    1979             :     }
    1980             : }
    1981             : 
    1982         355 : void CConnman::ThreadMessageHandler()
    1983             : {
    1984         355 :     int64_t nLastSendMessagesTimeMasternodes = 0;
    1985             : 
    1986      386203 :     while (!flagInterruptMsgProc) {
    1987      771696 :         std::vector<CNode*> vNodesCopy = CopyNodeVector();
    1988             : 
    1989      385848 :         bool fMoreWork = false;
    1990             : 
    1991             :         // Don't send other messages to quorum nodes too often
    1992      385848 :         bool fSkipSendMessagesForMasternodes = true;
    1993      385848 :         if (GetTimeMillis() - nLastSendMessagesTimeMasternodes >= 100) {
    1994      180333 :             fSkipSendMessagesForMasternodes = false;
    1995      180333 :             nLastSendMessagesTimeMasternodes = GetTimeMillis();
    1996             :         }
    1997             : 
    1998     2423560 :         for (CNode* pnode : vNodesCopy) {
    1999     2037710 :             if (pnode->fDisconnect)
    2000         100 :                 continue;
    2001             : 
    2002             :             // Receive messages
    2003     2037610 :             bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
    2004     2037610 :             fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
    2005     2037610 :             if (flagInterruptMsgProc)
    2006           0 :                 return;
    2007             : 
    2008             :             // Send messages
    2009     2037610 :             if (!fSkipSendMessagesForMasternodes || !pnode->m_masternode_connection) {
    2010     3911790 :                 LOCK(pnode->cs_sendProcessing);
    2011     1955900 :                 m_msgproc->SendMessages(pnode, flagInterruptMsgProc);
    2012             :             }
    2013             : 
    2014     2037610 :             if (flagInterruptMsgProc)
    2015             :                 return;
    2016             :         }
    2017             : 
    2018             : 
    2019      385848 :         ReleaseNodeVector(vNodesCopy);
    2020             : 
    2021      771696 :         std::unique_lock<std::mutex> lock(mutexMsgProc);
    2022      385848 :         if (!fMoreWork) {
    2023      503002 :             condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this] { return fMsgProcWake; });
    2024             :         }
    2025      385848 :         fMsgProcWake = false;
    2026             :     }
    2027             : }
    2028             : 
    2029         346 : bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, bool fWhitelisted)
    2030             : {
    2031         346 :     strError = "";
    2032         346 :     int nOne = 1;
    2033             : 
    2034             :     // Create socket for listening for incoming connections
    2035         346 :     struct sockaddr_storage sockaddr;
    2036         346 :     socklen_t len = sizeof(sockaddr);
    2037         346 :     if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
    2038           0 :         strError = strprintf("Error: Bind address family for %s not supported", addrBind.ToString());
    2039           0 :         LogPrintf("%s\n", strError);
    2040           0 :         return false;
    2041             :     }
    2042             : 
    2043         346 :     SOCKET hListenSocket = CreateSocket(addrBind);
    2044         346 :     if (hListenSocket == INVALID_SOCKET) {
    2045           0 :         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()));
    2046           0 :         LogPrintf("%s\n", strError);
    2047           0 :         return false;
    2048             :     }
    2049             : 
    2050             : #ifndef WIN32
    2051             :     // Allow binding if the port is still in TIME_WAIT state after
    2052             :     // the program was closed and restarted. Not an issue on windows!
    2053         346 :     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
    2054             : #endif
    2055             : 
    2056             :     // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
    2057             :     // and enable it by default or not. Try to enable it, if possible.
    2058         346 :     if (addrBind.IsIPv6()) {
    2059             : #ifdef IPV6_V6ONLY
    2060           1 :         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_arg_type)&nOne, sizeof(int));
    2061             : #endif
    2062             : #ifdef WIN32
    2063             :         int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
    2064             :         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
    2065             : #endif
    2066             :     }
    2067             : 
    2068         346 :     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) {
    2069           0 :         int nErr = WSAGetLastError();
    2070           0 :         if (nErr == WSAEADDRINUSE)
    2071           0 :             strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
    2072             :         else
    2073           0 :             strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
    2074           0 :         LogPrintf("%s\n", strError);
    2075           0 :         CloseSocket(hListenSocket);
    2076           0 :         return false;
    2077             :     }
    2078         346 :     LogPrintf("Bound to %s\n", addrBind.ToString());
    2079             : 
    2080             :     // Listen for incoming connections
    2081         346 :     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) {
    2082           0 :         strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
    2083           0 :         LogPrintf("%s\n", strError);
    2084           0 :         CloseSocket(hListenSocket);
    2085           0 :         return false;
    2086             :     }
    2087             : 
    2088         346 :     vhListenSocket.emplace_back(hListenSocket, fWhitelisted);
    2089             : 
    2090         346 :     if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
    2091           0 :         AddLocal(addrBind, LOCAL_BIND);
    2092             : 
    2093             :     return true;
    2094             : }
    2095             : 
    2096         355 : void Discover()
    2097             : {
    2098         355 :     if (!fDiscover)
    2099         355 :         return;
    2100             : 
    2101             : #ifdef WIN32
    2102             :     // Get local host IP
    2103             :     char pszHostName[256] = "";
    2104             :     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) {
    2105             :         std::vector<CNetAddr> vaddr;
    2106             :         if (LookupHost(pszHostName, vaddr, 0, true)) {
    2107             :             for (const CNetAddr& addr : vaddr) {
    2108             :                 if (AddLocal(addr, LOCAL_IF))
    2109             :                     LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
    2110             :             }
    2111             :         }
    2112             :     }
    2113             : #elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
    2114             :     // Get local host ip
    2115           0 :     struct ifaddrs* myaddrs;
    2116           0 :     if (getifaddrs(&myaddrs) == 0) {
    2117           0 :         for (struct ifaddrs* ifa = myaddrs; ifa != nullptr; ifa = ifa->ifa_next) {
    2118           0 :             if (ifa->ifa_addr == nullptr) continue;
    2119           0 :             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
    2120           0 :             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
    2121           0 :             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
    2122           0 :             if (ifa->ifa_addr->sa_family == AF_INET) {
    2123           0 :                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
    2124           0 :                 CNetAddr addr(s4->sin_addr);
    2125           0 :                 if (AddLocal(addr, LOCAL_IF))
    2126           0 :                     LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
    2127           0 :             } else if (ifa->ifa_addr->sa_family == AF_INET6) {
    2128           0 :                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
    2129           0 :                 CNetAddr addr(s6->sin6_addr);
    2130           0 :                 if (AddLocal(addr, LOCAL_IF))
    2131           0 :                     LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
    2132             :             }
    2133             :         }
    2134           0 :         freeifaddrs(myaddrs);
    2135             :     }
    2136             : #endif
    2137             : }
    2138             : 
    2139          19 : void CConnman::SetNetworkActive(bool active)
    2140             : {
    2141          19 :     LogPrint(BCLog::NET, "SetNetworkActive: %s\n", active);
    2142             : 
    2143          19 :     if (fNetworkActive == active) {
    2144             :         return;
    2145             :     }
    2146             : 
    2147          19 :     fNetworkActive = active;
    2148             : 
    2149          19 :     if (clientInterface) clientInterface->NotifyNetworkActiveChanged(fNetworkActive);
    2150             : }
    2151             : 
    2152         968 : CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In)
    2153             : {
    2154         484 :     setBannedIsDirty = false;
    2155         484 :     fAddressesInitialized = false;
    2156         484 :     nLastNodeId = 0;
    2157         484 :     nPrevNodeCount = 0;
    2158         484 :     nSendBufferMaxSize = 0;
    2159         484 :     nReceiveFloodSize = 0;
    2160         484 :     flagInterruptMsgProc = false;
    2161             : 
    2162         484 :     Options connOptions;
    2163         484 :     Init(connOptions);
    2164             :     // init tier two connections manager
    2165         484 :     m_tiertwo_conn_man = std::make_unique<TierTwoConnMan>(this);
    2166         484 : }
    2167             : 
    2168        1456 : NodeId CConnman::GetNewNodeId()
    2169             : {
    2170        1456 :     return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
    2171             : }
    2172             : 
    2173         346 : bool CConnman::Bind(const CService& addr, unsigned int flags) {
    2174         346 :     if (!(flags & BF_EXPLICIT) && !IsReachable(addr))
    2175             :         return false;
    2176         692 :     std::string strError;
    2177         346 :     if (!BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) {
    2178           0 :         if ((flags & BF_REPORT_ERROR) && clientInterface) {
    2179           0 :             clientInterface->ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR);
    2180             :         }
    2181           0 :         return false;
    2182             :     }
    2183             :     return true;
    2184             : }
    2185             : 
    2186         345 : bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<CService>& whiteBinds) {
    2187         345 :     bool fBound = false;
    2188         689 :     for (const auto& addrBind : binds) {
    2189         344 :         fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
    2190             :     }
    2191         345 :     for (const auto& addrBind : whiteBinds) {
    2192           0 :         fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST));
    2193             :     }
    2194         345 :     if (binds.empty() && whiteBinds.empty()) {
    2195           1 :         struct in_addr inaddr_any;
    2196           1 :         inaddr_any.s_addr = INADDR_ANY;
    2197           1 :         fBound |= Bind(CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE);
    2198           1 :         fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE);
    2199             :     }
    2200         345 :     return fBound;
    2201             : }
    2202             : 
    2203         355 : bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
    2204             : {
    2205         355 :     Init(connOptions);
    2206             : 
    2207         355 :     {
    2208         355 :         LOCK(cs_totalBytesRecv);
    2209         355 :         nTotalBytesRecv = 0;
    2210             :     }
    2211         355 :     {
    2212         355 :         LOCK(cs_totalBytesSent);
    2213         355 :         nTotalBytesSent = 0;
    2214             :     }
    2215             : 
    2216         355 :     if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) {
    2217           0 :         if (clientInterface) {
    2218           0 :             clientInterface->ThreadSafeMessageBox(
    2219           0 :                     _("Failed to listen on any port. Use -listen=0 if you want this."),
    2220             :                     "", CClientUIInterface::MSG_ERROR);
    2221             :         }
    2222           0 :         return false;
    2223             :     }
    2224             : 
    2225         355 :     for (const auto& strDest : connOptions.vSeedNodes) {
    2226           0 :         AddOneShot(strDest);
    2227             :     }
    2228             : 
    2229         355 :     if (clientInterface)
    2230         710 :         clientInterface->InitMessage(_("Loading addresses..."));
    2231         355 :     m_msgproc = connOptions.m_msgproc;
    2232             :     // Load addresses from peers.dat
    2233         355 :     int64_t nStart = GetTimeMillis();
    2234         355 :     {
    2235         355 :         CAddrDB adb;
    2236         355 :         if (adb.Read(addrman))
    2237          85 :             LogPrintf("Loaded %i addresses from peers.dat  %dms\n", addrman.size(), GetTimeMillis() - nStart);
    2238             :         else {
    2239         270 :             addrman.Clear(); // Addrman can be in an inconsistent state after failure, reset it
    2240         270 :             LogPrintf("Invalid or missing peers.dat; recreating\n");
    2241         270 :             DumpAddresses();
    2242             :         }
    2243             :     }
    2244         355 :     if (clientInterface)
    2245         710 :         clientInterface->InitMessage(_("Loading banlist..."));
    2246             :     // Load addresses from banlist.dat
    2247         355 :     nStart = GetTimeMillis();
    2248         710 :     CBanDB bandb;
    2249         710 :     banmap_t banmap;
    2250         355 :     if (bandb.Read(banmap)) {
    2251          86 :         SetBanned(banmap); // thread save setter
    2252          86 :         SetBannedSetDirty(false); // no need to write down, just read data
    2253          86 :         SweepBanned(); // sweep out unused entries
    2254             : 
    2255          86 :         LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat  %dms\n",
    2256             :             banmap.size(), GetTimeMillis() - nStart);
    2257             :     } else {
    2258         269 :         LogPrintf("Invalid or missing banlist.dat; recreating\n");
    2259         269 :         SetBannedSetDirty(true); // force write
    2260         269 :         DumpBanlist();
    2261             :     }
    2262             : 
    2263             :     // Initialize random numbers. Even when rand() is only usable for trivial use-cases most nodes should have a different
    2264             :     // seed after all the file-IO done at this point. Should be good enough even when nodes are started via scripts.
    2265         355 :     srand(time(nullptr));
    2266             : 
    2267         355 :     fAddressesInitialized = true;
    2268             : 
    2269         355 :     if (semOutbound == nullptr) {
    2270             :         // initialize semaphore
    2271         355 :         semOutbound = std::make_unique<CSemaphore>(std::min((nMaxOutbound + nMaxFeeler), nMaxConnections));
    2272             :     }
    2273         355 :     if (semAddnode == nullptr) {
    2274             :         // initialize semaphore
    2275         355 :         semAddnode = std::make_unique<CSemaphore>(nMaxAddnode);
    2276             :     }
    2277             : 
    2278             :     //
    2279             :     // Start threads
    2280             :     //
    2281         355 :     assert(m_msgproc);
    2282         355 :     InterruptSocks5(false);
    2283         355 :     interruptNet.reset();
    2284         355 :     flagInterruptMsgProc = false;
    2285             : 
    2286         355 :     {
    2287         355 :         std::unique_lock<std::mutex> lock(mutexMsgProc);
    2288         355 :         fMsgProcWake = false;
    2289             :     }
    2290             : 
    2291             : #ifdef USE_WAKEUP_PIPE
    2292         355 :     if (pipe(wakeupPipe) != 0) {
    2293           0 :         wakeupPipe[0] = wakeupPipe[1] = -1;
    2294           0 :         LogPrint(BCLog::NET, "pipe() for wakeupPipe failed\n");
    2295             :     } else {
    2296         355 :         int fFlags = fcntl(wakeupPipe[0], F_GETFL, 0);
    2297         355 :         if (fcntl(wakeupPipe[0], F_SETFL, fFlags | O_NONBLOCK) == -1) {
    2298           0 :             LogPrint(BCLog::NET, "fcntl for O_NONBLOCK on wakeupPipe failed\n");
    2299             :         }
    2300         355 :         fFlags = fcntl(wakeupPipe[1], F_GETFL, 0);
    2301         355 :         if (fcntl(wakeupPipe[1], F_SETFL, fFlags | O_NONBLOCK) == -1) {
    2302           0 :             LogPrint(BCLog::NET, "fcntl for O_NONBLOCK on wakeupPipe failed\n");
    2303             :         }
    2304             :     }
    2305             : #endif
    2306             : 
    2307             :     // Send and receive from sockets, accept connections
    2308         355 :     threadSocketHandler = std::thread(&TraceThread<std::function<void()> >, "net", std::function<void()>(std::bind(&CConnman::ThreadSocketHandler, this)));
    2309             : 
    2310         355 :     if (!gArgs.GetBoolArg("-dnsseed", true))
    2311           0 :         LogPrintf("DNS seeding disabled\n");
    2312             :     else
    2313         355 :         threadDNSAddressSeed = std::thread(&TraceThread<std::function<void()> >, "dnsseed", std::function<void()>(std::bind(&CConnman::ThreadDNSAddressSeed, this)));
    2314             : 
    2315             :     // Initiate outbound connections from -addnode
    2316         355 :     threadOpenAddedConnections = std::thread(&TraceThread<std::function<void()> >, "addcon", std::function<void()>(std::bind(&CConnman::ThreadOpenAddedConnections, this)));
    2317             : 
    2318             :     // Start tier two connection manager
    2319         355 :     if (m_tiertwo_conn_man) {
    2320         355 :         TierTwoConnMan::Options opts;
    2321         355 :         opts.m_has_specified_outgoing = !connOptions.m_specified_outgoing.empty();
    2322         355 :         m_tiertwo_conn_man->start(scheduler, opts);
    2323             :     }
    2324             : 
    2325         355 :     if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
    2326           0 :         if (clientInterface) {
    2327           0 :             clientInterface->ThreadSafeMessageBox(
    2328           0 :                     _("Cannot provide specific connections and have addrman find outgoing connections at the same."),
    2329             :                     "", CClientUIInterface::MSG_ERROR);
    2330             :         }
    2331           0 :         return false;
    2332             :     }
    2333         355 :     if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {
    2334         710 :         threadOpenConnections = std::thread(&TraceThread<std::function<void()> >, "opencon", std::function<void()>(
    2335        1065 :                 std::bind(&CConnman::ThreadOpenConnections, this, connOptions.m_specified_outgoing)));
    2336             :     }
    2337             : 
    2338             :     // Process messages
    2339         355 :     threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));
    2340             : 
    2341             :     // Dump network addresses
    2342         355 :     scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL * 1000);
    2343             : 
    2344         355 :     return true;
    2345             : }
    2346             : 
    2347             : class CNetCleanup
    2348             : {
    2349             : public:
    2350           0 :     CNetCleanup() {}
    2351             : 
    2352         479 :     ~CNetCleanup()
    2353             :     {
    2354             : #ifdef WIN32
    2355             :         // Shutdown Windows Sockets
    2356             :         WSACleanup();
    2357             : #endif
    2358         479 :     }
    2359             : }
    2360             : instance_of_cnetcleanup;
    2361             : 
    2362           0 : void CExplicitNetCleanup::callCleanup()
    2363             : {
    2364             :     // Explicit call to destructor of CNetCleanup because it's not implicitly called
    2365             :     // when the wallet is restarted from within the wallet itself.
    2366           0 :     CNetCleanup* tmp = new CNetCleanup();
    2367           0 :     delete tmp; // Stroustrup's gonna kill me for that
    2368           0 : }
    2369             : 
    2370         850 : void CConnman::Interrupt()
    2371             : {
    2372         850 :     {
    2373         850 :         std::lock_guard<std::mutex> lock(mutexMsgProc);
    2374         850 :         flagInterruptMsgProc = true;
    2375             :     }
    2376         850 :     condMsgProc.notify_all();
    2377             : 
    2378         850 :     interruptNet();
    2379         850 :     if (m_tiertwo_conn_man) m_tiertwo_conn_man->interrupt();
    2380         850 :     InterruptSocks5(true);
    2381             : 
    2382         850 :     if (semOutbound) {
    2383        6390 :         for (int i=0; i<(nMaxOutbound + nMaxFeeler); i++) {
    2384        6035 :             semOutbound->post();
    2385             :         }
    2386             :     }
    2387             : 
    2388         850 :     if (semAddnode) {
    2389        6035 :         for (int i=0; i<nMaxAddnode; i++) {
    2390        5680 :             semAddnode->post();
    2391             :         }
    2392             :     }
    2393         850 : }
    2394             : 
    2395         850 : void CConnman::Stop()
    2396             : {
    2397         850 :     if (threadMessageHandler.joinable())
    2398         355 :         threadMessageHandler.join();
    2399         850 :     if (threadOpenConnections.joinable())
    2400         355 :         threadOpenConnections.join();
    2401         850 :     if (threadOpenAddedConnections.joinable())
    2402         355 :         threadOpenAddedConnections.join();
    2403         850 :     if (threadDNSAddressSeed.joinable())
    2404         355 :         threadDNSAddressSeed.join();
    2405         850 :     if (threadSocketHandler.joinable())
    2406         355 :         threadSocketHandler.join();
    2407             :     // Stop tier two connection manager
    2408         850 :     if (m_tiertwo_conn_man) m_tiertwo_conn_man->stop();
    2409             : 
    2410         850 :     if (fAddressesInitialized)
    2411             :     {
    2412         355 :         DumpData();
    2413         355 :         fAddressesInitialized = false;
    2414             :     }
    2415             : 
    2416             :     // Close sockets
    2417        1630 :     for(CNode* pnode : vNodes)
    2418         780 :         pnode->CloseSocketDisconnect();
    2419        1196 :     for(ListenSocket& hListenSocket : vhListenSocket)
    2420         346 :         if (hListenSocket.socket != INVALID_SOCKET)
    2421         346 :             if (!CloseSocket(hListenSocket.socket))
    2422           0 :                 LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
    2423             : 
    2424             :     // clean up some globals (to help leak detection)
    2425        1630 :     for(CNode* pnode : vNodes) {
    2426         780 :         DeleteNode(pnode);
    2427             :     }
    2428         850 :     for(CNode* pnode : vNodesDisconnected) {
    2429           0 :         DeleteNode(pnode);
    2430             :     }
    2431         850 :     vNodes.clear();
    2432         850 :     vNodesDisconnected.clear();
    2433         850 :     vhListenSocket.clear();
    2434         850 :     semOutbound.reset();
    2435         850 :     semAddnode.reset();
    2436             : #ifdef USE_WAKEUP_PIPE
    2437         850 :     if (wakeupPipe[0] != -1) close(wakeupPipe[0]);
    2438         850 :     if (wakeupPipe[1] != -1) close(wakeupPipe[1]);
    2439         850 :     wakeupPipe[0] = wakeupPipe[1] = -1;
    2440             : #endif
    2441         850 : }
    2442             : 
    2443        1456 : void CConnman::DeleteNode(CNode* pnode)
    2444             : {
    2445        1456 :     assert(pnode);
    2446        1456 :     bool fUpdateConnectionTime = false;
    2447        1456 :     m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
    2448        1456 :     if (fUpdateConnectionTime) {
    2449         642 :         addrman.Connected(pnode->addr);
    2450             :     }
    2451        1456 :     delete pnode;
    2452        1456 : }
    2453             : 
    2454        1077 : CConnman::~CConnman()
    2455             : {
    2456         484 :     Interrupt();
    2457         484 :     Stop();
    2458         484 : }
    2459             : 
    2460         648 : void CConnman::SetServices(const CService &addr, ServiceFlags nServices)
    2461             : {
    2462         648 :     addrman.SetServices(addr, nServices);
    2463         648 : }
    2464             : 
    2465         648 : void CConnman::MarkAddressGood(const CAddress& addr)
    2466             : {
    2467         648 :     addrman.Good(addr);
    2468         648 : }
    2469             : 
    2470          66 : void CConnman::AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty)
    2471             : {
    2472          66 :     addrman.Add(addr, addrFrom, nTimePenalty);
    2473          66 : }
    2474             : 
    2475       10010 : bool CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
    2476             : {
    2477       10010 :     return addrman.Add(vAddr, addrFrom, nTimePenalty);
    2478             : }
    2479             : 
    2480         654 : std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct, Optional<Network> network)
    2481             : {
    2482         654 :     return addrman.GetAddr(max_addresses, max_pct, network);
    2483             : }
    2484             : 
    2485           1 : bool CConnman::AddNode(const std::string& strNode)
    2486             : {
    2487           2 :     LOCK(cs_vAddedNodes);
    2488           1 :     for (const std::string& it : vAddedNodes) {
    2489           0 :         if (strNode == it) return false;
    2490             :     }
    2491             : 
    2492           1 :     vAddedNodes.push_back(strNode);
    2493             :     return true;
    2494             : }
    2495             : 
    2496           0 : bool CConnman::RemoveAddedNode(const std::string& strNode)
    2497             : {
    2498           0 :     LOCK(cs_vAddedNodes);
    2499           0 :     for(std::vector<std::string>::iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) {
    2500           0 :         if (strNode == *it) {
    2501           0 :             vAddedNodes.erase(it);
    2502           0 :             return true;
    2503             :         }
    2504             :     }
    2505           0 :     return false;
    2506             : }
    2507             : 
    2508         226 : size_t CConnman::GetMaxOutboundNodeCount()
    2509             : {
    2510         226 :     return nMaxOutbound;
    2511             : }
    2512             : 
    2513        1787 : size_t CConnman::GetNodeCount(NumConnections flags)
    2514             : {
    2515        1787 :     LOCK(cs_vNodes);
    2516        1787 :     if (flags == CConnman::CONNECTIONS_ALL) // Shortcut if we want total
    2517        1787 :         return vNodes.size();
    2518             : 
    2519           0 :     int nNum = 0;
    2520           0 :     for (const auto& pnode : vNodes) {
    2521           0 :         if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) {
    2522           0 :             nNum++;
    2523             :         }
    2524             :     }
    2525             : 
    2526           0 :     return nNum;
    2527             : }
    2528             : 
    2529       16992 : void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats)
    2530             : {
    2531       16992 :     vstats.clear();
    2532       16992 :     LOCK(cs_vNodes);
    2533       16992 :     vstats.reserve(vNodes.size());
    2534       78365 :     for (CNode* pnode : vNodes) {
    2535       61373 :         vstats.emplace_back();
    2536       61373 :         pnode->copyStats(vstats.back(), addrman.m_asmap);
    2537             :     }
    2538       16992 : }
    2539             : 
    2540          25 : bool CConnman::DisconnectNode(const std::string& strNode)
    2541             : {
    2542          50 :     LOCK(cs_vNodes);
    2543          25 :     if (CNode* pnode = FindNode(strNode)) {
    2544          24 :         pnode->fDisconnect = true;
    2545          24 :         return true;
    2546             :     }
    2547             :     return false;
    2548             : }
    2549             : 
    2550           0 : bool CConnman::DisconnectNode(NodeId id)
    2551             : {
    2552           0 :     LOCK(cs_vNodes);
    2553           0 :     for(CNode* pnode : vNodes) {
    2554           0 :         if (id == pnode->GetId()) {
    2555           0 :             pnode->fDisconnect = true;
    2556           0 :             return true;
    2557             :         }
    2558             :     }
    2559           0 :     return false;
    2560             : }
    2561             : 
    2562       15462 : void CConnman::RelayInv(CInv& inv, int minProtoVersion)
    2563             : {
    2564       15462 :     LOCK(cs_vNodes);
    2565       60344 :     for (CNode* pnode : vNodes){
    2566       44882 :         if (!pnode->fSuccessfullyConnected) continue;
    2567       44872 :         if ((pnode->nServices == NODE_BLOOM_WITHOUT_MN) && inv.IsMasterNodeType()) continue;
    2568       44872 :         if (!pnode->CanRelay()) continue;
    2569       44860 :         if (pnode->nVersion >= minProtoVersion)
    2570       44860 :             pnode->PushInventory(inv);
    2571             :     }
    2572       15462 : }
    2573             : 
    2574       56830 : void CConnman::RemoveAskFor(const uint256& invHash, int invType)
    2575             : {
    2576       56830 :     mapAlreadyAskedFor.erase(CInv(invType, invHash));
    2577             : 
    2578       56830 :     LOCK(cs_vNodes);
    2579      152474 :     for (const auto& pnode : vNodes) {
    2580       95644 :         pnode->AskForInvReceived(invHash);
    2581             :     }
    2582       56830 : }
    2583             : 
    2584         108 : void CConnman::UpdateQuorumRelayMemberIfNeeded(CNode* pnode)
    2585             : {
    2586         113 :     if (!pnode->m_masternode_iqr_connection && pnode->m_masternode_connection &&
    2587         118 :         m_tiertwo_conn_man->isMasternodeQuorumRelayMember(WITH_LOCK(pnode->cs_mnauth, return pnode->verifiedProRegTxHash))) {
    2588           0 :         pnode->m_masternode_iqr_connection = true;
    2589             :     }
    2590         108 : }
    2591             : 
    2592      344736 : void CConnman::RecordBytesRecv(uint64_t bytes)
    2593             : {
    2594      344736 :     LOCK(cs_totalBytesRecv);
    2595      344736 :     nTotalBytesRecv += bytes;
    2596      344736 : }
    2597             : 
    2598      288071 : void CConnman::RecordBytesSent(uint64_t bytes)
    2599             : {
    2600      288071 :     LOCK(cs_totalBytesSent);
    2601      288071 :     nTotalBytesSent += bytes;
    2602      288071 : }
    2603             : 
    2604           5 : uint64_t CConnman::GetTotalBytesRecv()
    2605             : {
    2606           5 :     LOCK(cs_totalBytesRecv);
    2607           5 :     return nTotalBytesRecv;
    2608             : }
    2609             : 
    2610           5 : uint64_t CConnman::GetTotalBytesSent()
    2611             : {
    2612           5 :     LOCK(cs_totalBytesSent);
    2613           5 :     return nTotalBytesSent;
    2614             : }
    2615             : 
    2616        1230 : ServiceFlags CConnman::GetLocalServices() const
    2617             : {
    2618        1230 :     return nLocalServices;
    2619             : }
    2620             : 
    2621       38794 : void CConnman::SetBestHeight(int height)
    2622             : {
    2623       38794 :     nBestHeight.store(height, std::memory_order_release);
    2624       38794 : }
    2625             : 
    2626        1456 : int CConnman::GetBestHeight() const
    2627             : {
    2628        1456 :     return nBestHeight.load(std::memory_order_acquire);
    2629             : }
    2630             : 
    2631      378830 : unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
    2632           0 : unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; }
    2633             : 
    2634        1464 : CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const std::string& addrNameIn, bool fInboundIn) :
    2635        1464 :     nTimeConnected(GetSystemTimeInSeconds()),
    2636             :     addr(addrIn),
    2637             :     fInbound(fInboundIn),
    2638             :     nKeyedNetGroup(nKeyedNetGroupIn),
    2639             :     addrKnown(5000, 0.001),
    2640             :     filterInventoryKnown(50000, 0.000001),
    2641             :     id(idIn),
    2642             :     nLocalHostNonce(nLocalHostNonceIn),
    2643             :     nLocalServices(nLocalServicesIn),
    2644             :     nMyStartingHeight(nMyStartingHeightIn),
    2645       10248 :     nSendVersion(0)
    2646             : {
    2647        1464 :     nServices = NODE_NONE;
    2648        1464 :     nServicesExpected = NODE_NONE;
    2649        1464 :     hSocket = hSocketIn;
    2650        1464 :     nRecvVersion = INIT_PROTO_VERSION;
    2651        1464 :     nLastSend = 0;
    2652        1464 :     nLastRecv = 0;
    2653        1464 :     nSendBytes = 0;
    2654        1464 :     nRecvBytes = 0;
    2655        1464 :     nTimeOffset = 0;
    2656        2157 :     addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
    2657        1464 :     nVersion = 0;
    2658        1464 :     strSubVer = "";
    2659        1464 :     fWhitelisted = false;
    2660        1464 :     fOneShot = false;
    2661        1464 :     fAddnode = false;
    2662        1464 :     m_masternode_connection = false;
    2663        1464 :     fClient = false; // set by version message
    2664        1464 :     fFeeler = false;
    2665        1464 :     fSuccessfullyConnected = false;
    2666        1464 :     fDisconnect = false;
    2667        1464 :     nRefCount = 0;
    2668        1464 :     nSendSize = 0;
    2669        1464 :     nSendOffset = 0;
    2670        1464 :     hashContinue = UINT256_ZERO;
    2671        1464 :     nStartingHeight = -1;
    2672        1464 :     filterInventoryKnown.reset();
    2673        1464 :     fSendMempool = false;
    2674        1464 :     fGetAddr = false;
    2675        1464 :     fRelayTxes = false;
    2676        1464 :     pfilter = std::make_unique<CBloomFilter>();
    2677        1464 :     timeLastMempoolReq = 0;
    2678        1464 :     nPingNonceSent = 0;
    2679        1464 :     nPingUsecStart = 0;
    2680        1464 :     nPingUsecTime = 0;
    2681        1464 :     fPingQueued = false;
    2682        1464 :     nMinPingUsecTime = std::numeric_limits<int64_t>::max();
    2683        1464 :     fPauseRecv = false;
    2684        1464 :     fPauseSend = false;
    2685        1464 :     nProcessQueueSize = 0;
    2686             : 
    2687       84912 :     for (const std::string &msg : getAllNetMessageTypes())
    2688       83448 :         mapRecvBytesPerMsgCmd[msg] = 0;
    2689        1464 :     mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0;
    2690             : 
    2691        1464 :     if (fLogIPs)
    2692           0 :         LogPrint(BCLog::NET, "Added connection to %s peer=%d\n", addrName, id);
    2693             :     else
    2694        1464 :         LogPrint(BCLog::NET, "Added connection peer=%d\n", id);
    2695        1464 : }
    2696             : 
    2697       10584 : CNode::~CNode()
    2698             : {
    2699        1464 :     CloseSocket(hSocket);
    2700        1464 : }
    2701             : 
    2702       71263 : void CNode::AskFor(const CInv& inv, int64_t doubleRequestDelay)
    2703             : {
    2704       71263 :     if (mapAskFor.size() > MAPASKFOR_MAX_SZ || setAskFor.size() > SETASKFOR_MAX_SZ)
    2705          12 :         return;
    2706             :     // a peer may not have multiple non-responded queue positions for a single inv item
    2707       71263 :     if (!setAskFor.insert(inv.hash).second)
    2708             :         return;
    2709             : 
    2710             :     // We're using mapAskFor as a priority queue,
    2711             :     // the key is the earliest time the request can be sent
    2712       71251 :     int64_t nRequestTime;
    2713       71251 :     limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv);
    2714       71251 :     if (it != mapAlreadyAskedFor.end())
    2715        5397 :         nRequestTime = it->second;
    2716             :     else
    2717       65854 :         nRequestTime = 0;
    2718      142502 :     LogPrint(BCLog::NET, "askfor %s  %d (%s) peer=%d\n", inv.ToString(), nRequestTime, FormatISO8601Time(nRequestTime / 1000000), id);
    2719             : 
    2720             :     // Make sure not to reuse time indexes to keep things in the same order
    2721       71251 :     int64_t nNow = GetTimeMicros() - 1000000;
    2722       71251 :     static int64_t nLastTime;
    2723       71251 :     ++nLastTime;
    2724       71251 :     nNow = std::max(nNow, nLastTime);
    2725       71251 :     nLastTime = nNow;
    2726             : 
    2727             :     // Each retry is 2 minutes after the last
    2728       71251 :     nRequestTime = std::max(nRequestTime + doubleRequestDelay, nNow);
    2729       71251 :     if (it != mapAlreadyAskedFor.end())
    2730        5397 :         mapAlreadyAskedFor.update(it, nRequestTime);
    2731             :     else
    2732       65854 :         mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
    2733       71251 :     mapAskFor.insert(std::make_pair(nRequestTime, inv));
    2734             : }
    2735             : 
    2736       95644 : void CNode::AskForInvReceived(const uint256& invHash)
    2737             : {
    2738       95644 :     setAskFor.erase(invHash);
    2739       95644 :     for (auto it = mapAskFor.begin(); it != mapAskFor.end();) {
    2740       26673 :         if (it->second.hash == invHash) {
    2741        4989 :             it = mapAskFor.erase(it);
    2742             :         } else {
    2743      144001 :             ++it;
    2744             :         }
    2745             :     }
    2746       95644 : }
    2747             : 
    2748      959341 : bool CConnman::NodeFullyConnected(const CNode* pnode)
    2749             : {
    2750      959341 :     return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
    2751             : }
    2752             : 
    2753      329466 : void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg, bool allowOptimisticSend)
    2754             : {
    2755      329466 :     size_t nMessageSize = msg.data.size();
    2756      329466 :     size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE;
    2757      653124 :     LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n",  SanitizeString(msg.command.c_str()), nMessageSize, pnode->GetId());
    2758             : 
    2759      329466 :     std::vector<unsigned char> serializedHeader;
    2760      329466 :     serializedHeader.reserve(CMessageHeader::HEADER_SIZE);
    2761      329466 :     uint256 hash = Hash(msg.data.data(), msg.data.data() + nMessageSize);
    2762      329466 :     CMessageHeader hdr(Params().MessageStart(), msg.command.c_str(), nMessageSize);
    2763      329466 :     memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
    2764             : 
    2765      329466 :     CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, serializedHeader, 0, hdr};
    2766             : 
    2767      329466 :     size_t nBytesSent = 0;
    2768      329466 :     {
    2769      329466 :         LOCK(pnode->cs_vSend);
    2770      329466 :         bool hasPendingData = !pnode->vSendMsg.empty();
    2771      329466 :         bool optimisticSend(allowOptimisticSend && pnode->vSendMsg.empty());
    2772             : 
    2773             :         //log total amount of bytes per command
    2774      329466 :         pnode->mapSendBytesPerMsgCmd[msg.command] += nTotalSize;
    2775      329466 :         pnode->nSendSize += nTotalSize;
    2776             : 
    2777      329466 :         if (pnode->nSendSize > nSendBufferMaxSize)
    2778           8 :             pnode->fPauseSend = true;
    2779      329466 :         pnode->vSendMsg.push_back(std::move(serializedHeader));
    2780      329466 :         if (nMessageSize)
    2781      324574 :             pnode->vSendMsg.push_back(std::move(msg.data));
    2782             : 
    2783             :         // If write queue empty, attempt "optimistic write"
    2784      329466 :         if (optimisticSend == true)
    2785           0 :             nBytesSent = SocketSendData(pnode);
    2786             :         // wake up select() call in case there was no pending data before (so it was not selecting this socket for sending)
    2787      329466 :         else if (!hasPendingData && wakeupSelectNeeded)
    2788      206411 :             WakeSelect();
    2789             :     }
    2790      329466 :     if (nBytesSent)
    2791           0 :         RecordBytesSent(nBytesSent);
    2792      329466 : }
    2793             : 
    2794           0 : bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
    2795             : {
    2796           0 :     CNode* found = nullptr;
    2797           0 :     LOCK(cs_vNodes);
    2798           0 :     for (auto&& pnode : vNodes) {
    2799           0 :         if(pnode->GetId() == id) {
    2800             :             found = pnode;
    2801             :             break;
    2802             :         }
    2803             :     }
    2804           0 :     return found != nullptr && NodeFullyConnected(found) && func(found);
    2805             : }
    2806             : 
    2807         132 : bool CConnman::ForNode(const CService& addr, const std::function<bool(const CNode* pnode)>& cond, const std::function<bool(CNode* pnode)>& func)
    2808             : {
    2809         132 :     CNode* found = nullptr;
    2810         132 :     LOCK(cs_vNodes);
    2811        1088 :     for (auto&& pnode : vNodes) {
    2812        1088 :         if(static_cast<CService>(pnode->addr) == addr) {
    2813         132 :             found = pnode;
    2814         132 :             break;
    2815             :         }
    2816             :     }
    2817         327 :     return found != nullptr && cond(found) && func(found);
    2818             : }
    2819             : 
    2820          20 : bool CConnman::IsNodeConnected(const CAddress& addr)
    2821             : {
    2822          20 :     return FindNode(addr.ToStringIPPort());
    2823             : }
    2824             : 
    2825          20 : CNode* CConnman::ConnectNode(const CAddress& addrConnect)
    2826             : {
    2827          20 :     return ConnectNode(addrConnect, nullptr, true, true);
    2828             : }
    2829             : 
    2830             : // valid, reachable and routable address (except for RegTest)
    2831          17 : bool validateMasternodeIP(const std::string& addrStr)
    2832             : {
    2833          34 :     CNetAddr resolved;
    2834          17 :     if (LookupHost(addrStr, resolved, false)) {
    2835          12 :         return ((IsReachable(resolved) && resolved.IsRoutable()) ||
    2836           2 :                 (Params().IsRegTestNet() && resolved.IsValid()));
    2837             :     }
    2838             :     return false;
    2839             : }
    2840             : 
    2841       56995 : int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
    2842       56995 :     return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
    2843             : }
    2844             : 
    2845     1528450 : std::vector<CNode*> CConnman::CopyNodeVector(std::function<bool(const CNode* pnode)> cond)
    2846             : {
    2847     1528450 :     std::vector<CNode*> vecNodesCopy;
    2848     1528450 :     LOCK(cs_vNodes);
    2849    12290800 :     for (size_t i = 0; i < vNodes.size(); ++i) {
    2850    10762300 :         CNode* pnode = vNodes[i];
    2851    10762300 :         if (!cond(pnode))
    2852        1162 :             continue;
    2853    10761100 :         pnode->AddRef();
    2854    10761100 :         vecNodesCopy.push_back(pnode);
    2855             :     }
    2856     3056900 :     return vecNodesCopy;
    2857             : }
    2858             : 
    2859     1435050 : std::vector<CNode*> CConnman::CopyNodeVector()
    2860             : {
    2861     2870110 :     return CopyNodeVector(AllNodes);
    2862             : }
    2863             : 
    2864     1528450 : void CConnman::ReleaseNodeVector(const std::vector<CNode*>& vecNodes)
    2865             : {
    2866    12289600 :     for (size_t i = 0; i < vecNodes.size(); ++i) {
    2867    10761100 :         CNode* pnode = vecNodes[i];
    2868    10761100 :         pnode->Release();
    2869             :     }
    2870     1528450 : }
    2871             : 
    2872        2933 : CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id)
    2873             : {
    2874        2933 :     return CSipHasher(nSeed0, nSeed1).Write(id);
    2875             : }
    2876             : 
    2877        1456 : uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad)
    2878             : {
    2879        1456 :     std::vector<unsigned char> vchNetGroup(ad.GetGroup(addrman.m_asmap));
    2880             : 
    2881        2912 :     return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize();
    2882             : }
    2883             : 

Generated by: LCOV version 1.14