LCOV - code coverage report
Current view: top level - src - net.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 799 1159 68.9 %
Date: 2015-10-12 22:39:14 Functions: 75 99 75.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #if defined(HAVE_CONFIG_H)
       7             : #include "config/bitcoin-config.h"
       8             : #endif
       9             : 
      10             : #include "net.h"
      11             : 
      12             : #include "addrman.h"
      13             : #include "chainparams.h"
      14             : #include "clientversion.h"
      15             : #include "crypto/common.h"
      16             : #include "hash.h"
      17             : #include "primitives/transaction.h"
      18             : #include "scheduler.h"
      19             : #include "ui_interface.h"
      20             : #include "utilstrencodings.h"
      21             : 
      22             : #ifdef WIN32
      23             : #include <string.h>
      24             : #else
      25             : #include <fcntl.h>
      26             : #endif
      27             : 
      28             : #ifdef USE_UPNP
      29             : #include <miniupnpc/miniupnpc.h>
      30             : #include <miniupnpc/miniwget.h>
      31             : #include <miniupnpc/upnpcommands.h>
      32             : #include <miniupnpc/upnperrors.h>
      33             : #endif
      34             : 
      35             : #include <boost/filesystem.hpp>
      36             : #include <boost/thread.hpp>
      37             : 
      38             : // Dump addresses to peers.dat every 15 minutes (900s)
      39             : #define DUMP_ADDRESSES_INTERVAL 900
      40             : 
      41             : #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
      42             : #define MSG_NOSIGNAL 0
      43             : #endif
      44             : 
      45             : // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
      46             : // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
      47             : #ifdef WIN32
      48             : #ifndef PROTECTION_LEVEL_UNRESTRICTED
      49             : #define PROTECTION_LEVEL_UNRESTRICTED 10
      50             : #endif
      51             : #ifndef IPV6_PROTECTION_LEVEL
      52             : #define IPV6_PROTECTION_LEVEL 23
      53             : #endif
      54             : #endif
      55             : 
      56             : using namespace std;
      57             : 
      58             : namespace {
      59             :     const int MAX_OUTBOUND_CONNECTIONS = 8;
      60             : 
      61             :     struct ListenSocket {
      62             :         SOCKET socket;
      63             :         bool whitelisted;
      64             : 
      65         182 :         ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {}
      66             :     };
      67             : }
      68             : 
      69             : //
      70             : // Global state variables
      71             : //
      72             : bool fDiscover = true;
      73             : bool fListen = true;
      74             : uint64_t nLocalServices = NODE_NETWORK;
      75          96 : CCriticalSection cs_mapLocalHost;
      76          96 : map<CNetAddr, LocalServiceInfo> mapLocalHost;
      77             : static bool vfReachable[NET_MAX] = {};
      78             : static bool vfLimited[NET_MAX] = {};
      79             : static CNode* pnodeLocalHost = NULL;
      80             : uint64_t nLocalHostNonce = 0;
      81          96 : static std::vector<ListenSocket> vhListenSocket;
      82          96 : CAddrMan addrman;
      83             : int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
      84             : bool fAddressesInitialized = false;
      85          96 : std::string strSubVersion;
      86             : 
      87             : vector<CNode*> vNodes;
      88          96 : CCriticalSection cs_vNodes;
      89          96 : map<CInv, CDataStream> mapRelay;
      90          96 : deque<pair<int64_t, CInv> > vRelayExpiration;
      91          96 : CCriticalSection cs_mapRelay;
      92          96 : limitedmap<CInv, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
      93             : 
      94          96 : static deque<string> vOneShots;
      95          96 : CCriticalSection cs_vOneShots;
      96             : 
      97          96 : set<CNetAddr> setservAddNodeAddresses;
      98          96 : CCriticalSection cs_setservAddNodeAddresses;
      99             : 
     100          96 : vector<std::string> vAddedNodes;
     101          96 : CCriticalSection cs_vAddedNodes;
     102             : 
     103             : NodeId nLastNodeId = 0;
     104          96 : CCriticalSection cs_nLastNodeId;
     105             : 
     106             : static CSemaphore *semOutbound = NULL;
     107          96 : boost::condition_variable messageHandlerCondition;
     108             : 
     109             : // Signals for message handling
     110          96 : static CNodeSignals g_signals;
     111         238 : CNodeSignals& GetNodeSignals() { return g_signals; }
     112             : 
     113           0 : void AddOneShot(const std::string& strDest)
     114             : {
     115           0 :     LOCK(cs_vOneShots);
     116           0 :     vOneShots.push_back(strDest);
     117           0 : }
     118             : 
     119         630 : unsigned short GetListenPort()
     120             : {
     121        1260 :     return (unsigned short)(GetArg("-port", Params().GetDefaultPort()));
     122             : }
     123             : 
     124             : // find 'best' local address for a particular peer
     125         446 : bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
     126             : {
     127         446 :     if (!fListen)
     128             :         return false;
     129             : 
     130         443 :     int nBestScore = -1;
     131         443 :     int nBestReachability = -1;
     132             :     {
     133         443 :         LOCK(cs_mapLocalHost);
     134         886 :         for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
     135             :         {
     136           0 :             int nScore = (*it).second.nScore;
     137           0 :             int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
     138           0 :             if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
     139             :             {
     140           0 :                 addr = CService((*it).first, (*it).second.nPort);
     141           0 :                 nBestReachability = nReachability;
     142           0 :                 nBestScore = nScore;
     143             :             }
     144             :         }
     145             :     }
     146         443 :     return nBestScore >= 0;
     147             : }
     148             : 
     149             : //! Convert the pnSeeds6 array into usable address objects.
     150           1 : static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn)
     151             : {
     152             :     // It'll only connect to one or two seed nodes because once it connects,
     153             :     // it'll get a pile of addresses with newer timestamps.
     154             :     // Seed nodes are given a random 'last seen time' of between one and two
     155             :     // weeks ago.
     156           1 :     const int64_t nOneWeek = 7*24*60*60;
     157             :     std::vector<CAddress> vSeedsOut;
     158           2 :     vSeedsOut.reserve(vSeedsIn.size());
     159           5 :     for (std::vector<SeedSpec6>::const_iterator i(vSeedsIn.begin()); i != vSeedsIn.end(); ++i)
     160             :     {
     161             :         struct in6_addr ip;
     162           0 :         memcpy(&ip, i->addr, sizeof(ip));
     163           0 :         CAddress addr(CService(ip, i->port));
     164           0 :         addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
     165           0 :         vSeedsOut.push_back(addr);
     166             :     }
     167           1 :     return vSeedsOut;
     168             : }
     169             : 
     170             : // get best local address for a particular peer as a CAddress
     171             : // Otherwise, return the unroutable 0.0.0.0 but filled in with
     172             : // the normal parameters, since the IP may be changed to a useful
     173             : // one by discovery.
     174         446 : CAddress GetLocalAddress(const CNetAddr *paddrPeer)
     175             : {
     176         446 :     CAddress ret(CService("0.0.0.0",GetListenPort()),0);
     177         446 :     CService addr;
     178         446 :     if (GetLocal(addr, paddrPeer))
     179             :     {
     180           0 :         ret = CAddress(addr);
     181             :     }
     182         446 :     ret.nServices = nLocalServices;
     183         446 :     ret.nTime = GetAdjustedTime();
     184         446 :     return ret;
     185             : }
     186             : 
     187           0 : int GetnScore(const CService& addr)
     188             : {
     189           0 :     LOCK(cs_mapLocalHost);
     190           0 :     if (mapLocalHost.count(addr) == LOCAL_NONE)
     191             :         return 0;
     192           0 :     return mapLocalHost[addr].nScore;
     193             : }
     194             : 
     195             : // Is our peer's addrLocal potentially useful as an external IP source?
     196         181 : bool IsPeerAddrLocalGood(CNode *pnode)
     197             : {
     198         181 :     return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
     199         181 :            !IsLimited(pnode->addrLocal.GetNetwork());
     200             : }
     201             : 
     202             : // pushes our own address to a peer
     203         157 : void AdvertizeLocal(CNode *pnode)
     204             : {
     205         157 :     if (fListen && pnode->fSuccessfullyConnected)
     206             :     {
     207         149 :         CAddress addrLocal = GetLocalAddress(&pnode->addr);
     208             :         // If discovery is enabled, sometimes give our peer the address it
     209             :         // tells us that it sees us as in case it has a better idea of our
     210             :         // address than we do.
     211         149 :         if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
     212           0 :              GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
     213             :         {
     214           0 :             addrLocal.SetIP(pnode->addrLocal);
     215             :         }
     216         149 :         if (addrLocal.IsRoutable())
     217             :         {
     218           0 :             pnode->PushAddress(addrLocal);
     219             :         }
     220             :     }
     221         157 : }
     222             : 
     223           6 : void SetReachable(enum Network net, bool fFlag)
     224             : {
     225           6 :     LOCK(cs_mapLocalHost);
     226           6 :     vfReachable[net] = fFlag;
     227           6 :     if (net == NET_IPV6 && fFlag)
     228           0 :         vfReachable[NET_IPV4] = true;
     229           6 : }
     230             : 
     231             : // learn a new local address
     232           2 : bool AddLocal(const CService& addr, int nScore)
     233             : {
     234           2 :     if (!addr.IsRoutable())
     235             :         return false;
     236             : 
     237           0 :     if (!fDiscover && nScore < LOCAL_MANUAL)
     238             :         return false;
     239             : 
     240           0 :     if (IsLimited(addr))
     241             :         return false;
     242             : 
     243           0 :     LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
     244             : 
     245             :     {
     246           0 :         LOCK(cs_mapLocalHost);
     247           0 :         bool fAlready = mapLocalHost.count(addr) > 0;
     248           0 :         LocalServiceInfo &info = mapLocalHost[addr];
     249           0 :         if (!fAlready || nScore >= info.nScore) {
     250           0 :             info.nScore = nScore + (fAlready ? 1 : 0);
     251           0 :             info.nPort = addr.GetPort();
     252             :         }
     253           0 :         SetReachable(addr.GetNetwork());
     254             :     }
     255             : 
     256           0 :     return true;
     257             : }
     258             : 
     259           2 : bool AddLocal(const CNetAddr &addr, int nScore)
     260             : {
     261           2 :     return AddLocal(CService(addr, GetListenPort()), nScore);
     262             : }
     263             : 
     264             : /** Make a particular network entirely off-limits (no automatic connects to it) */
     265           0 : void SetLimited(enum Network net, bool fLimited)
     266             : {
     267           0 :     if (net == NET_UNROUTABLE)
     268           0 :         return;
     269           0 :     LOCK(cs_mapLocalHost);
     270           0 :     vfLimited[net] = fLimited;
     271             : }
     272             : 
     273         194 : bool IsLimited(enum Network net)
     274             : {
     275         194 :     LOCK(cs_mapLocalHost);
     276         388 :     return vfLimited[net];
     277             : }
     278             : 
     279         182 : bool IsLimited(const CNetAddr &addr)
     280             : {
     281         182 :     return IsLimited(addr.GetNetwork());
     282             : }
     283             : 
     284             : /** vote for a local address */
     285           0 : bool SeenLocal(const CService& addr)
     286             : {
     287             :     {
     288           0 :         LOCK(cs_mapLocalHost);
     289           0 :         if (mapLocalHost.count(addr) == 0)
     290           0 :             return false;
     291           0 :         mapLocalHost[addr].nScore++;
     292             :     }
     293           0 :     return true;
     294             : }
     295             : 
     296             : 
     297             : /** check whether a given address is potentially local */
     298           0 : bool IsLocal(const CService& addr)
     299             : {
     300           0 :     LOCK(cs_mapLocalHost);
     301           0 :     return mapLocalHost.count(addr) > 0;
     302             : }
     303             : 
     304             : /** check whether a given network is one we can probably connect to */
     305          12 : bool IsReachable(enum Network net)
     306             : {
     307          12 :     LOCK(cs_mapLocalHost);
     308          24 :     return vfReachable[net] && !vfLimited[net];
     309             : }
     310             : 
     311             : /** check whether a given address is in a network we can probably connect to */
     312           0 : bool IsReachable(const CNetAddr& addr)
     313             : {
     314           0 :     enum Network net = addr.GetNetwork();
     315           0 :     return IsReachable(net);
     316             : }
     317             : 
     318           9 : void AddressCurrentlyConnected(const CService& addr)
     319             : {
     320           9 :     addrman.Connected(addr);
     321           9 : }
     322             : 
     323             : 
     324             : uint64_t CNode::nTotalBytesRecv = 0;
     325             : uint64_t CNode::nTotalBytesSent = 0;
     326          96 : CCriticalSection CNode::cs_totalBytesRecv;
     327          96 : CCriticalSection CNode::cs_totalBytesSent;
     328             : 
     329     3031205 : CNode* FindNode(const CNetAddr& ip)
     330             : {
     331     3031205 :     LOCK(cs_vNodes);
     332    27280833 :     BOOST_FOREACH(CNode* pnode, vNodes)
     333     3031201 :         if ((CNetAddr)pnode->addr == ip)
     334     3031201 :             return (pnode);
     335           4 :     return NULL;
     336             : }
     337             : 
     338           9 : CNode* FindNode(const CSubNet& subNet)
     339             : {
     340           9 :     LOCK(cs_vNodes);
     341          54 :     BOOST_FOREACH(CNode* pnode, vNodes)
     342           0 :     if (subNet.Match((CNetAddr)pnode->addr))
     343           0 :         return (pnode);
     344           9 :     return NULL;
     345             : }
     346             : 
     347         169 : CNode* FindNode(const std::string& addrName)
     348             : {
     349         169 :     LOCK(cs_vNodes);
     350        2388 :     BOOST_FOREACH(CNode* pnode, vNodes)
     351         240 :         if (pnode->addrName == addrName)
     352          22 :             return (pnode);
     353         147 :     return NULL;
     354             : }
     355             : 
     356           0 : CNode* FindNode(const CService& addr)
     357             : {
     358           0 :     LOCK(cs_vNodes);
     359           0 :     BOOST_FOREACH(CNode* pnode, vNodes)
     360           0 :         if ((CService)pnode->addr == addr)
     361           0 :             return (pnode);
     362           0 :     return NULL;
     363             : }
     364             : 
     365         147 : CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
     366             : {
     367         147 :     if (pszDest == NULL) {
     368           0 :         if (IsLocal(addrConnect))
     369             :             return NULL;
     370             : 
     371             :         // Look for an existing connection
     372           0 :         CNode* pnode = FindNode((CService)addrConnect);
     373           0 :         if (pnode)
     374             :         {
     375             :             pnode->AddRef();
     376           0 :             return pnode;
     377             :         }
     378             :     }
     379             : 
     380             :     /// debug print
     381             :     LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
     382             :         pszDest ? pszDest : addrConnect.ToString(),
     383         441 :         pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
     384             : 
     385             :     // Connect
     386             :     SOCKET hSocket;
     387         147 :     bool proxyConnectionFailed = false;
     388         147 :     if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) :
     389           0 :                   ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed))
     390             :     {
     391         139 :         if (!IsSelectableSocket(hSocket)) {
     392           0 :             LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
     393           0 :             CloseSocket(hSocket);
     394             :             return NULL;
     395             :         }
     396             : 
     397         139 :         addrman.Attempt(addrConnect);
     398             : 
     399             :         // Add node
     400         417 :         CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
     401         139 :         pnode->AddRef();
     402             : 
     403             :         {
     404         139 :             LOCK(cs_vNodes);
     405         139 :             vNodes.push_back(pnode);
     406             :         }
     407             : 
     408         139 :         pnode->nTimeConnected = GetTime();
     409             : 
     410         139 :         return pnode;
     411           8 :     } else if (!proxyConnectionFailed) {
     412             :         // If connecting to the node failed, and failure is not caused by a problem connecting to
     413             :         // the proxy, mark this as an attempt.
     414           8 :         addrman.Attempt(addrConnect);
     415             :     }
     416             : 
     417             :     return NULL;
     418             : }
     419             : 
     420          77 : void CNode::CloseSocketDisconnect()
     421             : {
     422          77 :     fDisconnect = true;
     423          77 :     if (hSocket != INVALID_SOCKET)
     424             :     {
     425          39 :         LogPrint("net", "disconnecting peer=%d\n", id);
     426          39 :         CloseSocket(hSocket);
     427             :     }
     428             : 
     429             :     // in case this fails, we'll empty the recv buffer when the CNode is deleted
     430          77 :     TRY_LOCK(cs_vRecvMsg, lockRecv);
     431          77 :     if (lockRecv)
     432          77 :         vRecvMsg.clear();
     433          77 : }
     434             : 
     435         265 : void CNode::PushVersion()
     436             : {
     437         530 :     int nBestHeight = g_signals.GetHeight().get_value_or(0);
     438             : 
     439         265 :     int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
     440         265 :     CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
     441         265 :     CAddress addrMe = GetLocalAddress(&addr);
     442         265 :     GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
     443         265 :     if (fLogIPs)
     444           0 :         LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id);
     445             :     else
     446         530 :         LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
     447             :     PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
     448         265 :                 nLocalHostNonce, strSubVersion, nBestHeight, true);
     449         265 : }
     450             : 
     451             : 
     452             : 
     453             : 
     454             : 
     455          96 : banmap_t CNode::setBanned;
     456          96 : CCriticalSection CNode::cs_setBanned;
     457             : bool CNode::setBannedIsDirty;
     458             : 
     459          10 : void CNode::ClearBanned()
     460             : {
     461          10 :     LOCK(cs_setBanned);
     462             :     setBanned.clear();
     463          10 :     setBannedIsDirty = true;
     464          10 : }
     465             : 
     466         144 : bool CNode::IsBanned(CNetAddr ip)
     467             : {
     468         144 :     bool fResult = false;
     469             :     {
     470         144 :         LOCK(cs_setBanned);
     471         318 :         for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
     472             :         {
     473          15 :             CSubNet subNet = (*it).first;
     474          15 :             CBanEntry banEntry = (*it).second;
     475             : 
     476          15 :             if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil)
     477           9 :                 fResult = true;
     478             :         }
     479             :     }
     480         144 :     return fResult;
     481             : }
     482             : 
     483           9 : bool CNode::IsBanned(CSubNet subnet)
     484             : {
     485           9 :     bool fResult = false;
     486             :     {
     487           9 :         LOCK(cs_setBanned);
     488           9 :         banmap_t::iterator i = setBanned.find(subnet);
     489           9 :         if (i != setBanned.end())
     490             :         {
     491           0 :             CBanEntry banEntry = (*i).second;
     492           0 :             if (GetTime() < banEntry.nBanUntil)
     493           0 :                 fResult = true;
     494             :         }
     495             :     }
     496           9 :     return fResult;
     497             : }
     498             : 
     499           8 : void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
     500           8 :     CSubNet subNet(addr);
     501           8 :     Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
     502           8 : }
     503             : 
     504          17 : void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
     505          17 :     CBanEntry banEntry(GetTime());
     506          17 :     banEntry.banReason = banReason;
     507          17 :     if (bantimeoffset <= 0)
     508             :     {
     509          39 :         bantimeoffset = GetArg("-bantime", 60*60*24); // Default 24-hour ban
     510          13 :         sinceUnixEpoch = false;
     511             :     }
     512          17 :     banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
     513             : 
     514             : 
     515          17 :     LOCK(cs_setBanned);
     516          17 :     if (setBanned[subNet].nBanUntil < banEntry.nBanUntil)
     517          17 :         setBanned[subNet] = banEntry;
     518             : 
     519          17 :     setBannedIsDirty = true;
     520          17 : }
     521             : 
     522           2 : bool CNode::Unban(const CNetAddr &addr) {
     523           2 :     CSubNet subNet(addr);
     524           2 :     return Unban(subNet);
     525             : }
     526             : 
     527           4 : bool CNode::Unban(const CSubNet &subNet) {
     528           4 :     LOCK(cs_setBanned);
     529           4 :     if (setBanned.erase(subNet))
     530             :     {
     531           3 :         setBannedIsDirty = true;
     532           3 :         return true;
     533             :     }
     534             :     return false;
     535             : }
     536             : 
     537          42 : void CNode::GetBanned(banmap_t &banMap)
     538             : {
     539          42 :     LOCK(cs_setBanned);
     540             :     banMap = setBanned; //create a thread safe copy
     541          42 : }
     542             : 
     543          94 : void CNode::SetBanned(const banmap_t &banMap)
     544             : {
     545          94 :     LOCK(cs_setBanned);
     546             :     setBanned = banMap;
     547          94 :     setBannedIsDirty = true;
     548          94 : }
     549             : 
     550         118 : void CNode::SweepBanned()
     551             : {
     552         118 :     int64_t now = GetTime();
     553             : 
     554         118 :     LOCK(cs_setBanned);
     555         118 :     banmap_t::iterator it = setBanned.begin();
     556         144 :     while(it != setBanned.end())
     557             :     {
     558          26 :         CBanEntry banEntry = (*it).second;
     559          26 :         if(now > banEntry.nBanUntil)
     560             :         {
     561           1 :             setBanned.erase(it++);
     562           1 :             setBannedIsDirty = true;
     563             :         }
     564             :         else
     565             :             ++it;
     566             :     }
     567         118 : }
     568             : 
     569          94 : bool CNode::BannedSetIsDirty()
     570             : {
     571          94 :     LOCK(cs_setBanned);
     572         188 :     return setBannedIsDirty;
     573             : }
     574             : 
     575          95 : void CNode::SetBannedSetDirty(bool dirty)
     576             : {
     577          95 :     LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag
     578          95 :     setBannedIsDirty = dirty;
     579          95 : }
     580             : 
     581             : 
     582          96 : std::vector<CSubNet> CNode::vWhitelistedRange;
     583          96 : CCriticalSection CNode::cs_vWhitelistedRange;
     584             : 
     585         126 : bool CNode::IsWhitelistedRange(const CNetAddr &addr) {
     586         126 :     LOCK(cs_vWhitelistedRange);
     587         762 :     BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) {
     588           2 :         if (subnet.Match(addr))
     589             :             return true;
     590             :     }
     591         124 :     return false;
     592             : }
     593             : 
     594           2 : void CNode::AddWhitelistedRange(const CSubNet &subnet) {
     595           2 :     LOCK(cs_vWhitelistedRange);
     596           2 :     vWhitelistedRange.push_back(subnet);
     597           2 : }
     598             : 
     599             : #undef X
     600             : #define X(name) stats.name = name
     601         538 : void CNode::copyStats(CNodeStats &stats)
     602             : {
     603         538 :     stats.nodeid = this->GetId();
     604         538 :     X(nServices);
     605         538 :     X(nLastSend);
     606         538 :     X(nLastRecv);
     607         538 :     X(nTimeConnected);
     608         538 :     X(nTimeOffset);
     609         538 :     X(addrName);
     610         538 :     X(nVersion);
     611         538 :     X(cleanSubVer);
     612         538 :     X(fInbound);
     613         538 :     X(nStartingHeight);
     614         538 :     X(nSendBytes);
     615         538 :     X(nRecvBytes);
     616         538 :     X(fWhitelisted);
     617             : 
     618             :     // It is common for nodes with good ping times to suddenly become lagged,
     619             :     // due to a new block arriving or other large transfer.
     620             :     // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
     621             :     // since pingtime does not update until the ping is complete, which might take a while.
     622             :     // So, if a ping is taking an unusually long time in flight,
     623             :     // the caller can immediately detect that this is happening.
     624         538 :     int64_t nPingUsecWait = 0;
     625         538 :     if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
     626          11 :         nPingUsecWait = GetTimeMicros() - nPingUsecStart;
     627             :     }
     628             : 
     629             :     // Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
     630         538 :     stats.dPingTime = (((double)nPingUsecTime) / 1e6);
     631         538 :     stats.dPingMin  = (((double)nMinPingUsecTime) / 1e6);
     632         538 :     stats.dPingWait = (((double)nPingUsecWait) / 1e6);
     633             : 
     634             :     // Leave string empty if addrLocal invalid (not filled in yet)
     635        1614 :     stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : "";
     636         538 : }
     637             : #undef X
     638             : 
     639             : // requires LOCK(cs_vRecvMsg)
     640        8599 : bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
     641             : {
     642       59551 :     while (nBytes > 0) {
     643             : 
     644             :         // get current incomplete message, or create a new one
     645      120673 :         if (vRecvMsg.empty() ||
     646       71934 :             vRecvMsg.back().complete())
     647       42412 :             vRecvMsg.push_back(CNetMessage(Params().MessageStart(), SER_NETWORK, nRecvVersion));
     648             : 
     649       84706 :         CNetMessage& msg = vRecvMsg.back();
     650             : 
     651             :         // absorb network data
     652             :         int handled;
     653       42353 :         if (!msg.in_data)
     654       21206 :             handled = msg.readHeader(pch, nBytes);
     655             :         else
     656       21147 :             handled = msg.readData(pch, nBytes);
     657             : 
     658       42353 :         if (handled < 0)
     659             :                 return false;
     660             : 
     661       42353 :         if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
     662           0 :             LogPrint("net", "Oversized message from peer=%i, disconnecting\n", GetId());
     663           0 :             return false;
     664             :         }
     665             : 
     666       42353 :         pch += handled;
     667       42353 :         nBytes -= handled;
     668             : 
     669       42353 :         if (msg.complete()) {
     670       21206 :             msg.nTime = GetTimeMicros();
     671       21206 :             messageHandlerCondition.notify_one();
     672             :         }
     673             :     }
     674             : 
     675             :     return true;
     676             : }
     677             : 
     678       21206 : int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
     679             : {
     680             :     // copy data to temporary parsing buffer
     681       21206 :     unsigned int nRemaining = 24 - nHdrPos;
     682       21206 :     unsigned int nCopy = std::min(nRemaining, nBytes);
     683             : 
     684       42412 :     memcpy(&hdrbuf[nHdrPos], pch, nCopy);
     685       21206 :     nHdrPos += nCopy;
     686             : 
     687             :     // if header incomplete, exit
     688       21206 :     if (nHdrPos < 24)
     689           0 :         return nCopy;
     690             : 
     691             :     // deserialize to CMessageHeader
     692             :     try {
     693       21206 :         hdrbuf >> hdr;
     694             :     }
     695           0 :     catch (const std::exception&) {
     696             :         return -1;
     697             :     }
     698             : 
     699             :     // reject messages larger than MAX_SIZE
     700       21206 :     if (hdr.nMessageSize > MAX_SIZE)
     701             :             return -1;
     702             : 
     703             :     // switch state to reading message data
     704       21206 :     in_data = true;
     705             : 
     706       21206 :     return nCopy;
     707             : }
     708             : 
     709       21147 : int CNetMessage::readData(const char *pch, unsigned int nBytes)
     710             : {
     711       21147 :     unsigned int nRemaining = hdr.nMessageSize - nDataPos;
     712       21147 :     unsigned int nCopy = std::min(nRemaining, nBytes);
     713             : 
     714       42294 :     if (vRecv.size() < nDataPos + nCopy) {
     715             :         // Allocate up to 256 KiB ahead, but never more than the total message size.
     716       62586 :         vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
     717             :     }
     718             : 
     719       42294 :     memcpy(&vRecv[nDataPos], pch, nCopy);
     720       21147 :     nDataPos += nCopy;
     721             : 
     722       21147 :     return nCopy;
     723             : }
     724             : 
     725             : 
     726             : 
     727             : 
     728             : 
     729             : 
     730             : 
     731             : 
     732             : 
     733             : // requires LOCK(cs_vSend)
     734       20971 : void SocketSendData(CNode *pnode)
     735             : {
     736       20971 :     std::deque<CSerializeData>::iterator it = pnode->vSendMsg.begin();
     737             : 
     738       83876 :     while (it != pnode->vSendMsg.end()) {
     739       20971 :         const CSerializeData &data = *it;
     740       20971 :         assert(data.size() > pnode->nSendOffset);
     741       41942 :         int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
     742       20971 :         if (nBytes > 0) {
     743       20967 :             pnode->nLastSend = GetTime();
     744       20967 :             pnode->nSendBytes += nBytes;
     745       20967 :             pnode->nSendOffset += nBytes;
     746       20967 :             pnode->RecordBytesSent(nBytes);
     747       41934 :             if (pnode->nSendOffset == data.size()) {
     748       20967 :                 pnode->nSendOffset = 0;
     749       20967 :                 pnode->nSendSize -= data.size();
     750       20967 :                 it++;
     751             :             } else {
     752             :                 // could not send full message; stop sending more
     753             :                 break;
     754             :             }
     755             :         } else {
     756           4 :             if (nBytes < 0) {
     757             :                 // error
     758           4 :                 int nErr = WSAGetLastError();
     759           4 :                 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
     760             :                 {
     761           8 :                     LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
     762           4 :                     pnode->CloseSocketDisconnect();
     763             :                 }
     764             :             }
     765             :             // couldn't send anything at all
     766             :             break;
     767             :         }
     768             :     }
     769             : 
     770       41942 :     if (it == pnode->vSendMsg.end()) {
     771       20967 :         assert(pnode->nSendOffset == 0);
     772       20967 :         assert(pnode->nSendSize == 0);
     773             :     }
     774       41942 :     pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
     775       20971 : }
     776             : 
     777          96 : static list<CNode*> vNodesDisconnected;
     778             : 
     779             : class CNodeRef {
     780             : public:
     781           0 :     CNodeRef(CNode *pnode) : _pnode(pnode) {
     782           0 :         LOCK(cs_vNodes);
     783           0 :         _pnode->AddRef();
     784           0 :     }
     785             : 
     786           0 :     ~CNodeRef() {
     787           0 :         LOCK(cs_vNodes);
     788           0 :         _pnode->Release();
     789           0 :     }
     790             : 
     791             :     CNode& operator *() const {return *_pnode;};
     792           0 :     CNode* operator ->() const {return _pnode;};
     793             : 
     794           0 :     CNodeRef& operator =(const CNodeRef& other)
     795             :     {
     796           0 :         if (this != &other) {
     797           0 :             LOCK(cs_vNodes);
     798             : 
     799           0 :             _pnode->Release();
     800           0 :             _pnode = other._pnode;
     801           0 :             _pnode->AddRef();
     802             :         }
     803           0 :         return *this;
     804             :     }
     805             : 
     806           0 :     CNodeRef(const CNodeRef& other):
     807           0 :         _pnode(other._pnode)
     808             :     {
     809           0 :         LOCK(cs_vNodes);
     810           0 :         _pnode->AddRef();
     811           0 :     }
     812             : private:
     813             :     CNode *_pnode;
     814             : };
     815             : 
     816           0 : static bool ReverseCompareNodeMinPingTime(const CNodeRef &a, const CNodeRef &b)
     817             : {
     818           0 :     return a->nMinPingUsecTime > b->nMinPingUsecTime;
     819             : }
     820             : 
     821           0 : static bool ReverseCompareNodeTimeConnected(const CNodeRef &a, const CNodeRef &b)
     822             : {
     823           0 :     return a->nTimeConnected > b->nTimeConnected;
     824             : }
     825             : 
     826           0 : class CompareNetGroupKeyed
     827             : {
     828             :     std::vector<unsigned char> vchSecretKey;
     829             : public:
     830           0 :     CompareNetGroupKeyed()
     831           0 :     {
     832           0 :         vchSecretKey.resize(32, 0);
     833           0 :         GetRandBytes(vchSecretKey.data(), vchSecretKey.size());
     834           0 :     }
     835             : 
     836           0 :     bool operator()(const CNodeRef &a, const CNodeRef &b)
     837             :     {
     838             :         std::vector<unsigned char> vchGroupA, vchGroupB;
     839           0 :         CSHA256 hashA, hashB;
     840           0 :         std::vector<unsigned char> vchA(32), vchB(32);
     841             : 
     842           0 :         vchGroupA = a->addr.GetGroup();
     843           0 :         vchGroupB = b->addr.GetGroup();
     844             : 
     845           0 :         hashA.Write(begin_ptr(vchGroupA), vchGroupA.size());
     846           0 :         hashB.Write(begin_ptr(vchGroupB), vchGroupB.size());
     847             : 
     848           0 :         hashA.Write(begin_ptr(vchSecretKey), vchSecretKey.size());
     849           0 :         hashB.Write(begin_ptr(vchSecretKey), vchSecretKey.size());
     850             : 
     851           0 :         hashA.Finalize(begin_ptr(vchA));
     852           0 :         hashB.Finalize(begin_ptr(vchB));
     853             : 
     854           0 :         return vchA < vchB;
     855             :     }
     856             : };
     857             : 
     858           0 : static bool AttemptToEvictConnection(bool fPreferNewConnection) {
     859             :     std::vector<CNodeRef> vEvictionCandidates;
     860             :     {
     861           0 :         LOCK(cs_vNodes);
     862             : 
     863           0 :         BOOST_FOREACH(CNode *node, vNodes) {
     864           0 :             if (node->fWhitelisted)
     865             :                 continue;
     866           0 :             if (!node->fInbound)
     867             :                 continue;
     868           0 :             if (node->fDisconnect)
     869             :                 continue;
     870           0 :             if (node->addr.IsLocal())
     871             :                 continue;
     872           0 :             vEvictionCandidates.push_back(CNodeRef(node));
     873             :         }
     874             :     }
     875             : 
     876           0 :     if (vEvictionCandidates.empty()) return false;
     877             : 
     878             :     // Protect connections with certain characteristics
     879             : 
     880             :     // Deterministically select 4 peers to protect by netgroup.
     881             :     // An attacker cannot predict which netgroups will be protected.
     882           0 :     static CompareNetGroupKeyed comparerNetGroupKeyed;
     883           0 :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), comparerNetGroupKeyed);
     884           0 :     vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
     885             : 
     886           0 :     if (vEvictionCandidates.empty()) return false;
     887             : 
     888             :     // Protect the 8 nodes with the best ping times.
     889             :     // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
     890             :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime);
     891           0 :     vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
     892             : 
     893           0 :     if (vEvictionCandidates.empty()) return false;
     894             : 
     895             :     // Protect the half of the remaining nodes which have been connected the longest.
     896             :     // This replicates the existing implicit behavior.
     897             :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
     898           0 :     vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast<int>(vEvictionCandidates.size() / 2), vEvictionCandidates.end());
     899             : 
     900           0 :     if (vEvictionCandidates.empty()) return false;
     901             : 
     902             :     // Identify the network group with the most connections
     903             :     std::vector<unsigned char> naMostConnections;
     904           0 :     unsigned int nMostConnections = 0;
     905             :     std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
     906           0 :     BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
     907           0 :         mapAddrCounts[node->addr.GetGroup()].push_back(node);
     908             : 
     909           0 :         if (mapAddrCounts[node->addr.GetGroup()].size() > nMostConnections) {
     910           0 :             nMostConnections = mapAddrCounts[node->addr.GetGroup()].size();
     911           0 :             naMostConnections = node->addr.GetGroup();
     912             :         }
     913             :     }
     914             : 
     915             :     // Reduce to the network group with the most connections
     916           0 :     vEvictionCandidates = mapAddrCounts[naMostConnections];
     917             : 
     918             :     // Do not disconnect peers if there is only 1 connection from their network group
     919           0 :     if (vEvictionCandidates.size() <= 1)
     920             :         // unless we prefer the new connection (for whitelisted peers)
     921           0 :         if (!fPreferNewConnection)
     922             :             return false;
     923             : 
     924             :     // Disconnect the most recent connection from the network group with the most connections
     925             :     std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
     926           0 :     vEvictionCandidates[0]->fDisconnect = true;
     927             : 
     928           0 :     return true;
     929             : }
     930             : 
     931         126 : static void AcceptConnection(const ListenSocket& hListenSocket) {
     932             :     struct sockaddr_storage sockaddr;
     933         126 :     socklen_t len = sizeof(sockaddr);
     934         126 :     SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
     935         126 :     CAddress addr;
     936         126 :     int nInbound = 0;
     937         126 :     int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS;
     938             : 
     939         126 :     if (hSocket != INVALID_SOCKET)
     940         126 :         if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
     941           0 :             LogPrintf("Warning: Unknown socket family\n");
     942             : 
     943         126 :     bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
     944             :     {
     945         126 :         LOCK(cs_vNodes);
     946        1686 :         BOOST_FOREACH(CNode* pnode, vNodes)
     947         155 :             if (pnode->fInbound)
     948          56 :                 nInbound++;
     949             :     }
     950             : 
     951         126 :     if (hSocket == INVALID_SOCKET)
     952             :     {
     953           0 :         int nErr = WSAGetLastError();
     954           0 :         if (nErr != WSAEWOULDBLOCK)
     955           0 :             LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
     956           0 :         return;
     957             :     }
     958             : 
     959         126 :     if (!IsSelectableSocket(hSocket))
     960             :     {
     961           0 :         LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString());
     962           0 :         CloseSocket(hSocket);
     963             :         return;
     964             :     }
     965             : 
     966         126 :     if (CNode::IsBanned(addr) && !whitelisted)
     967             :     {
     968           0 :         LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
     969           0 :         CloseSocket(hSocket);
     970             :         return;
     971             :     }
     972             : 
     973         126 :     if (nInbound >= nMaxInbound)
     974             :     {
     975           0 :         if (!AttemptToEvictConnection(whitelisted)) {
     976             :             // No connection to evict, disconnect the new connection
     977           0 :             LogPrint("net", "failed to find an eviction candidate - connection dropped (full)\n");
     978           0 :             CloseSocket(hSocket);
     979             :             return;
     980             :         }
     981             :     }
     982             : 
     983         378 :     CNode* pnode = new CNode(hSocket, addr, "", true);
     984         126 :     pnode->AddRef();
     985         126 :     pnode->fWhitelisted = whitelisted;
     986             : 
     987         252 :     LogPrint("net", "connection from %s accepted\n", addr.ToString());
     988             : 
     989             :     {
     990         126 :         LOCK(cs_vNodes);
     991         126 :         vNodes.push_back(pnode);
     992             :     }
     993             : }
     994             : 
     995          94 : void ThreadSocketHandler()
     996             : {
     997          94 :     unsigned int nPrevNodeCount = 0;
     998             :     while (true)
     999             :     {
    1000             :         //
    1001             :         // Disconnect nodes
    1002             :         //
    1003             :         {
    1004       25977 :             LOCK(cs_vNodes);
    1005             :             // Disconnect unused nodes
    1006       25977 :             vector<CNode*> vNodesCopy = vNodes;
    1007      511692 :             BOOST_FOREACH(CNode* pnode, vNodesCopy)
    1008             :             {
    1009      177876 :                 if (pnode->fDisconnect ||
    1010       59266 :                     (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
    1011             :                 {
    1012             :                     // remove from vNodes
    1013             :                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
    1014             : 
    1015             :                     // release outbound grant (if any)
    1016          39 :                     pnode->grantOutbound.Release();
    1017             : 
    1018             :                     // close socket and cleanup
    1019          39 :                     pnode->CloseSocketDisconnect();
    1020             : 
    1021             :                     // hold in disconnected pool until all refs are released
    1022          39 :                     if (pnode->fNetworkNode || pnode->fInbound)
    1023          39 :                         pnode->Release();
    1024             :                     vNodesDisconnected.push_back(pnode);
    1025             :                 }
    1026             :             }
    1027             :         }
    1028             :         {
    1029             :             // Delete disconnected nodes
    1030       25977 :             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
    1031      156096 :             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
    1032             :             {
    1033             :                 // wait until threads are done using it
    1034          78 :                 if (pnode->GetRefCount() <= 0)
    1035             :                 {
    1036          39 :                     bool fDelete = false;
    1037             :                     {
    1038          39 :                         TRY_LOCK(pnode->cs_vSend, lockSend);
    1039          39 :                         if (lockSend)
    1040             :                         {
    1041          39 :                             TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
    1042          39 :                             if (lockRecv)
    1043             :                             {
    1044          39 :                                 TRY_LOCK(pnode->cs_inventory, lockInv);
    1045          39 :                                 if (lockInv)
    1046          39 :                                     fDelete = true;
    1047             :                             }
    1048             :                         }
    1049             :                     }
    1050          39 :                     if (fDelete)
    1051             :                     {
    1052          39 :                         vNodesDisconnected.remove(pnode);
    1053          39 :                         delete pnode;
    1054             :                     }
    1055             :                 }
    1056             :             }
    1057             :         }
    1058       51954 :         if(vNodes.size() != nPrevNodeCount) {
    1059         282 :             nPrevNodeCount = vNodes.size();
    1060         282 :             uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
    1061             :         }
    1062             : 
    1063             :         //
    1064             :         // Find which sockets have data to receive
    1065             :         //
    1066             :         struct timeval timeout;
    1067       25977 :         timeout.tv_sec  = 0;
    1068       25977 :         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
    1069             : 
    1070             :         fd_set fdsetRecv;
    1071             :         fd_set fdsetSend;
    1072             :         fd_set fdsetError;
    1073       25977 :         FD_ZERO(&fdsetRecv);
    1074       25977 :         FD_ZERO(&fdsetSend);
    1075       25977 :         FD_ZERO(&fdsetError);
    1076       25977 :         SOCKET hSocketMax = 0;
    1077       25977 :         bool have_fds = false;
    1078             : 
    1079      401662 :         BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
    1080       49160 :             FD_SET(hListenSocket.socket, &fdsetRecv);
    1081       98320 :             hSocketMax = max(hSocketMax, hListenSocket.socket);
    1082       49160 :             have_fds = true;
    1083             :         }
    1084             : 
    1085             :         {
    1086       25977 :             LOCK(cs_vNodes);
    1087      511458 :             BOOST_FOREACH(CNode* pnode, vNodes)
    1088             :             {
    1089       59266 :                 if (pnode->hSocket == INVALID_SOCKET)
    1090             :                     continue;
    1091       59266 :                 FD_SET(pnode->hSocket, &fdsetError);
    1092      118532 :                 hSocketMax = max(hSocketMax, pnode->hSocket);
    1093       59266 :                 have_fds = true;
    1094             : 
    1095             :                 // Implement the following logic:
    1096             :                 // * If there is data to send, select() for sending data. As this only
    1097             :                 //   happens when optimistic write failed, we choose to first drain the
    1098             :                 //   write buffer in this case before receiving more. This avoids
    1099             :                 //   needlessly queueing received data, if the remote peer is not themselves
    1100             :                 //   receiving data. This means properly utilizing TCP flow control signalling.
    1101             :                 // * Otherwise, if there is no (complete) message in the receive buffer,
    1102             :                 //   or there is space left in the buffer, select() for receiving data.
    1103             :                 // * (if neither of the above applies, there is certainly one message
    1104             :                 //   in the receiver buffer ready to be processed).
    1105             :                 // Together, that means that at least one of the following is always possible,
    1106             :                 // so we don't deadlock:
    1107             :                 // * We send some data.
    1108             :                 // * We wait for data to be received (and disconnect after timeout).
    1109             :                 // * We process a message in the buffer (message handler thread).
    1110             :                 {
    1111       59266 :                     TRY_LOCK(pnode->cs_vSend, lockSend);
    1112      116871 :                     if (lockSend && !pnode->vSendMsg.empty()) {
    1113           0 :                         FD_SET(pnode->hSocket, &fdsetSend);
    1114             :                         continue;
    1115             :                     }
    1116             :                 }
    1117             :                 {
    1118       59266 :                     TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
    1119      175835 :                     if (lockRecv && (
    1120      103932 :                         pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
    1121       11580 :                         pnode->GetTotalRecvSize() <= ReceiveFloodSize()))
    1122       57303 :                         FD_SET(pnode->hSocket, &fdsetRecv);
    1123             :                 }
    1124             :             }
    1125             :         }
    1126             : 
    1127       25974 :         int nSelect = select(have_fds ? hSocketMax + 1 : 0,
    1128       51951 :                              &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
    1129       25977 :         boost::this_thread::interruption_point();
    1130             : 
    1131       25883 :         if (nSelect == SOCKET_ERROR)
    1132             :         {
    1133           0 :             if (have_fds)
    1134             :             {
    1135           0 :                 int nErr = WSAGetLastError();
    1136           0 :                 LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
    1137           0 :                 for (unsigned int i = 0; i <= hSocketMax; i++)
    1138           0 :                     FD_SET(i, &fdsetRecv);
    1139             :             }
    1140           0 :             FD_ZERO(&fdsetSend);
    1141           0 :             FD_ZERO(&fdsetError);
    1142           0 :             MilliSleep(timeout.tv_usec/1000);
    1143             :         }
    1144             : 
    1145             :         //
    1146             :         // Accept new connections
    1147             :         //
    1148      449166 :         BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
    1149             :         {
    1150       48978 :             if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
    1151             :             {
    1152         126 :                 AcceptConnection(hListenSocket);
    1153             :             }
    1154             :         }
    1155             : 
    1156             :         //
    1157             :         // Service each socket
    1158             :         //
    1159             :         vector<CNode*> vNodesCopy;
    1160             :         {
    1161       25883 :             LOCK(cs_vNodes);
    1162       25883 :             vNodesCopy = vNodes;
    1163      511128 :             BOOST_FOREACH(CNode* pnode, vNodesCopy)
    1164             :                 pnode->AddRef();
    1165             :         }
    1166      511128 :         BOOST_FOREACH(CNode* pnode, vNodesCopy)
    1167             :         {
    1168       59305 :             boost::this_thread::interruption_point();
    1169             : 
    1170             :             //
    1171             :             // Receive
    1172             :             //
    1173       59305 :             if (pnode->hSocket == INVALID_SOCKET)
    1174             :                 continue;
    1175       59305 :             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
    1176             :             {
    1177        9182 :                 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
    1178        9182 :                 if (lockRecv)
    1179             :                 {
    1180             :                     {
    1181             :                         // typical socket buffer is 8K-64K
    1182             :                         char pchBuf[0x10000];
    1183       17266 :                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
    1184        8633 :                         if (nBytes > 0)
    1185             :                         {
    1186        8599 :                             if (!pnode->ReceiveMsgBytes(pchBuf, nBytes))
    1187           0 :                                 pnode->CloseSocketDisconnect();
    1188        8599 :                             pnode->nLastRecv = GetTime();
    1189        8599 :                             pnode->nRecvBytes += nBytes;
    1190        8599 :                             pnode->RecordBytesRecv(nBytes);
    1191             :                         }
    1192          34 :                         else if (nBytes == 0)
    1193             :                         {
    1194             :                             // socket closed gracefully
    1195          19 :                             if (!pnode->fDisconnect)
    1196          19 :                                 LogPrint("net", "socket closed\n");
    1197          19 :                             pnode->CloseSocketDisconnect();
    1198             :                         }
    1199          15 :                         else if (nBytes < 0)
    1200             :                         {
    1201             :                             // error
    1202          15 :                             int nErr = WSAGetLastError();
    1203          15 :                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
    1204             :                             {
    1205          15 :                                 if (!pnode->fDisconnect)
    1206          30 :                                     LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
    1207          15 :                                 pnode->CloseSocketDisconnect();
    1208             :                             }
    1209             :                         }
    1210             :                     }
    1211             :                 }
    1212             :             }
    1213             : 
    1214             :             //
    1215             :             // Send
    1216             :             //
    1217       59305 :             if (pnode->hSocket == INVALID_SOCKET)
    1218             :                 continue;
    1219       59271 :             if (FD_ISSET(pnode->hSocket, &fdsetSend))
    1220             :             {
    1221           0 :                 TRY_LOCK(pnode->cs_vSend, lockSend);
    1222           0 :                 if (lockSend)
    1223           0 :                     SocketSendData(pnode);
    1224             :             }
    1225             : 
    1226             :             //
    1227             :             // Inactivity checking
    1228             :             //
    1229       59271 :             int64_t nTime = GetTime();
    1230       59271 :             if (nTime - pnode->nTimeConnected > 60)
    1231             :             {
    1232           0 :                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
    1233             :                 {
    1234           0 :                     LogPrint("net", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id);
    1235           0 :                     pnode->fDisconnect = true;
    1236             :                 }
    1237           0 :                 else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
    1238             :                 {
    1239           0 :                     LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
    1240           0 :                     pnode->fDisconnect = true;
    1241             :                 }
    1242           0 :                 else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
    1243             :                 {
    1244           0 :                     LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
    1245           0 :                     pnode->fDisconnect = true;
    1246             :                 }
    1247           0 :                 else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
    1248             :                 {
    1249           0 :                     LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
    1250           0 :                     pnode->fDisconnect = true;
    1251             :                 }
    1252             :             }
    1253             :         }
    1254             :         {
    1255       25883 :             LOCK(cs_vNodes);
    1256      511128 :             BOOST_FOREACH(CNode* pnode, vNodesCopy)
    1257       59305 :                 pnode->Release();
    1258             :         }
    1259       25883 :     }
    1260             : }
    1261             : 
    1262             : 
    1263             : 
    1264             : 
    1265             : 
    1266             : 
    1267             : 
    1268             : 
    1269             : 
    1270             : #ifdef USE_UPNP
    1271           0 : void ThreadMapPort()
    1272             : {
    1273           0 :     std::string port = strprintf("%u", GetListenPort());
    1274           0 :     const char * multicastif = 0;
    1275           0 :     const char * minissdpdpath = 0;
    1276           0 :     struct UPNPDev * devlist = 0;
    1277             :     char lanaddr[64];
    1278             : 
    1279             : #ifndef UPNPDISCOVER_SUCCESS
    1280             :     /* miniupnpc 1.5 */
    1281             :     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
    1282             : #elif MINIUPNPC_API_VERSION < 14
    1283             :     /* miniupnpc 1.6 */
    1284           0 :     int error = 0;
    1285           0 :     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
    1286             : #else
    1287             :     /* miniupnpc 1.9.20150730 */
    1288             :     int error = 0;
    1289             :     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
    1290             : #endif
    1291             : 
    1292             :     struct UPNPUrls urls;
    1293             :     struct IGDdatas data;
    1294             :     int r;
    1295             : 
    1296           0 :     r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
    1297           0 :     if (r == 1)
    1298             :     {
    1299           0 :         if (fDiscover) {
    1300             :             char externalIPAddress[40];
    1301           0 :             r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
    1302           0 :             if(r != UPNPCOMMAND_SUCCESS)
    1303           0 :                 LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
    1304             :             else
    1305             :             {
    1306           0 :                 if(externalIPAddress[0])
    1307             :                 {
    1308           0 :                     LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
    1309           0 :                     AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
    1310             :                 }
    1311             :                 else
    1312           0 :                     LogPrintf("UPnP: GetExternalIPAddress failed.\n");
    1313             :             }
    1314             :         }
    1315             : 
    1316           0 :         string strDesc = "Bitcoin " + FormatFullVersion();
    1317             : 
    1318             :         try {
    1319             :             while (true) {
    1320             : #ifndef UPNPDISCOVER_SUCCESS
    1321             :                 /* miniupnpc 1.5 */
    1322             :                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
    1323             :                                     port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
    1324             : #else
    1325             :                 /* miniupnpc 1.6 */
    1326             :                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
    1327           0 :                                     port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
    1328             : #endif
    1329             : 
    1330           0 :                 if(r!=UPNPCOMMAND_SUCCESS)
    1331           0 :                     LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
    1332           0 :                         port, port, lanaddr, r, strupnperror(r));
    1333             :                 else
    1334           0 :                     LogPrintf("UPnP Port Mapping successful.\n");;
    1335             : 
    1336           0 :                 MilliSleep(20*60*1000); // Refresh every 20 minutes
    1337             :             }
    1338             :         }
    1339           0 :         catch (const boost::thread_interrupted&)
    1340             :         {
    1341           0 :             r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
    1342           0 :             LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
    1343           0 :             freeUPNPDevlist(devlist); devlist = 0;
    1344           0 :             FreeUPNPUrls(&urls);
    1345           0 :             throw;
    1346             :         }
    1347             :     } else {
    1348           0 :         LogPrintf("No valid UPnP IGDs found\n");
    1349           0 :         freeUPNPDevlist(devlist); devlist = 0;
    1350           0 :         if (r != 0)
    1351           0 :             FreeUPNPUrls(&urls);
    1352             :     }
    1353           0 : }
    1354             : 
    1355         188 : void MapPort(bool fUseUPnP)
    1356             : {
    1357             :     static boost::thread* upnp_thread = NULL;
    1358             : 
    1359         188 :     if (fUseUPnP)
    1360             :     {
    1361           0 :         if (upnp_thread) {
    1362           0 :             upnp_thread->interrupt();
    1363           0 :             upnp_thread->join();
    1364           0 :             delete upnp_thread;
    1365             :         }
    1366           0 :         upnp_thread = new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
    1367             :     }
    1368         188 :     else if (upnp_thread) {
    1369           0 :         upnp_thread->interrupt();
    1370           0 :         upnp_thread->join();
    1371           0 :         delete upnp_thread;
    1372           0 :         upnp_thread = NULL;
    1373             :     }
    1374         188 : }
    1375             : 
    1376             : #else
    1377             : void MapPort(bool)
    1378             : {
    1379             :     // Intentionally left blank.
    1380             : }
    1381             : #endif
    1382             : 
    1383             : 
    1384             : 
    1385             : 
    1386             : 
    1387             : 
    1388          90 : void ThreadDNSAddressSeed()
    1389             : {
    1390             :     // goal: only query DNS seeds if address need is acute
    1391         360 :     if ((addrman.size() > 0) &&
    1392          90 :         (!GetBoolArg("-forcednsseed", false))) {
    1393           0 :         MilliSleep(11 * 1000);
    1394             : 
    1395           0 :         LOCK(cs_vNodes);
    1396           0 :         if (vNodes.size() >= 2) {
    1397           0 :             LogPrintf("P2P peers available. Skipped DNS seeding.\n");
    1398          90 :             return;
    1399             :         }
    1400             :     }
    1401             : 
    1402         180 :     const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
    1403          90 :     int found = 0;
    1404             : 
    1405          90 :     LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
    1406             : 
    1407         450 :     BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
    1408           0 :         if (HaveNameProxy()) {
    1409           0 :             AddOneShot(seed.host);
    1410             :         } else {
    1411             :             vector<CNetAddr> vIPs;
    1412             :             vector<CAddress> vAdd;
    1413           0 :             if (LookupHost(seed.host.c_str(), vIPs))
    1414             :             {
    1415           0 :                 BOOST_FOREACH(const CNetAddr& ip, vIPs)
    1416             :                 {
    1417           0 :                     int nOneDay = 24*3600;
    1418           0 :                     CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
    1419           0 :                     addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
    1420           0 :                     vAdd.push_back(addr);
    1421           0 :                     found++;
    1422             :                 }
    1423             :             }
    1424           0 :             addrman.Add(vAdd, CNetAddr(seed.name, true));
    1425             :         }
    1426             :     }
    1427             : 
    1428          90 :     LogPrintf("%d addresses found from DNS seeds\n", found);
    1429             : }
    1430             : 
    1431             : 
    1432             : 
    1433             : 
    1434             : 
    1435             : 
    1436             : 
    1437             : 
    1438             : 
    1439             : 
    1440             : 
    1441             : 
    1442          94 : void DumpAddresses()
    1443             : {
    1444          94 :     int64_t nStart = GetTimeMillis();
    1445             : 
    1446          94 :     CAddrDB adb;
    1447          94 :     adb.Write(addrman);
    1448             : 
    1449             :     LogPrint("net", "Flushed %d addresses to peers.dat  %dms\n",
    1450         188 :            addrman.size(), GetTimeMillis() - nStart);
    1451          94 : }
    1452             : 
    1453          94 : void DumpData()
    1454             : {
    1455          94 :     DumpAddresses();
    1456             : 
    1457          94 :     if (CNode::BannedSetIsDirty())
    1458             :     {
    1459           1 :         DumpBanlist();
    1460           1 :         CNode::SetBannedSetDirty(false);
    1461             :     }
    1462          94 : }
    1463             : 
    1464        1842 : void static ProcessOneShot()
    1465             : {
    1466             :     string strDest;
    1467             :     {
    1468        1842 :         LOCK(cs_vOneShots);
    1469        1842 :         if (vOneShots.empty())
    1470        1842 :             return;
    1471           0 :         strDest = vOneShots.front();
    1472           0 :         vOneShots.pop_front();
    1473             :     }
    1474           0 :     CAddress addr;
    1475           0 :     CSemaphoreGrant grant(*semOutbound, true);
    1476           0 :     if (grant) {
    1477           0 :         if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
    1478           0 :             AddOneShot(strDest);
    1479             :     }
    1480             : }
    1481             : 
    1482          94 : void ThreadOpenConnections()
    1483             : {
    1484             :     // Connect to specific addresses
    1485         388 :     if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
    1486             :     {
    1487          27 :         for (int64_t nLoop = 0;; nLoop++)
    1488             :         {
    1489          31 :             ProcessOneShot();
    1490         394 :             BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"])
    1491             :             {
    1492          31 :                 CAddress addr;
    1493          31 :                 OpenNetworkConnection(addr, NULL, strAddr.c_str());
    1494          92 :                 for (int i = 0; i < 10 && i < nLoop; i++)
    1495             :                 {
    1496          95 :                     MilliSleep(500);
    1497             :                 }
    1498             :             }
    1499          28 :             MilliSleep(500);
    1500          27 :         }
    1501             :     }
    1502             : 
    1503             :     // Initiate network connections
    1504          90 :     int64_t nStart = GetTime();
    1505             :     while (true)
    1506             :     {
    1507        1811 :         ProcessOneShot();
    1508             : 
    1509        1811 :         MilliSleep(500);
    1510             : 
    1511        1721 :         CSemaphoreGrant grant(*semOutbound);
    1512        1721 :         boost::this_thread::interruption_point();
    1513             : 
    1514             :         // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
    1515        1721 :         if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
    1516             :             static bool done = false;
    1517          58 :             if (!done) {
    1518           1 :                 LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
    1519           3 :                 addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
    1520           1 :                 done = true;
    1521             :             }
    1522             :         }
    1523             : 
    1524             :         //
    1525             :         // Choose an address to connect to based on most recently seen
    1526             :         //
    1527        1721 :         CAddress addrConnect;
    1528             : 
    1529             :         // Only connect out to one peer per network group (/16 for IPv4).
    1530             :         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
    1531        1721 :         int nOutbound = 0;
    1532             :         set<vector<unsigned char> > setConnected;
    1533             :         {
    1534        1721 :             LOCK(cs_vNodes);
    1535       32052 :             BOOST_FOREACH(CNode* pnode, vNodes) {
    1536        3621 :                 if (!pnode->fInbound) {
    1537        3444 :                     setConnected.insert(pnode->addr.GetGroup());
    1538        1722 :                     nOutbound++;
    1539             :                 }
    1540             :             }
    1541             :         }
    1542             : 
    1543        1721 :         int64_t nANow = GetAdjustedTime();
    1544             : 
    1545             :         int nTries = 0;
    1546             :         while (true)
    1547             :         {
    1548        1721 :             CAddrInfo addr = addrman.Select();
    1549             : 
    1550             :             // if we selected an invalid address, restart
    1551        1721 :             if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
    1552             :                 break;
    1553             : 
    1554             :             // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
    1555             :             // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
    1556             :             // already-connected network ranges, ...) before trying new addrman addresses.
    1557           0 :             nTries++;
    1558           0 :             if (nTries > 100)
    1559             :                 break;
    1560             : 
    1561           0 :             if (IsLimited(addr))
    1562           0 :                 continue;
    1563             : 
    1564             :             // only consider very recently tried nodes after 30 failed attempts
    1565           0 :             if (nANow - addr.nLastTry < 600 && nTries < 30)
    1566             :                 continue;
    1567             : 
    1568             :             // do not allow non-default ports, unless after 50 invalid addresses selected already
    1569           0 :             if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
    1570             :                 continue;
    1571             : 
    1572           0 :             addrConnect = addr;
    1573           0 :             break;
    1574             :         }
    1575             : 
    1576        3442 :         if (addrConnect.IsValid())
    1577           0 :             OpenNetworkConnection(addrConnect, &grant);
    1578        1721 :     }
    1579             : }
    1580             : 
    1581          94 : void ThreadOpenAddedConnections()
    1582             : {
    1583             :     {
    1584          94 :         LOCK(cs_vAddedNodes);
    1585         282 :         vAddedNodes = mapMultiArgs["-addnode"];
    1586             :     }
    1587             : 
    1588          94 :     if (HaveNameProxy()) {
    1589             :         while(true) {
    1590          12 :             list<string> lAddresses(0);
    1591             :             {
    1592           4 :                 LOCK(cs_vAddedNodes);
    1593          24 :                 BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
    1594             :                     lAddresses.push_back(strAddNode);
    1595             :             }
    1596          24 :             BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
    1597           0 :                 CAddress addr;
    1598           0 :                 CSemaphoreGrant grant(*semOutbound);
    1599           0 :                 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
    1600           0 :                 MilliSleep(500);
    1601             :             }
    1602           4 :             MilliSleep(120000); // Retry every 2 minutes
    1603           0 :         }
    1604             :     }
    1605             : 
    1606           0 :     for (unsigned int i = 0; true; i++)
    1607             :     {
    1608         270 :         list<string> lAddresses(0);
    1609             :         {
    1610          90 :             LOCK(cs_vAddedNodes);
    1611         540 :             BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
    1612             :                 lAddresses.push_back(strAddNode);
    1613             :         }
    1614             : 
    1615         360 :         list<vector<CService> > lservAddressesToAdd(0);
    1616         540 :         BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
    1617         180 :             vector<CService> vservNode(0);
    1618           0 :             if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
    1619             :             {
    1620             :                 lservAddressesToAdd.push_back(vservNode);
    1621             :                 {
    1622           0 :                     LOCK(cs_setservAddNodeAddresses);
    1623           0 :                     BOOST_FOREACH(const CService& serv, vservNode)
    1624           0 :                         setservAddNodeAddresses.insert(serv);
    1625             :                 }
    1626             :             }
    1627             :         }
    1628             :         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
    1629             :         // (keeping in mind that addnode entries can have many IPs if fNameLookup)
    1630             :         {
    1631          90 :             LOCK(cs_vNodes);
    1632         540 :             BOOST_FOREACH(CNode* pnode, vNodes)
    1633           0 :                 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
    1634           0 :                     BOOST_FOREACH(const CService& addrNode, *(it))
    1635           0 :                         if (pnode->addr == addrNode)
    1636             :                         {
    1637           0 :                             it = lservAddressesToAdd.erase(it);
    1638           0 :                             it--;
    1639             :                             break;
    1640             :                         }
    1641             :         }
    1642         540 :         BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
    1643             :         {
    1644           0 :             CSemaphoreGrant grant(*semOutbound);
    1645           0 :             OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
    1646           0 :             MilliSleep(500);
    1647             :         }
    1648          90 :         MilliSleep(120000); // Retry every 2 minutes
    1649           0 :     }
    1650             : }
    1651             : 
    1652             : // if successful, this moves the passed grant to the constructed node
    1653         168 : bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
    1654             : {
    1655             :     //
    1656             :     // Initiate outbound network connection
    1657             :     //
    1658         168 :     boost::this_thread::interruption_point();
    1659         168 :     if (!pszDest) {
    1660           0 :         if (IsLocal(addrConnect) ||
    1661           0 :             FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
    1662           0 :             FindNode(addrConnect.ToStringIPPort()))
    1663             :             return false;
    1664         504 :     } else if (FindNode(std::string(pszDest)))
    1665             :         return false;
    1666             : 
    1667         147 :     CNode* pnode = ConnectNode(addrConnect, pszDest);
    1668         147 :     boost::this_thread::interruption_point();
    1669             : 
    1670         147 :     if (!pnode)
    1671             :         return false;
    1672         139 :     if (grantOutbound)
    1673           0 :         grantOutbound->MoveTo(pnode->grantOutbound);
    1674         139 :     pnode->fNetworkNode = true;
    1675         139 :     if (fOneShot)
    1676           0 :         pnode->fOneShot = true;
    1677             : 
    1678             :     return true;
    1679             : }
    1680             : 
    1681             : 
    1682          94 : void ThreadMessageHandler()
    1683             : {
    1684          94 :     boost::mutex condition_mutex;
    1685             :     boost::unique_lock<boost::mutex> lock(condition_mutex);
    1686             : 
    1687          94 :     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
    1688             :     while (true)
    1689             :     {
    1690             :         vector<CNode*> vNodesCopy;
    1691             :         {
    1692       24309 :             LOCK(cs_vNodes);
    1693       24309 :             vNodesCopy = vNodes;
    1694      502020 :             BOOST_FOREACH(CNode* pnode, vNodesCopy) {
    1695             :                 pnode->AddRef();
    1696             :             }
    1697             :         }
    1698             : 
    1699             :         // Poll the connected nodes for messages
    1700       24309 :         CNode* pnodeTrickle = NULL;
    1701       24309 :         if (!vNodesCopy.empty())
    1702       65850 :             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
    1703             : 
    1704       24309 :         bool fSleep = true;
    1705             : 
    1706      502020 :         BOOST_FOREACH(CNode* pnode, vNodesCopy)
    1707             :         {
    1708       59361 :             if (pnode->fDisconnect)
    1709             :                 continue;
    1710             : 
    1711             :             // Receive messages
    1712             :             {
    1713       59361 :                 TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
    1714       59361 :                 if (lockRecv)
    1715             :                 {
    1716       59067 :                     if (!g_signals.ProcessMessages(pnode))
    1717           0 :                         pnode->CloseSocketDisconnect();
    1718             : 
    1719       59067 :                     if (pnode->nSendSize < SendBufferSize())
    1720             :                     {
    1721      205923 :                         if (!pnode->vRecvGetData.empty() || (!pnode->vRecvMsg.empty() && pnode->vRecvMsg[0].complete()))
    1722             :                         {
    1723       15623 :                             fSleep = false;
    1724             :                         }
    1725             :                     }
    1726             :                 }
    1727             :             }
    1728       59361 :             boost::this_thread::interruption_point();
    1729             : 
    1730             :             // Send messages
    1731             :             {
    1732       59361 :                 TRY_LOCK(pnode->cs_vSend, lockSend);
    1733       59361 :                 if (lockSend)
    1734       59359 :                     g_signals.SendMessages(pnode, pnode == pnodeTrickle || pnode->fWhitelisted);
    1735             :             }
    1736       59361 :             boost::this_thread::interruption_point();
    1737             :         }
    1738             : 
    1739             :         {
    1740       24309 :             LOCK(cs_vNodes);
    1741      502020 :             BOOST_FOREACH(CNode* pnode, vNodesCopy)
    1742       59361 :                 pnode->Release();
    1743             :         }
    1744             : 
    1745       24309 :         if (fSleep)
    1746       26914 :             messageHandlerCondition.timed_wait(lock, boost::posix_time::microsec_clock::universal_time() + boost::posix_time::milliseconds(100));
    1747          94 :     }
    1748             : }
    1749             : 
    1750             : 
    1751             : 
    1752             : 
    1753             : 
    1754             : 
    1755         182 : bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted)
    1756             : {
    1757             :     strError = "";
    1758         182 :     int nOne = 1;
    1759             : 
    1760             :     // Create socket for listening for incoming connections
    1761             :     struct sockaddr_storage sockaddr;
    1762         182 :     socklen_t len = sizeof(sockaddr);
    1763         182 :     if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
    1764             :     {
    1765           0 :         strError = strprintf("Error: Bind address family for %s not supported", addrBind.ToString());
    1766           0 :         LogPrintf("%s\n", strError);
    1767             :         return false;
    1768             :     }
    1769             : 
    1770         182 :     SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
    1771         182 :     if (hListenSocket == INVALID_SOCKET)
    1772             :     {
    1773           0 :         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()));
    1774           0 :         LogPrintf("%s\n", strError);
    1775             :         return false;
    1776             :     }
    1777         182 :     if (!IsSelectableSocket(hListenSocket))
    1778             :     {
    1779             :         strError = "Error: Couldn't create a listenable socket for incoming connections";
    1780           0 :         LogPrintf("%s\n", strError);
    1781             :         return false;
    1782             :     }
    1783             : 
    1784             : 
    1785             : #ifndef WIN32
    1786             : #ifdef SO_NOSIGPIPE
    1787             :     // Different way of disabling SIGPIPE on BSD
    1788             :     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
    1789             : #endif
    1790             :     // Allow binding if the port is still in TIME_WAIT state after
    1791             :     // the program was closed and restarted.
    1792         182 :     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
    1793             : #else
    1794             :     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOne, sizeof(int));
    1795             : #endif
    1796             : 
    1797             :     // Set to non-blocking, incoming connections will also inherit this
    1798         182 :     if (!SetSocketNonBlocking(hListenSocket, true)) {
    1799           0 :         strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
    1800           0 :         LogPrintf("%s\n", strError);
    1801             :         return false;
    1802             :     }
    1803             : 
    1804             :     // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
    1805             :     // and enable it by default or not. Try to enable it, if possible.
    1806         182 :     if (addrBind.IsIPv6()) {
    1807             : #ifdef IPV6_V6ONLY
    1808             : #ifdef WIN32
    1809             :         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
    1810             : #else
    1811          91 :         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
    1812             : #endif
    1813             : #endif
    1814             : #ifdef WIN32
    1815             :         int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
    1816             :         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
    1817             : #endif
    1818             :     }
    1819             : 
    1820         182 :     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
    1821             :     {
    1822           0 :         int nErr = WSAGetLastError();
    1823           0 :         if (nErr == WSAEADDRINUSE)
    1824           0 :             strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin Core is probably already running."), addrBind.ToString());
    1825             :         else
    1826           0 :             strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
    1827           0 :         LogPrintf("%s\n", strError);
    1828           0 :         CloseSocket(hListenSocket);
    1829             :         return false;
    1830             :     }
    1831         364 :     LogPrintf("Bound to %s\n", addrBind.ToString());
    1832             : 
    1833             :     // Listen for incoming connections
    1834         182 :     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
    1835             :     {
    1836           0 :         strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
    1837           0 :         LogPrintf("%s\n", strError);
    1838           0 :         CloseSocket(hListenSocket);
    1839             :         return false;
    1840             :     }
    1841             : 
    1842         364 :     vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted));
    1843             : 
    1844         182 :     if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
    1845           0 :         AddLocal(addrBind, LOCAL_BIND);
    1846             : 
    1847             :     return true;
    1848             : }
    1849             : 
    1850          94 : void static Discover(boost::thread_group& threadGroup)
    1851             : {
    1852          94 :     if (!fDiscover)
    1853          93 :         return;
    1854             : 
    1855             : #ifdef WIN32
    1856             :     // Get local host IP
    1857             :     char pszHostName[256] = "";
    1858             :     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
    1859             :     {
    1860             :         vector<CNetAddr> vaddr;
    1861             :         if (LookupHost(pszHostName, vaddr))
    1862             :         {
    1863             :             BOOST_FOREACH (const CNetAddr &addr, vaddr)
    1864             :             {
    1865             :                 if (AddLocal(addr, LOCAL_IF))
    1866             :                     LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
    1867             :             }
    1868             :         }
    1869             :     }
    1870             : #else
    1871             :     // Get local host ip
    1872             :     struct ifaddrs* myaddrs;
    1873           1 :     if (getifaddrs(&myaddrs) == 0)
    1874             :     {
    1875           7 :         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
    1876             :         {
    1877           6 :             if (ifa->ifa_addr == NULL) continue;
    1878           6 :             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
    1879           6 :             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
    1880           3 :             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
    1881           3 :             if (ifa->ifa_addr->sa_family == AF_INET)
    1882             :             {
    1883           1 :                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
    1884           1 :                 CNetAddr addr(s4->sin_addr);
    1885           1 :                 if (AddLocal(addr, LOCAL_IF))
    1886           0 :                     LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
    1887             :             }
    1888           2 :             else if (ifa->ifa_addr->sa_family == AF_INET6)
    1889             :             {
    1890           1 :                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
    1891           1 :                 CNetAddr addr(s6->sin6_addr);
    1892           1 :                 if (AddLocal(addr, LOCAL_IF))
    1893           0 :                     LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
    1894             :             }
    1895             :         }
    1896           1 :         freeifaddrs(myaddrs);
    1897             :     }
    1898             : #endif
    1899             : }
    1900             : 
    1901          94 : void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
    1902             : {
    1903         188 :     uiInterface.InitMessage(_("Loading addresses..."));
    1904             :     // Load addresses for peers.dat
    1905          94 :     int64_t nStart = GetTimeMillis();
    1906             :     {
    1907          94 :         CAddrDB adb;
    1908          94 :         if (!adb.Read(addrman))
    1909          66 :             LogPrintf("Invalid or missing peers.dat; recreating\n");
    1910             :     }
    1911             : 
    1912             :     //try to read stored banlist
    1913          94 :     CBanDB bandb;
    1914             :     banmap_t banmap;
    1915          94 :     if (!bandb.Read(banmap))
    1916          93 :         LogPrintf("Invalid or missing banlist.dat; recreating\n");
    1917             : 
    1918          94 :     CNode::SetBanned(banmap); //thread save setter
    1919          94 :     CNode::SetBannedSetDirty(false); //no need to write down just read or nonexistent data
    1920          94 :     CNode::SweepBanned(); //sweap out unused entries
    1921             : 
    1922         282 :     LogPrintf("Loaded %i addresses from peers.dat  %dms\n",
    1923          94 :            addrman.size(), GetTimeMillis() - nStart);
    1924          94 :     fAddressesInitialized = true;
    1925             : 
    1926          94 :     if (semOutbound == NULL) {
    1927             :         // initialize semaphore
    1928          94 :         int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
    1929          94 :         semOutbound = new CSemaphore(nMaxOutbound);
    1930             :     }
    1931             : 
    1932          94 :     if (pnodeLocalHost == NULL)
    1933         282 :         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
    1934             : 
    1935          94 :     Discover(threadGroup);
    1936             : 
    1937             :     //
    1938             :     // Start threads
    1939             :     //
    1940             : 
    1941         282 :     if (!GetBoolArg("-dnsseed", true))
    1942           4 :         LogPrintf("DNS seeding disabled\n");
    1943             :     else
    1944          90 :         threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
    1945             : 
    1946             :     // Map ports with UPnP
    1947         282 :     MapPort(GetBoolArg("-upnp", DEFAULT_UPNP));
    1948             : 
    1949             :     // Send and receive from sockets, accept connections
    1950          94 :     threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "net", &ThreadSocketHandler));
    1951             : 
    1952             :     // Initiate outbound connections from -addnode
    1953          94 :     threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "addcon", &ThreadOpenAddedConnections));
    1954             : 
    1955             :     // Initiate outbound connections
    1956          94 :     threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "opencon", &ThreadOpenConnections));
    1957             : 
    1958             :     // Process messages
    1959          94 :     threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
    1960             : 
    1961             :     // Dump network addresses
    1962         188 :     scheduler.scheduleEvery(&DumpData, DUMP_ADDRESSES_INTERVAL);
    1963          94 : }
    1964             : 
    1965          94 : bool StopNode()
    1966             : {
    1967          94 :     LogPrintf("StopNode()\n");
    1968          94 :     MapPort(false);
    1969          94 :     if (semOutbound)
    1970         752 :         for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
    1971         752 :             semOutbound->post();
    1972             : 
    1973          94 :     if (fAddressesInitialized)
    1974             :     {
    1975          94 :         DumpData();
    1976          94 :         fAddressesInitialized = false;
    1977             :     }
    1978             : 
    1979          94 :     return true;
    1980             : }
    1981             : 
    1982             : class CNetCleanup
    1983             : {
    1984             : public:
    1985           0 :     CNetCleanup() {}
    1986             : 
    1987          96 :     ~CNetCleanup()
    1988             :     {
    1989             :         // Close sockets
    1990        1932 :         BOOST_FOREACH(CNode* pnode, vNodes)
    1991         226 :             if (pnode->hSocket != INVALID_SOCKET)
    1992         226 :                 CloseSocket(pnode->hSocket);
    1993        1668 :         BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket)
    1994         182 :             if (hListenSocket.socket != INVALID_SOCKET)
    1995         182 :                 if (!CloseSocket(hListenSocket.socket))
    1996           0 :                     LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
    1997             : 
    1998             :         // clean up some globals (to help leak detection)
    1999        1932 :         BOOST_FOREACH(CNode *pnode, vNodes)
    2000         226 :             delete pnode;
    2001         576 :         BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
    2002           0 :             delete pnode;
    2003             :         vNodes.clear();
    2004             :         vNodesDisconnected.clear();
    2005             :         vhListenSocket.clear();
    2006         190 :         delete semOutbound;
    2007          96 :         semOutbound = NULL;
    2008          96 :         delete pnodeLocalHost;
    2009          96 :         pnodeLocalHost = NULL;
    2010             : 
    2011             : #ifdef WIN32
    2012             :         // Shutdown Windows Sockets
    2013             :         WSACleanup();
    2014             : #endif
    2015          96 :     }
    2016             : }
    2017          96 : instance_of_cnetcleanup;
    2018             : 
    2019             : 
    2020             : 
    2021             : 
    2022             : 
    2023             : 
    2024             : 
    2025         491 : void RelayTransaction(const CTransaction& tx)
    2026             : {
    2027             :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    2028             :     ss.reserve(10000);
    2029             :     ss << tx;
    2030         491 :     RelayTransaction(tx, ss);
    2031         491 : }
    2032             : 
    2033         491 : void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
    2034             : {
    2035         491 :     CInv inv(MSG_TX, tx.GetHash());
    2036             :     {
    2037         491 :         LOCK(cs_mapRelay);
    2038             :         // Expire old relay messages
    2039         938 :         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
    2040             :         {
    2041           0 :             mapRelay.erase(vRelayExpiration.front().second);
    2042           0 :             vRelayExpiration.pop_front();
    2043             :         }
    2044             : 
    2045             :         // Save original serialized message so newer versions are preserved
    2046        1964 :         mapRelay.insert(std::make_pair(inv, ss));
    2047         982 :         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
    2048             :     }
    2049         491 :     LOCK(cs_vNodes);
    2050       12462 :     BOOST_FOREACH(CNode* pnode, vNodes)
    2051             :     {
    2052        1586 :         if(!pnode->fRelayTxes)
    2053           0 :             continue;
    2054        1586 :         LOCK(pnode->cs_filter);
    2055        1586 :         if (pnode->pfilter)
    2056             :         {
    2057        1586 :             if (pnode->pfilter->IsRelevantAndUpdate(tx))
    2058        1586 :                 pnode->PushInventory(inv);
    2059             :         } else
    2060           0 :             pnode->PushInventory(inv);
    2061             :     }
    2062         491 : }
    2063             : 
    2064        8599 : void CNode::RecordBytesRecv(uint64_t bytes)
    2065             : {
    2066        8599 :     LOCK(cs_totalBytesRecv);
    2067        8599 :     nTotalBytesRecv += bytes;
    2068        8599 : }
    2069             : 
    2070       20967 : void CNode::RecordBytesSent(uint64_t bytes)
    2071             : {
    2072       20967 :     LOCK(cs_totalBytesSent);
    2073       20967 :     nTotalBytesSent += bytes;
    2074       20967 : }
    2075             : 
    2076           0 : uint64_t CNode::GetTotalBytesRecv()
    2077             : {
    2078           0 :     LOCK(cs_totalBytesRecv);
    2079           0 :     return nTotalBytesRecv;
    2080             : }
    2081             : 
    2082           0 : uint64_t CNode::GetTotalBytesSent()
    2083             : {
    2084           0 :     LOCK(cs_totalBytesSent);
    2085           0 :     return nTotalBytesSent;
    2086             : }
    2087             : 
    2088           0 : void CNode::Fuzz(int nChance)
    2089             : {
    2090           0 :     if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake
    2091           0 :     if (GetRand(nChance) != 0) return; // Fuzz 1 of every nChance messages
    2092             : 
    2093           0 :     switch (GetRand(3))
    2094             :     {
    2095             :     case 0:
    2096             :         // xor a random byte with a random value:
    2097           0 :         if (!ssSend.empty()) {
    2098           0 :             CDataStream::size_type pos = GetRand(ssSend.size());
    2099           0 :             ssSend[pos] ^= (unsigned char)(GetRand(256));
    2100             :         }
    2101             :         break;
    2102             :     case 1:
    2103             :         // delete a random byte:
    2104           0 :         if (!ssSend.empty()) {
    2105           0 :             CDataStream::size_type pos = GetRand(ssSend.size());
    2106           0 :             ssSend.erase(ssSend.begin()+pos);
    2107             :         }
    2108             :         break;
    2109             :     case 2:
    2110             :         // insert a random byte at a random position
    2111             :         {
    2112           0 :             CDataStream::size_type pos = GetRand(ssSend.size());
    2113           0 :             char ch = (char)GetRand(256);
    2114           0 :             ssSend.insert(ssSend.begin()+pos, ch);
    2115             :         }
    2116           0 :         break;
    2117             :     }
    2118             :     // Chance of more than one change half the time:
    2119             :     // (more changes exponentially less likely):
    2120           0 :     Fuzz(2);
    2121             : }
    2122             : 
    2123             : //
    2124             : // CAddrDB
    2125             : //
    2126             : 
    2127         188 : CAddrDB::CAddrDB()
    2128             : {
    2129         564 :     pathAddr = GetDataDir() / "peers.dat";
    2130         188 : }
    2131             : 
    2132          94 : bool CAddrDB::Write(const CAddrMan& addr)
    2133             : {
    2134             :     // Generate random temporary filename
    2135          94 :     unsigned short randv = 0;
    2136          94 :     GetRandBytes((unsigned char*)&randv, sizeof(randv));
    2137          94 :     std::string tmpfn = strprintf("peers.dat.%04x", randv);
    2138             : 
    2139             :     // serialize addresses, checksum data up to that point, then append csum
    2140             :     CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
    2141         376 :     ssPeers << FLATDATA(Params().MessageStart());
    2142             :     ssPeers << addr;
    2143          94 :     uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
    2144             :     ssPeers << hash;
    2145             : 
    2146             :     // open temp output file, and associate with CAutoFile
    2147         188 :     boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
    2148         188 :     FILE *file = fopen(pathTmp.string().c_str(), "wb");
    2149             :     CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
    2150          94 :     if (fileout.IsNull())
    2151           0 :         return error("%s: Failed to open file %s", __func__, pathTmp.string());
    2152             : 
    2153             :     // Write and commit header, data
    2154             :     try {
    2155          94 :         fileout << ssPeers;
    2156             :     }
    2157           0 :     catch (const std::exception& e) {
    2158           0 :         return error("%s: Serialize or I/O error - %s", __func__, e.what());
    2159             :     }
    2160          94 :     FileCommit(fileout.Get());
    2161          94 :     fileout.fclose();
    2162             : 
    2163             :     // replace existing peers.dat, if any, with new peers.dat.XXXX
    2164         376 :     if (!RenameOver(pathTmp, pathAddr))
    2165           0 :         return error("%s: Rename-into-place failed", __func__);
    2166             : 
    2167             :     return true;
    2168             : }
    2169             : 
    2170          94 : bool CAddrDB::Read(CAddrMan& addr)
    2171             : {
    2172             :     // open input file, and associate with CAutoFile
    2173         282 :     FILE *file = fopen(pathAddr.string().c_str(), "rb");
    2174             :     CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
    2175          94 :     if (filein.IsNull())
    2176         132 :         return error("%s: Failed to open file %s", __func__, pathAddr.string());
    2177             : 
    2178             :     // use file size to size memory buffer
    2179          56 :     uint64_t fileSize = boost::filesystem::file_size(pathAddr);
    2180          28 :     uint64_t dataSize = 0;
    2181             :     // Don't try to resize to a negative number if file is small
    2182          28 :     if (fileSize >= sizeof(uint256))
    2183          28 :         dataSize = fileSize - sizeof(uint256);
    2184             :     vector<unsigned char> vchData;
    2185          28 :     vchData.resize(dataSize);
    2186             :     uint256 hashIn;
    2187             : 
    2188             :     // read data and checksum from file
    2189             :     try {
    2190          28 :         filein.read((char *)&vchData[0], dataSize);
    2191          28 :         filein >> hashIn;
    2192             :     }
    2193           0 :     catch (const std::exception& e) {
    2194           0 :         return error("%s: Deserialize or I/O error - %s", __func__, e.what());
    2195             :     }
    2196          28 :     filein.fclose();
    2197             : 
    2198             :     CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
    2199             : 
    2200             :     // verify stored checksum matches input data
    2201          28 :     uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
    2202          28 :     if (hashIn != hashTmp)
    2203           0 :         return error("%s: Checksum mismatch, data corrupted", __func__);
    2204             : 
    2205             :     unsigned char pchMsgTmp[4];
    2206             :     try {
    2207             :         // de-serialize file header (network specific magic number) and ..
    2208          28 :         ssPeers >> FLATDATA(pchMsgTmp);
    2209             : 
    2210             :         // ... verify the network matches ours
    2211          56 :         if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
    2212           0 :             return error("%s: Invalid network magic number", __func__);
    2213             : 
    2214             :         // de-serialize address data into one CAddrMan object
    2215             :         ssPeers >> addr;
    2216             :     }
    2217           0 :     catch (const std::exception& e) {
    2218           0 :         return error("%s: Deserialize or I/O error - %s", __func__, e.what());
    2219             :     }
    2220             : 
    2221             :     return true;
    2222             : }
    2223             : 
    2224       34740 : unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
    2225      279372 : unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
    2226             : 
    2227         363 : CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) :
    2228             :     ssSend(SER_NETWORK, INIT_PROTO_VERSION),
    2229             :     addrKnown(5000, 0.001),
    2230        6171 :     setInventoryKnown(SendBufferSize() / 1000)
    2231             : {
    2232         363 :     nServices = 0;
    2233         363 :     hSocket = hSocketIn;
    2234         363 :     nRecvVersion = INIT_PROTO_VERSION;
    2235         363 :     nLastSend = 0;
    2236         363 :     nLastRecv = 0;
    2237         363 :     nSendBytes = 0;
    2238         363 :     nRecvBytes = 0;
    2239         363 :     nTimeConnected = GetTime();
    2240         363 :     nTimeOffset = 0;
    2241         363 :     addr = addrIn;
    2242         726 :     addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
    2243         363 :     nVersion = 0;
    2244         363 :     strSubVer = "";
    2245         363 :     fWhitelisted = false;
    2246         363 :     fOneShot = false;
    2247         363 :     fClient = false; // set by version message
    2248         363 :     fInbound = fInboundIn;
    2249         363 :     fNetworkNode = false;
    2250         363 :     fSuccessfullyConnected = false;
    2251         363 :     fDisconnect = false;
    2252         363 :     nRefCount = 0;
    2253         363 :     nSendSize = 0;
    2254         363 :     nSendOffset = 0;
    2255         363 :     hashContinue = uint256();
    2256         363 :     nStartingHeight = -1;
    2257         363 :     fGetAddr = false;
    2258         363 :     fRelayTxes = false;
    2259         726 :     pfilter = new CBloomFilter();
    2260         363 :     nPingNonceSent = 0;
    2261         363 :     nPingUsecStart = 0;
    2262         363 :     nPingUsecTime = 0;
    2263         363 :     fPingQueued = false;
    2264         363 :     nMinPingUsecTime = std::numeric_limits<int64_t>::max();
    2265             : 
    2266             :     {
    2267         363 :         LOCK(cs_nLastNodeId);
    2268         363 :         id = nLastNodeId++;
    2269             :     }
    2270             : 
    2271         363 :     if (fLogIPs)
    2272           0 :         LogPrint("net", "Added connection to %s peer=%d\n", addrName, id);
    2273             :     else
    2274         363 :         LogPrint("net", "Added connection peer=%d\n", id);
    2275             : 
    2276             :     // Be shy and don't send version until we hear
    2277         363 :     if (hSocket != INVALID_SOCKET && !fInbound)
    2278         139 :         PushVersion();
    2279             : 
    2280         363 :     GetNodeSignals().InitializeNode(GetId(), this);
    2281         363 : }
    2282             : 
    2283        5445 : CNode::~CNode()
    2284             : {
    2285         363 :     CloseSocket(hSocket);
    2286             : 
    2287         363 :     if (pfilter)
    2288         726 :         delete pfilter;
    2289             : 
    2290         363 :     GetNodeSignals().FinalizeNode(GetId());
    2291         363 : }
    2292             : 
    2293         518 : void CNode::AskFor(const CInv& inv)
    2294             : {
    2295        1036 :     if (mapAskFor.size() > MAPASKFOR_MAX_SZ)
    2296           0 :         return;
    2297             :     // We're using mapAskFor as a priority queue,
    2298             :     // the key is the earliest time the request can be sent
    2299             :     int64_t nRequestTime;
    2300         518 :     limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv);
    2301         518 :     if (it != mapAlreadyAskedFor.end())
    2302         155 :         nRequestTime = it->second;
    2303             :     else
    2304         363 :         nRequestTime = 0;
    2305        1554 :     LogPrint("net", "askfor %s  %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000), id);
    2306             : 
    2307             :     // Make sure not to reuse time indexes to keep things in the same order
    2308         518 :     int64_t nNow = GetTimeMicros() - 1000000;
    2309             :     static int64_t nLastTime;
    2310         518 :     ++nLastTime;
    2311         518 :     nNow = std::max(nNow, nLastTime);
    2312         518 :     nLastTime = nNow;
    2313             : 
    2314             :     // Each retry is 2 minutes after the last
    2315        1036 :     nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
    2316         518 :     if (it != mapAlreadyAskedFor.end())
    2317         155 :         mapAlreadyAskedFor.update(it, nRequestTime);
    2318             :     else
    2319         363 :         mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
    2320        1554 :     mapAskFor.insert(std::make_pair(nRequestTime, inv));
    2321             : }
    2322             : 
    2323       20974 : void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend)
    2324             : {
    2325       20974 :     ENTER_CRITICAL_SECTION(cs_vSend);
    2326       41948 :     assert(ssSend.size() == 0);
    2327       62922 :     ssSend << CMessageHeader(Params().MessageStart(), pszCommand, 0);
    2328       83896 :     LogPrint("net", "sending: %s ", SanitizeString(pszCommand));
    2329       20974 : }
    2330             : 
    2331           0 : void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
    2332             : {
    2333           0 :     ssSend.clear();
    2334             : 
    2335           0 :     LEAVE_CRITICAL_SECTION(cs_vSend);
    2336             : 
    2337           0 :     LogPrint("net", "(aborted)\n");
    2338           0 : }
    2339             : 
    2340       20974 : void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
    2341             : {
    2342             :     // The -*messagestest options are intentionally not documented in the help message,
    2343             :     // since they are only used during development to debug the networking code and are
    2344             :     // not intended for end-users.
    2345       83896 :     if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0)
    2346             :     {
    2347           0 :         LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
    2348           0 :         AbortMessage();
    2349           0 :         return;
    2350             :     }
    2351       83896 :     if (mapArgs.count("-fuzzmessagestest"))
    2352           0 :         Fuzz(GetArg("-fuzzmessagestest", 10));
    2353             : 
    2354       41948 :     if (ssSend.size() == 0)
    2355             :     {
    2356           0 :         LEAVE_CRITICAL_SECTION(cs_vSend);
    2357             :         return;
    2358             :     }
    2359             :     // Set the size
    2360       41948 :     unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
    2361       41948 :     WriteLE32((uint8_t*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize);
    2362             : 
    2363             :     // Set the checksum
    2364       83896 :     uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());
    2365       20974 :     unsigned int nChecksum = 0;
    2366             :     memcpy(&nChecksum, &hash, sizeof(nChecksum));
    2367       41948 :     assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
    2368       41948 :     memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
    2369             : 
    2370       20974 :     LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
    2371             : 
    2372       62922 :     std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
    2373       20974 :     ssSend.GetAndClear(*it);
    2374       41948 :     nSendSize += (*it).size();
    2375             : 
    2376             :     // If write queue empty, attempt "optimistic write"
    2377       41948 :     if (it == vSendMsg.begin())
    2378       20971 :         SocketSendData(this);
    2379             : 
    2380       20974 :     LEAVE_CRITICAL_SECTION(cs_vSend);
    2381             : }
    2382             : 
    2383             : //
    2384             : // CBanDB
    2385             : //
    2386             : 
    2387         118 : CBanDB::CBanDB()
    2388             : {
    2389         354 :     pathBanlist = GetDataDir() / "banlist.dat";
    2390         118 : }
    2391             : 
    2392          24 : bool CBanDB::Write(const banmap_t& banSet)
    2393             : {
    2394             :     // Generate random temporary filename
    2395          24 :     unsigned short randv = 0;
    2396          24 :     GetRandBytes((unsigned char*)&randv, sizeof(randv));
    2397          24 :     std::string tmpfn = strprintf("banlist.dat.%04x", randv);
    2398             : 
    2399             :     // serialize banlist, checksum data up to that point, then append csum
    2400             :     CDataStream ssBanlist(SER_DISK, CLIENT_VERSION);
    2401          96 :     ssBanlist << FLATDATA(Params().MessageStart());
    2402             :     ssBanlist << banSet;
    2403          24 :     uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end());
    2404             :     ssBanlist << hash;
    2405             : 
    2406             :     // open temp output file, and associate with CAutoFile
    2407          48 :     boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
    2408          48 :     FILE *file = fopen(pathTmp.string().c_str(), "wb");
    2409             :     CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
    2410          24 :     if (fileout.IsNull())
    2411           0 :         return error("%s: Failed to open file %s", __func__, pathTmp.string());
    2412             : 
    2413             :     // Write and commit header, data
    2414             :     try {
    2415          24 :         fileout << ssBanlist;
    2416             :     }
    2417           0 :     catch (const std::exception& e) {
    2418           0 :         return error("%s: Serialize or I/O error - %s", __func__, e.what());
    2419             :     }
    2420          24 :     FileCommit(fileout.Get());
    2421          24 :     fileout.fclose();
    2422             : 
    2423             :     // replace existing banlist.dat, if any, with new banlist.dat.XXXX
    2424          96 :     if (!RenameOver(pathTmp, pathBanlist))
    2425           0 :         return error("%s: Rename-into-place failed", __func__);
    2426             : 
    2427             :     return true;
    2428             : }
    2429             : 
    2430          94 : bool CBanDB::Read(banmap_t& banSet)
    2431             : {
    2432             :     // open input file, and associate with CAutoFile
    2433         282 :     FILE *file = fopen(pathBanlist.string().c_str(), "rb");
    2434             :     CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
    2435          94 :     if (filein.IsNull())
    2436         186 :         return error("%s: Failed to open file %s", __func__, pathBanlist.string());
    2437             : 
    2438             :     // use file size to size memory buffer
    2439           2 :     uint64_t fileSize = boost::filesystem::file_size(pathBanlist);
    2440           1 :     uint64_t dataSize = 0;
    2441             :     // Don't try to resize to a negative number if file is small
    2442           1 :     if (fileSize >= sizeof(uint256))
    2443           1 :         dataSize = fileSize - sizeof(uint256);
    2444             :     vector<unsigned char> vchData;
    2445           1 :     vchData.resize(dataSize);
    2446             :     uint256 hashIn;
    2447             : 
    2448             :     // read data and checksum from file
    2449             :     try {
    2450           1 :         filein.read((char *)&vchData[0], dataSize);
    2451           1 :         filein >> hashIn;
    2452             :     }
    2453           0 :     catch (const std::exception& e) {
    2454           0 :         return error("%s: Deserialize or I/O error - %s", __func__, e.what());
    2455             :     }
    2456           1 :     filein.fclose();
    2457             : 
    2458             :     CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION);
    2459             : 
    2460             :     // verify stored checksum matches input data
    2461           1 :     uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end());
    2462           1 :     if (hashIn != hashTmp)
    2463           0 :         return error("%s: Checksum mismatch, data corrupted", __func__);
    2464             : 
    2465             :     unsigned char pchMsgTmp[4];
    2466             :     try {
    2467             :         // de-serialize file header (network specific magic number) and ..
    2468           1 :         ssBanlist >> FLATDATA(pchMsgTmp);
    2469             : 
    2470             :         // ... verify the network matches ours
    2471           2 :         if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
    2472           0 :             return error("%s: Invalid network magic number", __func__);
    2473             :         
    2474             :         // de-serialize address data into one CAddrMan object
    2475             :         ssBanlist >> banSet;
    2476             :     }
    2477           0 :     catch (const std::exception& e) {
    2478           0 :         return error("%s: Deserialize or I/O error - %s", __func__, e.what());
    2479             :     }
    2480             :     
    2481             :     return true;
    2482             : }
    2483             : 
    2484          24 : void DumpBanlist()
    2485             : {
    2486          24 :     int64_t nStart = GetTimeMillis();
    2487             : 
    2488          24 :     CNode::SweepBanned(); //clean unused entries (if bantime has expired)
    2489             : 
    2490          24 :     CBanDB bandb;
    2491             :     banmap_t banmap;
    2492          24 :     CNode::GetBanned(banmap);
    2493          24 :     bandb.Write(banmap);
    2494             : 
    2495             :     LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat  %dms\n",
    2496          48 :              banmap.size(), GetTimeMillis() - nStart);
    2497         312 : }

Generated by: LCOV version 1.11