Skip to content

Commit 026c6ed

Browse files
committed
Merge #8282: net: Feeler connections to increase online addrs in the tried table.
dbb1f64 Added feeler connections increasing good addrs in the tried table. (Ethan Heilman)
2 parents 62a5a8a + dbb1f64 commit 026c6ed

File tree

4 files changed

+83
-9
lines changed

4 files changed

+83
-9
lines changed

src/main.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4903,6 +4903,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
49034903

49044904
if (strCommand == NetMsgType::VERSION)
49054905
{
4906+
// Feeler connections exist only to verify if address is online.
4907+
if (pfrom->fFeeler) {
4908+
assert(pfrom->fInbound == false);
4909+
pfrom->fDisconnect = true;
4910+
}
4911+
49064912
// Each connection can only send one version message
49074913
if (pfrom->nVersion != 0)
49084914
{

src/net.cpp

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
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
@@ -61,6 +64,7 @@
6164

6265
namespace {
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;

src/net.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ namespace boost {
4141
static const int PING_INTERVAL = 2 * 60;
4242
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
4343
static const int TIMEOUT_INTERVAL = 20 * 60;
44+
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
45+
static const int FEELER_INTERVAL = 120;
4446
/** The maximum number of entries in an 'inv' protocol message */
4547
static const unsigned int MAX_INV_SZ = 50000;
4648
/** The maximum number of new addresses to accumulate before announcing. */
@@ -89,7 +91,7 @@ CNode* FindNode(const CSubNet& subNet);
8991
CNode* FindNode(const std::string& addrName);
9092
CNode* FindNode(const CService& ip);
9193
CNode* FindNode(const NodeId id); //TODO: Remove this
92-
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
94+
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
9395
void MapPort(bool fUseUPnP);
9496
unsigned short GetListenPort();
9597
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
@@ -350,6 +352,7 @@ class CNode
350352
// the network or wire types and the cleaned string used when displayed or logged.
351353
std::string strSubVer, cleanSubVer;
352354
bool fWhitelisted; // This peer can bypass DoS banning.
355+
bool fFeeler; // If true this node is being used as a short lived feeler.
353356
bool fOneShot;
354357
bool fClient;
355358
bool fInbound;

src/test/net_tests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,26 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
150150
BOOST_CHECK(addrman2.size() == 0);
151151
}
152152

153+
BOOST_AUTO_TEST_CASE(cnode_simple_test)
154+
{
155+
SOCKET hSocket = INVALID_SOCKET;
156+
157+
in_addr ipv4Addr;
158+
ipv4Addr.s_addr = 0xa0b0c001;
159+
160+
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
161+
std::string pszDest = "";
162+
bool fInboundIn = false;
163+
164+
// Test that fFeeler is false by default.
165+
CNode* pnode1 = new CNode(hSocket, addr, pszDest, fInboundIn);
166+
BOOST_CHECK(pnode1->fInbound == false);
167+
BOOST_CHECK(pnode1->fFeeler == false);
168+
169+
fInboundIn = true;
170+
CNode* pnode2 = new CNode(hSocket, addr, pszDest, fInboundIn);
171+
BOOST_CHECK(pnode2->fInbound == true);
172+
BOOST_CHECK(pnode2->fFeeler == false);
173+
}
174+
153175
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)