43
43
// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
44
44
#define DUMP_ADDRESSES_INTERVAL 900
45
45
46
+ // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
47
+ #define FEELER_SLEEP_WINDOW 1
48
+
46
49
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
47
50
#define MSG_NOSIGNAL 0
48
51
#endif
61
64
62
65
namespace {
63
66
const int MAX_OUTBOUND_CONNECTIONS = 8 ;
67
+ const int MAX_FEELER_CONNECTIONS = 1 ;
64
68
65
69
struct ListenSocket {
66
70
SOCKET socket;
@@ -1017,7 +1021,8 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
1017
1021
SOCKET hSocket = accept (hListenSocket.socket , (struct sockaddr *)&sockaddr, &len);
1018
1022
CAddress addr;
1019
1023
int nInbound = 0 ;
1020
- int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS;
1024
+ int nMaxInbound = nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS);
1025
+ assert (nMaxInbound > 0 );
1021
1026
1022
1027
if (hSocket != INVALID_SOCKET)
1023
1028
if (!addr.SetSockAddr ((const struct sockaddr *)&sockaddr))
@@ -1613,6 +1618,9 @@ void ThreadOpenConnections()
1613
1618
1614
1619
// Initiate network connections
1615
1620
int64_t nStart = GetTime ();
1621
+
1622
+ // Minimum time before next feeler connection (in microseconds).
1623
+ int64_t nNextFeeler = PoissonNextSend (nStart*1000 *1000 , FEELER_INTERVAL);
1616
1624
while (true )
1617
1625
{
1618
1626
ProcessOneShot ();
@@ -1652,13 +1660,36 @@ void ThreadOpenConnections()
1652
1660
}
1653
1661
}
1654
1662
}
1663
+ assert (nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS));
1655
1664
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
+ }
1657
1687
1688
+ int64_t nANow = GetAdjustedTime ();
1658
1689
int nTries = 0 ;
1659
1690
while (true )
1660
1691
{
1661
- CAddrInfo addr = addrman.Select ();
1692
+ CAddrInfo addr = addrman.Select (fFeeler );
1662
1693
1663
1694
// if we selected an invalid address, restart
1664
1695
if (!addr.IsValid () || setConnected.count (addr.GetGroup ()) || IsLocal (addr))
@@ -1694,8 +1725,17 @@ void ThreadOpenConnections()
1694
1725
break ;
1695
1726
}
1696
1727
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
+ }
1699
1739
}
1700
1740
}
1701
1741
@@ -1777,7 +1817,7 @@ void ThreadOpenAddedConnections()
1777
1817
}
1778
1818
1779
1819
// 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 )
1781
1821
{
1782
1822
//
1783
1823
// Initiate outbound network connection
@@ -1801,6 +1841,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSem
1801
1841
pnode->fNetworkNode = true ;
1802
1842
if (fOneShot )
1803
1843
pnode->fOneShot = true ;
1844
+ if (fFeeler )
1845
+ pnode->fFeeler = true ;
1804
1846
1805
1847
return true ;
1806
1848
}
@@ -2062,7 +2104,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
2062
2104
2063
2105
if (semOutbound == NULL ) {
2064
2106
// initialize semaphore
2065
- int nMaxOutbound = std::min (MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
2107
+ int nMaxOutbound = std::min (( MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS) , nMaxConnections);
2066
2108
semOutbound = new CSemaphore (nMaxOutbound);
2067
2109
}
2068
2110
@@ -2107,7 +2149,7 @@ bool StopNode()
2107
2149
LogPrintf (" StopNode()\n " );
2108
2150
MapPort (false );
2109
2151
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++)
2111
2153
semOutbound->post ();
2112
2154
2113
2155
if (fAddressesInitialized )
@@ -2448,6 +2490,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
2448
2490
fWhitelisted = false ;
2449
2491
fOneShot = false ;
2450
2492
fClient = false ; // set by version message
2493
+ fFeeler = false ;
2451
2494
fInbound = fInboundIn ;
2452
2495
fNetworkNode = false ;
2453
2496
fSuccessfullyConnected = false ;
0 commit comments