@ -56,7 +56,6 @@
# endif
# endif
using namespace std ;
namespace {
const int MAX_OUTBOUND_CONNECTIONS = 8 ;
@ -78,7 +77,7 @@ bool fDiscover = true;
bool fListen = true ;
uint64_t nLocalServices = NODE_NETWORK ;
CCriticalSection cs_mapLocalHost ;
map < CNetAddr , LocalServiceInfo > mapLocalHost ;
std : : map < CNetAddr , LocalServiceInfo > mapLocalHost ;
static bool vfLimited [ NET_MAX ] = { } ;
static CNode * pnodeLocalHost = NULL ;
uint64_t nLocalHostNonce = 0 ;
@ -88,20 +87,17 @@ int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
bool fAddressesInitialized = false ;
std : : string strSubVersion ;
vector < CNode * > vNodes ;
std : : vector < CNode * > vNodes ;
CCriticalSection cs_vNodes ;
map < uint256 , CTransaction > mapRelay ;
deque < pair < int64_t , uint256 > > vRelayExpiration ;
std : : map < uint256 , CTransaction > mapRelay ;
std : : deque < std : : pair < int64_t , uint256 > > vRelayExpiration ;
CCriticalSection cs_mapRelay ;
limitedmap < uint256 , int64_t > mapAlreadyAskedFor ( MAX_INV_SZ ) ;
static deque< string > vOneShots ;
static std: : deque< std : : string > vOneShots ;
CCriticalSection cs_vOneShots ;
set < CNetAddr > setservAddNodeAddresses ;
CCriticalSection cs_setservAddNodeAddresses ;
vector < std : : string > vAddedNodes ;
std : : vector < std : : string > vAddedNodes ;
CCriticalSection cs_vAddedNodes ;
NodeId nLastNodeId = 0 ;
@ -135,7 +131,7 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
int nBestReachability = - 1 ;
{
LOCK ( cs_mapLocalHost ) ;
for ( map< CNetAddr , LocalServiceInfo > : : iterator it = mapLocalHost . begin ( ) ; it ! = mapLocalHost . end ( ) ; it + + )
for ( std: : map< CNetAddr , LocalServiceInfo > : : iterator it = mapLocalHost . begin ( ) ; it ! = mapLocalHost . end ( ) ; it + + )
{
int nScore = ( * it ) . second . nScore ;
int nReachability = ( * it ) . first . GetReachabilityFrom ( paddrPeer ) ;
@ -426,6 +422,26 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
return NULL ;
}
static void DumpBanlist ( )
{
CNode : : SweepBanned ( ) ; // clean unused entries (if bantime has expired)
if ( ! CNode : : BannedSetIsDirty ( ) )
return ;
int64_t nStart = GetTimeMillis ( ) ;
CBanDB bandb ;
banmap_t banmap ;
CNode : : SetBannedSetDirty ( false ) ;
CNode : : GetBanned ( banmap ) ;
if ( ! bandb . Write ( banmap ) )
CNode : : SetBannedSetDirty ( true ) ;
LogPrint ( " net " , " Flushed %d banned node ips/subnets to banlist.dat %dms \n " ,
banmap . size ( ) , GetTimeMillis ( ) - nStart ) ;
}
void CNode : : CloseSocketDisconnect ( )
{
fDisconnect = true ;
@ -443,7 +459,7 @@ void CNode::CloseSocketDisconnect()
void CNode : : PushVersion ( )
{
int nBestHeight = g_signals . GetHeight ( ) . get_value_or ( 0 ) ;
int nBestHeight = GetNodeSignals( ) . GetHeight ( ) . get_value_or ( 0 ) ;
int64_t nTime = ( fInbound ? GetAdjustedTime ( ) : GetTime ( ) ) ;
CAddress addrYou = ( addr . IsRoutable ( ) & & ! IsProxy ( addr ) ? addr : CAddress ( CService ( " 0.0.0.0 " , 0 ) ) ) ;
@ -467,9 +483,13 @@ bool CNode::setBannedIsDirty;
void CNode : : ClearBanned ( )
{
LOCK ( cs_setBanned ) ;
setBanned . clear ( ) ;
setBannedIsDirty = true ;
{
LOCK ( cs_setBanned ) ;
setBanned . clear ( ) ;
setBannedIsDirty = true ;
}
DumpBanlist ( ) ; //store banlist to disk
uiInterface . BannedListChanged ( ) ;
}
bool CNode : : IsBanned ( CNetAddr ip )
@ -520,11 +540,25 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti
}
banEntry . nBanUntil = ( sinceUnixEpoch ? 0 : GetTime ( ) ) + bantimeoffset ;
LOCK ( cs_setBanned ) ;
if ( setBanned [ subNet ] . nBanUntil < banEntry . nBanUntil )
setBanned [ subNet ] = banEntry ;
setBannedIsDirty = true ;
{
LOCK ( cs_setBanned ) ;
if ( setBanned [ subNet ] . nBanUntil < banEntry . nBanUntil ) {
setBanned [ subNet ] = banEntry ;
setBannedIsDirty = true ;
}
else
return ;
}
uiInterface . BannedListChanged ( ) ;
{
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes ) {
if ( subNet . Match ( ( CNetAddr ) pnode - > addr ) )
pnode - > fDisconnect = true ;
}
}
if ( banReason = = BanReasonManuallyAdded )
DumpBanlist ( ) ; //store banlist to disk immediately if user requested ban
}
bool CNode : : Unban ( const CNetAddr & addr ) {
@ -533,13 +567,15 @@ bool CNode::Unban(const CNetAddr &addr) {
}
bool CNode : : Unban ( const CSubNet & subNet ) {
LOCK ( cs_setBanned ) ;
if ( setBanned . erase ( subNet ) )
{
LOCK ( cs_setBanned ) ;
if ( ! setBanned . erase ( subNet ) )
return false ;
setBannedIsDirty = true ;
return true ;
}
return false ;
uiInterface . BannedListChanged ( ) ;
DumpBanlist ( ) ; //store banlist to disk immediately
return true ;
}
void CNode : : GetBanned ( banmap_t & banMap )
@ -796,53 +832,24 @@ void SocketSendData(CNode *pnode)
pnode - > vSendMsg . erase ( pnode - > vSendMsg . begin ( ) , it ) ;
}
static list< CNode * > vNodesDisconnected ;
static std: : list< CNode * > vNodesDisconnected ;
class CNodeRef {
public :
CNodeRef ( CNode * pnode ) : _pnode ( pnode ) {
LOCK ( cs_vNodes ) ;
_pnode - > AddRef ( ) ;
}
~ CNodeRef ( ) {
LOCK ( cs_vNodes ) ;
_pnode - > Release ( ) ;
}
CNode & operator * ( ) const { return * _pnode ; } ;
CNode * operator - > ( ) const { return _pnode ; } ;
CNodeRef & operator = ( const CNodeRef & other )
{
if ( this ! = & other ) {
LOCK ( cs_vNodes ) ;
_pnode - > Release ( ) ;
_pnode = other . _pnode ;
_pnode - > AddRef ( ) ;
}
return * this ;
}
CNodeRef ( const CNodeRef & other ) :
_pnode ( other . _pnode )
{
LOCK ( cs_vNodes ) ;
_pnode - > AddRef ( ) ;
}
private :
CNode * _pnode ;
struct NodeEvictionCandidate
{
NodeId id ;
int64_t nTimeConnected ;
int64_t nMinPingUsecTime ;
CAddress addr ;
} ;
static bool ReverseCompareNodeMinPingTime ( const CNodeRef & a , const CNodeRef & b )
static bool ReverseCompareNodeMinPingTime ( const NodeEvictionCandidate & a , const NodeEvictionCandidate & b )
{
return a - > nMinPingUsecTime > b - > nMinPingUsecTime ;
return a . nMinPingUsecTime > b . nMinPingUsecTime ;
}
static bool ReverseCompareNodeTimeConnected ( const CNodeRef & a , const CNodeRef & b )
static bool ReverseCompareNodeTimeConnected ( const NodeEvictionCandidate & a , const NodeEvictionCandidate & b )
{
return a - > nTimeConnected > b - > nTimeConnected ;
return a . nTimeConnected > b . nTimeConnected ;
}
class CompareNetGroupKeyed
@ -855,14 +862,14 @@ public:
GetRandBytes ( vchSecretKey . data ( ) , vchSecretKey . size ( ) ) ;
}
bool operator ( ) ( const CNodeRef & a , const CNodeRef & b )
bool operator ( ) ( const NodeEvictionCandidate & a , const NodeEvictionCandidate & b )
{
std : : vector < unsigned char > vchGroupA , vchGroupB ;
CSHA256 hashA , hashB ;
std : : vector < unsigned char > vchA ( 32 ) , vchB ( 32 ) ;
vchGroupA = a - > addr . GetGroup ( ) ;
vchGroupB = b - > addr . GetGroup ( ) ;
vchGroupA = a . addr . GetGroup ( ) ;
vchGroupB = b . addr . GetGroup ( ) ;
hashA . Write ( begin_ptr ( vchGroupA ) , vchGroupA . size ( ) ) ;
hashB . Write ( begin_ptr ( vchGroupB ) , vchGroupB . size ( ) ) ;
@ -886,7 +893,7 @@ public:
* simultaneously better at all of them than honest peers .
*/
static bool AttemptToEvictConnection ( bool fPreferNewConnection ) {
std : : vector < CNodeRef > vEvictionCandidates ;
std : : vector < NodeEvictionCandidate > vEvictionCandidates ;
{
LOCK ( cs_vNodes ) ;
@ -897,7 +904,8 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
continue ;
if ( node - > fDisconnect )
continue ;
vEvictionCandidates . push_back ( CNodeRef ( node ) ) ;
NodeEvictionCandidate candidate = { node - > id , node - > nTimeConnected , node - > nMinPingUsecTime , node - > addr } ;
vEvictionCandidates . push_back ( candidate ) ;
}
}
@ -932,16 +940,16 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
std : : vector < unsigned char > naMostConnections ;
unsigned int nMostConnections = 0 ;
int64_t nMostConnectionsTime = 0 ;
std : : map < std : : vector < unsigned char > , std : : vector < CNodeRef > > mapAddrCounts ;
BOOST_FOREACH ( const CNodeRef & node , vEvictionCandidates ) {
mapAddrCounts [ node - > addr . GetGroup ( ) ] . push_back ( node ) ;
int64_t grouptime = mapAddrCounts [ node - > addr . GetGroup ( ) ] [ 0 ] - > nTimeConnected ;
size_t groupsize = mapAddrCounts [ node - > addr . GetGroup ( ) ] . size ( ) ;
std : : map < std : : vector < unsigned char > , std : : vector < NodeEvictionCandidate > > mapAddrCounts ;
BOOST_FOREACH ( const NodeEvictionCandidate & node , vEvictionCandidates ) {
mapAddrCounts [ node . addr . GetGroup ( ) ] . push_back ( node ) ;
int64_t grouptime = mapAddrCounts [ node . addr . GetGroup ( ) ] [ 0 ] . nTimeConnected ;
size_t groupsize = mapAddrCounts [ node . addr . GetGroup ( ) ] . size ( ) ;
if ( groupsize > nMostConnections | | ( groupsize = = nMostConnections & & grouptime > nMostConnectionsTime ) ) {
nMostConnections = groupsize ;
nMostConnectionsTime = grouptime ;
naMostConnections = node - > addr . GetGroup ( ) ;
naMostConnections = node . addr . GetGroup ( ) ;
}
}
@ -956,9 +964,15 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
return false ;
// Disconnect from the network group with the most connections
vEvictionCandidates [ 0 ] - > fDisconnect = true ;
return true ;
NodeId evicted = vEvictionCandidates . front ( ) . id ;
LOCK ( cs_vNodes ) ;
for ( std : : vector < CNode * > : : const_iterator it ( vNodes . begin ( ) ) ; it ! = vNodes . end ( ) ; + + it ) {
if ( ( * it ) - > GetId ( ) = = evicted ) {
( * it ) - > fDisconnect = true ;
return true ;
}
}
return false ;
}
static void AcceptConnection ( const ListenSocket & hListenSocket ) {
@ -1045,7 +1059,7 @@ void ThreadSocketHandler()
{
LOCK ( cs_vNodes ) ;
// Disconnect unused nodes
vector< CNode * > vNodesCopy = vNodes ;
std: : vector< CNode * > vNodesCopy = vNodes ;
BOOST_FOREACH ( CNode * pnode , vNodesCopy )
{
if ( pnode - > fDisconnect | |
@ -1069,7 +1083,7 @@ void ThreadSocketHandler()
}
{
// Delete disconnected nodes
list< CNode * > vNodesDisconnectedCopy = vNodesDisconnected ;
std: : list< CNode * > vNodesDisconnectedCopy = vNodesDisconnected ;
BOOST_FOREACH ( CNode * pnode , vNodesDisconnectedCopy )
{
// wait until threads are done using it
@ -1120,7 +1134,7 @@ void ThreadSocketHandler()
BOOST_FOREACH ( const ListenSocket & hListenSocket , vhListenSocket ) {
FD_SET ( hListenSocket . socket , & fdsetRecv ) ;
hSocketMax = max( hSocketMax , hListenSocket . socket ) ;
hSocketMax = std: : max( hSocketMax , hListenSocket . socket ) ;
have_fds = true ;
}
@ -1131,7 +1145,7 @@ void ThreadSocketHandler()
if ( pnode - > hSocket = = INVALID_SOCKET )
continue ;
FD_SET ( pnode - > hSocket , & fdsetError ) ;
hSocketMax = max( hSocketMax , pnode - > hSocket ) ;
hSocketMax = std: : max( hSocketMax , pnode - > hSocket ) ;
have_fds = true ;
// Implement the following logic:
@ -1198,7 +1212,7 @@ void ThreadSocketHandler()
//
// Service each socket
//
vector< CNode * > vNodesCopy ;
std: : vector< CNode * > vNodesCopy ;
{
LOCK ( cs_vNodes ) ;
vNodesCopy = vNodes ;
@ -1355,7 +1369,7 @@ void ThreadMapPort()
}
}
st ring strDesc = " Bitcoin " + FormatFullVersion ( ) ;
st d: : st ring strDesc = " Bitcoin " + FormatFullVersion ( ) ;
try {
while ( true ) {
@ -1441,7 +1455,7 @@ void ThreadDNSAddressSeed()
}
}
const vector< CDNSSeedData > & vSeeds = Params ( ) . DNSSeeds ( ) ;
const std: : vector< CDNSSeedData > & vSeeds = Params ( ) . DNSSeeds ( ) ;
int found = 0 ;
LogPrintf ( " Loading addresses from DNS seeds (could take a while) \n " ) ;
@ -1450,8 +1464,8 @@ void ThreadDNSAddressSeed()
if ( HaveNameProxy ( ) ) {
AddOneShot ( seed . host ) ;
} else {
vector< CNetAddr > vIPs ;
vector< CAddress > vAdd ;
std: : vector< CNetAddr > vIPs ;
std: : vector< CAddress > vAdd ;
if ( LookupHost ( seed . host . c_str ( ) , vIPs , 0 , true ) )
{
BOOST_FOREACH ( const CNetAddr & ip , vIPs )
@ -1508,7 +1522,7 @@ void DumpData()
void static ProcessOneShot ( )
{
st ring strDest ;
st d: : st ring strDest ;
{
LOCK ( cs_vOneShots ) ;
if ( vOneShots . empty ( ) )
@ -1574,7 +1588,7 @@ void ThreadOpenConnections()
// Only connect out to one peer per network group (/16 for IPv4).
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
int nOutbound = 0 ;
s et< vector < unsigned char > > setConnected ;
s td: : s et< std : : vector < unsigned char > > setConnected ;
{
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes ) {
@ -1632,7 +1646,7 @@ void ThreadOpenAddedConnections()
if ( HaveNameProxy ( ) ) {
while ( true ) {
list< string > lAddresses ( 0 ) ;
std: : list< std : : string > lAddresses ( 0 ) ;
{
LOCK ( cs_vAddedNodes ) ;
BOOST_FOREACH ( const std : : string & strAddNode , vAddedNodes )
@ -1650,32 +1664,25 @@ void ThreadOpenAddedConnections()
for ( unsigned int i = 0 ; true ; i + + )
{
list< string > lAddresses ( 0 ) ;
std: : list< std : : string > lAddresses ( 0 ) ;
{
LOCK ( cs_vAddedNodes ) ;
BOOST_FOREACH ( const std : : string & strAddNode , vAddedNodes )
lAddresses . push_back ( strAddNode ) ;
}
list< vector < CService > > lservAddressesToAdd ( 0 ) ;
std: : list< std : : vector < CService > > lservAddressesToAdd ( 0 ) ;
BOOST_FOREACH ( const std : : string & strAddNode , lAddresses ) {
vector< CService > vservNode ( 0 ) ;
std: : vector< CService > vservNode ( 0 ) ;
if ( Lookup ( strAddNode . c_str ( ) , vservNode , Params ( ) . GetDefaultPort ( ) , fNameLookup , 0 ) )
{
lservAddressesToAdd . push_back ( vservNode ) ;
{
LOCK ( cs_setservAddNodeAddresses ) ;
BOOST_FOREACH ( const CService & serv , vservNode )
setservAddNodeAddresses . insert ( serv ) ;
}
}
}
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
// (keeping in mind that addnode entries can have many IPs if fNameLookup)
{
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes )
for ( list< vector < CService > > : : iterator it = lservAddressesToAdd . begin ( ) ; it ! = lservAddressesToAdd . end ( ) ; it + + )
for ( std: : list< std : : vector < CService > > : : iterator it = lservAddressesToAdd . begin ( ) ; it ! = lservAddressesToAdd . end ( ) ; it + + )
BOOST_FOREACH ( const CService & addrNode , * ( it ) )
if ( pnode - > addr = = addrNode )
{
@ -1684,7 +1691,7 @@ void ThreadOpenAddedConnections()
break ;
}
}
BOOST_FOREACH ( vector< CService > & vserv , lservAddressesToAdd )
BOOST_FOREACH ( std: : vector< CService > & vserv , lservAddressesToAdd )
{
CSemaphoreGrant grant ( * semOutbound ) ;
OpenNetworkConnection ( CAddress ( vserv [ i % vserv . size ( ) ] ) , & grant ) ;
@ -1731,7 +1738,7 @@ void ThreadMessageHandler()
while ( true )
{
vector< CNode * > vNodesCopy ;
std: : vector< CNode * > vNodesCopy ;
{
LOCK ( cs_vNodes ) ;
vNodesCopy = vNodes ;
@ -1752,7 +1759,7 @@ void ThreadMessageHandler()
TRY_LOCK ( pnode - > cs_vRecvMsg , lockRecv ) ;
if ( lockRecv )
{
if ( ! g_signals . ProcessMessages ( pnode ) )
if ( ! GetNodeSignals( ) . ProcessMessages ( pnode ) )
pnode - > CloseSocketDisconnect ( ) ;
if ( pnode - > nSendSize < SendBufferSize ( ) )
@ -1770,7 +1777,7 @@ void ThreadMessageHandler()
{
TRY_LOCK ( pnode - > cs_vSend , lockSend ) ;
if ( lockSend )
g_signals . SendMessages ( pnode ) ;
GetNodeSignals( ) . SendMessages ( pnode ) ;
}
boost : : this_thread : : interruption_point ( ) ;
}
@ -1791,7 +1798,7 @@ void ThreadMessageHandler()
bool BindListenPort ( const CService & addrBind , st ring& strError , bool fWhitelisted )
bool BindListenPort ( const CService & addrBind , st d: : st ring& strError , bool fWhitelisted )
{
strError = " " ;
int nOne = 1 ;
@ -1899,7 +1906,7 @@ void static Discover(boost::thread_group& threadGroup)
char pszHostName [ 256 ] = " " ;
if ( gethostname ( pszHostName , sizeof ( pszHostName ) ) ! = SOCKET_ERROR )
{
vector< CNetAddr > vaddr ;
std: : vector< CNetAddr > vaddr ;
if ( LookupHost ( pszHostName , vaddr , 0 , true ) )
{
BOOST_FOREACH ( const CNetAddr & addr , vaddr )
@ -2300,7 +2307,7 @@ bool CAddrDB::Read(CAddrMan& addr)
// Don't try to resize to a negative number if file is small
if ( fileSize > = sizeof ( uint256 ) )
dataSize = fileSize - sizeof ( uint256 ) ;
vector< unsigned char > vchData ;
std: : vector< unsigned char > vchData ;
vchData . resize ( dataSize ) ;
uint256 hashIn ;
@ -2587,7 +2594,7 @@ bool CBanDB::Read(banmap_t& banSet)
// Don't try to resize to a negative number if file is small
if ( fileSize > = sizeof ( uint256 ) )
dataSize = fileSize - sizeof ( uint256 ) ;
vector< unsigned char > vchData ;
std: : vector< unsigned char > vchData ;
vchData . resize ( dataSize ) ;
uint256 hashIn ;
@ -2627,26 +2634,6 @@ bool CBanDB::Read(banmap_t& banSet)
return true ;
}
void DumpBanlist ( )
{
CNode : : SweepBanned ( ) ; // clean unused entries (if bantime has expired)
if ( ! CNode : : BannedSetIsDirty ( ) )
return ;
int64_t nStart = GetTimeMillis ( ) ;
CBanDB bandb ;
banmap_t banmap ;
CNode : : SetBannedSetDirty ( false ) ;
CNode : : GetBanned ( banmap ) ;
if ( ! bandb . Write ( banmap ) )
CNode : : SetBannedSetDirty ( true ) ;
LogPrint ( " net " , " Flushed %d banned node ips/subnets to banlist.dat %dms \n " ,
banmap . size ( ) , GetTimeMillis ( ) - nStart ) ;
}
int64_t PoissonNextSend ( int64_t nNow , int average_interval_seconds ) {
return nNow + ( int64_t ) ( log1p ( GetRand ( 1ULL < < 48 ) * - 0.0000000000000035527136788 /* -1/2^48 */ ) * average_interval_seconds * - 1000000.0 + 0.5 ) ;
}