@ -621,6 +621,7 @@ void CNode::copyStats(CNodeStats &stats)
X ( nVersion ) ;
X ( nVersion ) ;
X ( cleanSubVer ) ;
X ( cleanSubVer ) ;
X ( fInbound ) ;
X ( fInbound ) ;
X ( fAddnode ) ;
X ( nStartingHeight ) ;
X ( nStartingHeight ) ;
X ( nSendBytes ) ;
X ( nSendBytes ) ;
X ( mapSendBytesPerMsgCmd ) ;
X ( mapSendBytesPerMsgCmd ) ;
@ -1631,7 +1632,12 @@ void CConnman::ThreadOpenConnections()
{
{
LOCK ( cs_vNodes ) ;
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes ) {
BOOST_FOREACH ( CNode * pnode , vNodes ) {
if ( ! pnode - > fInbound ) {
if ( ! pnode - > fInbound & & ! pnode - > fAddnode ) {
// Netgroups for inbound and addnode peers are not excluded because our goal here
// is to not use multiple of our limited outbound slots on a single netgroup
// but inbound and addnode peers do not use our outbound slots. Inbound peers
// also have the added issue that they're attacker controlled and could be used
// to prevent us from connecting to particular hosts if we used them here.
setConnected . insert ( pnode - > addr . GetGroup ( ) ) ;
setConnected . insert ( pnode - > addr . GetGroup ( ) ) ;
nOutbound + + ;
nOutbound + + ;
}
}
@ -1776,27 +1782,35 @@ void CConnman::ThreadOpenAddedConnections()
vAddedNodes = mapMultiArgs . at ( " -addnode " ) ;
vAddedNodes = mapMultiArgs . at ( " -addnode " ) ;
}
}
for ( unsigned int i = 0 ; true ; i + + )
while ( true )
{
{
CSemaphoreGrant grant ( * semAddnode ) ;
std : : vector < AddedNodeInfo > vInfo = GetAddedNodeInfo ( ) ;
std : : vector < AddedNodeInfo > vInfo = GetAddedNodeInfo ( ) ;
bool tried = false ;
for ( const AddedNodeInfo & info : vInfo ) {
for ( const AddedNodeInfo & info : vInfo ) {
if ( ! info . fConnected ) {
if ( ! info . fConnected ) {
CSemaphoreGrant grant ( * semOutbound ) ;
if ( ! grant . TryAcquire ( ) ) {
// If we've used up our semaphore and need a new one, lets not wait here since while we are waiting
// the addednodeinfo state might change.
break ;
}
// If strAddedNode is an IP/port, decode it immediately, so
// If strAddedNode is an IP/port, decode it immediately, so
// OpenNetworkConnection can detect existing connections to that IP/port.
// OpenNetworkConnection can detect existing connections to that IP/port.
tried = true ;
CService service ( LookupNumeric ( info . strAddedNode . c_str ( ) , Params ( ) . GetDefaultPort ( ) ) ) ;
CService service ( LookupNumeric ( info . strAddedNode . c_str ( ) , Params ( ) . GetDefaultPort ( ) ) ) ;
OpenNetworkConnection ( CAddress ( service , NODE_NONE ) , false , & grant , info . strAddedNode . c_str ( ) , false ) ;
OpenNetworkConnection ( CAddress ( service , NODE_NONE ) , false , & grant , info . strAddedNode . c_str ( ) , false , false , true ) ;
if ( ! interruptNet . sleep_for ( std : : chrono : : milliseconds ( 500 ) ) )
if ( ! interruptNet . sleep_for ( std : : chrono : : milliseconds ( 500 ) ) )
return ;
return ;
}
}
}
}
if ( ! interruptNet . sleep_for ( std : : chrono : : minutes ( 2 ) ) )
// Retry every 60 seconds if a connection was attempted, otherwise two seconds
if ( ! interruptNet . sleep_for ( std : : chrono : : seconds ( tried ? 60 : 2 ) ) ) ;
return ;
return ;
}
}
}
}
// if successful, this moves the passed grant to the constructed node
// if successful, this moves the passed grant to the constructed node
bool CConnman : : OpenNetworkConnection ( const CAddress & addrConnect , bool fCountFailure , CSemaphoreGrant * grantOutbound , const char * pszDest , bool fOneShot , bool fFeeler )
bool CConnman : : OpenNetworkConnection ( const CAddress & addrConnect , bool fCountFailure , CSemaphoreGrant * grantOutbound , const char * pszDest , bool fOneShot , bool fFeeler , bool fAddnode )
{
{
//
//
// Initiate outbound network connection
// Initiate outbound network connection
@ -1825,6 +1839,8 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
pnode - > fOneShot = true ;
pnode - > fOneShot = true ;
if ( fFeeler )
if ( fFeeler )
pnode - > fFeeler = true ;
pnode - > fFeeler = true ;
if ( fAddnode )
pnode - > fAddnode = true ;
return true ;
return true ;
}
}
@ -2076,8 +2092,10 @@ CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSe
nSendBufferMaxSize = 0 ;
nSendBufferMaxSize = 0 ;
nReceiveFloodSize = 0 ;
nReceiveFloodSize = 0 ;
semOutbound = NULL ;
semOutbound = NULL ;
semAddnode = NULL ;
nMaxConnections = 0 ;
nMaxConnections = 0 ;
nMaxOutbound = 0 ;
nMaxOutbound = 0 ;
nMaxAddnode = 0 ;
nBestHeight = 0 ;
nBestHeight = 0 ;
clientInterface = NULL ;
clientInterface = NULL ;
flagInterruptMsgProc = false ;
flagInterruptMsgProc = false ;
@ -2099,6 +2117,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
nLocalServices = connOptions . nLocalServices ;
nLocalServices = connOptions . nLocalServices ;
nMaxConnections = connOptions . nMaxConnections ;
nMaxConnections = connOptions . nMaxConnections ;
nMaxOutbound = std : : min ( ( connOptions . nMaxOutbound ) , nMaxConnections ) ;
nMaxOutbound = std : : min ( ( connOptions . nMaxOutbound ) , nMaxConnections ) ;
nMaxAddnode = connOptions . nMaxAddnode ;
nMaxFeeler = connOptions . nMaxFeeler ;
nMaxFeeler = connOptions . nMaxFeeler ;
nSendBufferMaxSize = connOptions . nSendBufferMaxSize ;
nSendBufferMaxSize = connOptions . nSendBufferMaxSize ;
@ -2151,6 +2170,10 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
// initialize semaphore
// initialize semaphore
semOutbound = new CSemaphore ( std : : min ( ( nMaxOutbound + nMaxFeeler ) , nMaxConnections ) ) ;
semOutbound = new CSemaphore ( std : : min ( ( nMaxOutbound + nMaxFeeler ) , nMaxConnections ) ) ;
}
}
if ( semAddnode = = NULL ) {
// initialize semaphore
semAddnode = new CSemaphore ( nMaxAddnode ) ;
}
//
//
// Start threads
// Start threads
@ -2227,6 +2250,10 @@ void CConnman::Stop()
if ( threadSocketHandler . joinable ( ) )
if ( threadSocketHandler . joinable ( ) )
threadSocketHandler . join ( ) ;
threadSocketHandler . join ( ) ;
if ( semAddnode )
for ( int i = 0 ; i < nMaxAddnode ; i + + )
semOutbound - > post ( ) ;
if ( fAddressesInitialized )
if ( fAddressesInitialized )
{
{
DumpData ( ) ;
DumpData ( ) ;
@ -2254,6 +2281,8 @@ void CConnman::Stop()
vhListenSocket . clear ( ) ;
vhListenSocket . clear ( ) ;
delete semOutbound ;
delete semOutbound ;
semOutbound = NULL ;
semOutbound = NULL ;
delete semAddnode ;
semAddnode = NULL ;
}
}
void CConnman : : DeleteNode ( CNode * pnode )
void CConnman : : DeleteNode ( CNode * pnode )
@ -2554,6 +2583,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
strSubVer = " " ;
strSubVer = " " ;
fWhitelisted = false ;
fWhitelisted = false ;
fOneShot = false ;
fOneShot = false ;
fAddnode = false ;
fClient = false ; // set by version message
fClient = false ; // set by version message
fFeeler = false ;
fFeeler = false ;
fSuccessfullyConnected = false ;
fSuccessfullyConnected = false ;