4343// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
4444#define DUMP_ADDRESSES_INTERVAL 900
4545
46+ // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
47+ #define FEELER_SLEEP_WINDOW 1
48+
4649#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
4750#define MSG_NOSIGNAL 0
4851#endif
6164
6265namespace {
6366 const int MAX_OUTBOUND_CONNECTIONS = 8 ;
67+ const int MAX_FEELER_CONNECTIONS = 1 ;
6468
6569 struct ListenSocket {
6670 SOCKET socket;
@@ -1017,7 +1021,8 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
10171021 SOCKET hSocket = accept (hListenSocket.socket , (struct sockaddr *)&sockaddr, &len);
10181022 CAddress addr;
10191023 int nInbound = 0 ;
1020- int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS;
1024+ int nMaxInbound = nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS);
1025+ assert (nMaxInbound > 0 );
10211026
10221027 if (hSocket != INVALID_SOCKET)
10231028 if (!addr.SetSockAddr ((const struct sockaddr *)&sockaddr))
@@ -1613,6 +1618,9 @@ void ThreadOpenConnections()
16131618
16141619 // Initiate network connections
16151620 int64_t nStart = GetTime ();
1621+
1622+ // Minimum time before next feeler connection (in microseconds).
1623+ int64_t nNextFeeler = PoissonNextSend (nStart*1000 *1000 , FEELER_INTERVAL);
16161624 while (true )
16171625 {
16181626 ProcessOneShot ();
@@ -1652,13 +1660,36 @@ void ThreadOpenConnections()
16521660 }
16531661 }
16541662 }
1663+ assert (nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS));
16551664
1656- int64_t nANow = GetAdjustedTime ();
1665+ // Feeler Connections
1666+ //
1667+ // Design goals:
1668+ // * Increase the number of connectable addresses in the tried table.
1669+ //
1670+ // Method:
1671+ // * Choose a random address from new and attempt to connect to it if we can connect
1672+ // successfully it is added to tried.
1673+ // * Start attempting feeler connections only after node finishes making outbound
1674+ // connections.
1675+ // * Only make a feeler connection once every few minutes.
1676+ //
1677+ bool fFeeler = false ;
1678+ if (nOutbound >= MAX_OUTBOUND_CONNECTIONS) {
1679+ int64_t nTime = GetTimeMicros (); // The current time right now (in microseconds).
1680+ if (nTime > nNextFeeler) {
1681+ nNextFeeler = PoissonNextSend (nTime, FEELER_INTERVAL);
1682+ fFeeler = true ;
1683+ } else {
1684+ continue ;
1685+ }
1686+ }
16571687
1688+ int64_t nANow = GetAdjustedTime ();
16581689 int nTries = 0 ;
16591690 while (true )
16601691 {
1661- CAddrInfo addr = addrman.Select ();
1692+ CAddrInfo addr = addrman.Select (fFeeler );
16621693
16631694 // if we selected an invalid address, restart
16641695 if (!addr.IsValid () || setConnected.count (addr.GetGroup ()) || IsLocal (addr))
@@ -1694,8 +1725,17 @@ void ThreadOpenConnections()
16941725 break ;
16951726 }
16961727
1697- if (addrConnect.IsValid ())
1698- OpenNetworkConnection (addrConnect, (int )setConnected.size () >= std::min (nMaxConnections - 1 , 2 ), &grant);
1728+ if (addrConnect.IsValid ()) {
1729+
1730+ if (fFeeler ) {
1731+ // Add small amount of random noise before connection to avoid synchronization.
1732+ int randsleep = GetRandInt (FEELER_SLEEP_WINDOW * 1000 );
1733+ MilliSleep (randsleep);
1734+ LogPrint (" net" , " Making feeler connection to %s\n " , addrConnect.ToString ());
1735+ }
1736+
1737+ OpenNetworkConnection (addrConnect, (int )setConnected.size () >= std::min (nMaxConnections - 1 , 2 ), &grant, NULL , false , fFeeler );
1738+ }
16991739 }
17001740}
17011741
@@ -1777,7 +1817,7 @@ void ThreadOpenAddedConnections()
17771817}
17781818
17791819// if successful, this moves the passed grant to the constructed node
1780- bool OpenNetworkConnection (const CAddress& addrConnect, bool fCountFailure , CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot )
1820+ bool OpenNetworkConnection (const CAddress& addrConnect, bool fCountFailure , CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot , bool fFeeler )
17811821{
17821822 //
17831823 // Initiate outbound network connection
@@ -1801,6 +1841,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSem
18011841 pnode->fNetworkNode = true ;
18021842 if (fOneShot )
18031843 pnode->fOneShot = true ;
1844+ if (fFeeler )
1845+ pnode->fFeeler = true ;
18041846
18051847 return true ;
18061848}
@@ -2062,7 +2104,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
20622104
20632105 if (semOutbound == NULL ) {
20642106 // initialize semaphore
2065- int nMaxOutbound = std::min (MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
2107+ int nMaxOutbound = std::min (( MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS) , nMaxConnections);
20662108 semOutbound = new CSemaphore (nMaxOutbound);
20672109 }
20682110
@@ -2107,7 +2149,7 @@ bool StopNode()
21072149 LogPrintf (" StopNode()\n " );
21082150 MapPort (false );
21092151 if (semOutbound)
2110- for (int i=0 ; i<MAX_OUTBOUND_CONNECTIONS; i++)
2152+ for (int i=0 ; i<( MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS) ; i++)
21112153 semOutbound->post ();
21122154
21132155 if (fAddressesInitialized )
@@ -2448,6 +2490,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
24482490 fWhitelisted = false ;
24492491 fOneShot = false ;
24502492 fClient = false ; // set by version message
2493+ fFeeler = false ;
24512494 fInbound = fInboundIn ;
24522495 fNetworkNode = false ;
24532496 fSuccessfullyConnected = false ;
0 commit comments