mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-18 02:51:06 +00:00
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)
This commit is contained in:
commit
026c6edac9
@ -4903,6 +4903,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
|
|
||||||
if (strCommand == NetMsgType::VERSION)
|
if (strCommand == NetMsgType::VERSION)
|
||||||
{
|
{
|
||||||
|
// Feeler connections exist only to verify if address is online.
|
||||||
|
if (pfrom->fFeeler) {
|
||||||
|
assert(pfrom->fInbound == false);
|
||||||
|
pfrom->fDisconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Each connection can only send one version message
|
// Each connection can only send one version message
|
||||||
if (pfrom->nVersion != 0)
|
if (pfrom->nVersion != 0)
|
||||||
{
|
{
|
||||||
|
59
src/net.cpp
59
src/net.cpp
@ -43,6 +43,9 @@
|
|||||||
// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
|
// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
|
||||||
#define DUMP_ADDRESSES_INTERVAL 900
|
#define DUMP_ADDRESSES_INTERVAL 900
|
||||||
|
|
||||||
|
// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
|
||||||
|
#define FEELER_SLEEP_WINDOW 1
|
||||||
|
|
||||||
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
|
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
|
||||||
#define MSG_NOSIGNAL 0
|
#define MSG_NOSIGNAL 0
|
||||||
#endif
|
#endif
|
||||||
@ -61,6 +64,7 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const int MAX_OUTBOUND_CONNECTIONS = 8;
|
const int MAX_OUTBOUND_CONNECTIONS = 8;
|
||||||
|
const int MAX_FEELER_CONNECTIONS = 1;
|
||||||
|
|
||||||
struct ListenSocket {
|
struct ListenSocket {
|
||||||
SOCKET socket;
|
SOCKET socket;
|
||||||
@ -1017,7 +1021,8 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
|
|||||||
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
|
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
int nInbound = 0;
|
int nInbound = 0;
|
||||||
int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS;
|
int nMaxInbound = nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS);
|
||||||
|
assert(nMaxInbound > 0);
|
||||||
|
|
||||||
if (hSocket != INVALID_SOCKET)
|
if (hSocket != INVALID_SOCKET)
|
||||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
||||||
@ -1613,6 +1618,9 @@ void ThreadOpenConnections()
|
|||||||
|
|
||||||
// Initiate network connections
|
// Initiate network connections
|
||||||
int64_t nStart = GetTime();
|
int64_t nStart = GetTime();
|
||||||
|
|
||||||
|
// Minimum time before next feeler connection (in microseconds).
|
||||||
|
int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ProcessOneShot();
|
ProcessOneShot();
|
||||||
@ -1652,13 +1660,36 @@ void ThreadOpenConnections()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS));
|
||||||
|
|
||||||
|
// Feeler Connections
|
||||||
|
//
|
||||||
|
// Design goals:
|
||||||
|
// * Increase the number of connectable addresses in the tried table.
|
||||||
|
//
|
||||||
|
// Method:
|
||||||
|
// * Choose a random address from new and attempt to connect to it if we can connect
|
||||||
|
// successfully it is added to tried.
|
||||||
|
// * Start attempting feeler connections only after node finishes making outbound
|
||||||
|
// connections.
|
||||||
|
// * Only make a feeler connection once every few minutes.
|
||||||
|
//
|
||||||
|
bool fFeeler = false;
|
||||||
|
if (nOutbound >= MAX_OUTBOUND_CONNECTIONS) {
|
||||||
|
int64_t nTime = GetTimeMicros(); // The current time right now (in microseconds).
|
||||||
|
if (nTime > nNextFeeler) {
|
||||||
|
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
|
||||||
|
fFeeler = true;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64_t nANow = GetAdjustedTime();
|
int64_t nANow = GetAdjustedTime();
|
||||||
|
|
||||||
int nTries = 0;
|
int nTries = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
CAddrInfo addr = addrman.Select();
|
CAddrInfo addr = addrman.Select(fFeeler);
|
||||||
|
|
||||||
// if we selected an invalid address, restart
|
// if we selected an invalid address, restart
|
||||||
if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
|
if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
|
||||||
@ -1694,8 +1725,17 @@ void ThreadOpenConnections()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addrConnect.IsValid())
|
if (addrConnect.IsValid()) {
|
||||||
OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant);
|
|
||||||
|
if (fFeeler) {
|
||||||
|
// Add small amount of random noise before connection to avoid synchronization.
|
||||||
|
int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000);
|
||||||
|
MilliSleep(randsleep);
|
||||||
|
LogPrint("net", "Making feeler connection to %s\n", addrConnect.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant, NULL, false, fFeeler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1777,7 +1817,7 @@ void ThreadOpenAddedConnections()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if successful, this moves the passed grant to the constructed node
|
// if successful, this moves the passed grant to the constructed node
|
||||||
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
|
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Initiate outbound network connection
|
// Initiate outbound network connection
|
||||||
@ -1801,6 +1841,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSem
|
|||||||
pnode->fNetworkNode = true;
|
pnode->fNetworkNode = true;
|
||||||
if (fOneShot)
|
if (fOneShot)
|
||||||
pnode->fOneShot = true;
|
pnode->fOneShot = true;
|
||||||
|
if (fFeeler)
|
||||||
|
pnode->fFeeler = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2062,7 +2104,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
|
|
||||||
if (semOutbound == NULL) {
|
if (semOutbound == NULL) {
|
||||||
// initialize semaphore
|
// initialize semaphore
|
||||||
int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
|
int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections);
|
||||||
semOutbound = new CSemaphore(nMaxOutbound);
|
semOutbound = new CSemaphore(nMaxOutbound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2107,7 +2149,7 @@ bool StopNode()
|
|||||||
LogPrintf("StopNode()\n");
|
LogPrintf("StopNode()\n");
|
||||||
MapPort(false);
|
MapPort(false);
|
||||||
if (semOutbound)
|
if (semOutbound)
|
||||||
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
|
for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++)
|
||||||
semOutbound->post();
|
semOutbound->post();
|
||||||
|
|
||||||
if (fAddressesInitialized)
|
if (fAddressesInitialized)
|
||||||
@ -2448,6 +2490,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
|
|||||||
fWhitelisted = false;
|
fWhitelisted = false;
|
||||||
fOneShot = false;
|
fOneShot = false;
|
||||||
fClient = false; // set by version message
|
fClient = false; // set by version message
|
||||||
|
fFeeler = false;
|
||||||
fInbound = fInboundIn;
|
fInbound = fInboundIn;
|
||||||
fNetworkNode = false;
|
fNetworkNode = false;
|
||||||
fSuccessfullyConnected = false;
|
fSuccessfullyConnected = false;
|
||||||
|
@ -41,6 +41,8 @@ namespace boost {
|
|||||||
static const int PING_INTERVAL = 2 * 60;
|
static const int PING_INTERVAL = 2 * 60;
|
||||||
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
||||||
static const int TIMEOUT_INTERVAL = 20 * 60;
|
static const int TIMEOUT_INTERVAL = 20 * 60;
|
||||||
|
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
|
||||||
|
static const int FEELER_INTERVAL = 120;
|
||||||
/** The maximum number of entries in an 'inv' protocol message */
|
/** The maximum number of entries in an 'inv' protocol message */
|
||||||
static const unsigned int MAX_INV_SZ = 50000;
|
static const unsigned int MAX_INV_SZ = 50000;
|
||||||
/** The maximum number of new addresses to accumulate before announcing. */
|
/** The maximum number of new addresses to accumulate before announcing. */
|
||||||
@ -89,7 +91,7 @@ CNode* FindNode(const CSubNet& subNet);
|
|||||||
CNode* FindNode(const std::string& addrName);
|
CNode* FindNode(const std::string& addrName);
|
||||||
CNode* FindNode(const CService& ip);
|
CNode* FindNode(const CService& ip);
|
||||||
CNode* FindNode(const NodeId id); //TODO: Remove this
|
CNode* FindNode(const NodeId id); //TODO: Remove this
|
||||||
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
|
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
|
||||||
void MapPort(bool fUseUPnP);
|
void MapPort(bool fUseUPnP);
|
||||||
unsigned short GetListenPort();
|
unsigned short GetListenPort();
|
||||||
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
|
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
|
||||||
@ -350,6 +352,7 @@ public:
|
|||||||
// the network or wire types and the cleaned string used when displayed or logged.
|
// the network or wire types and the cleaned string used when displayed or logged.
|
||||||
std::string strSubVer, cleanSubVer;
|
std::string strSubVer, cleanSubVer;
|
||||||
bool fWhitelisted; // This peer can bypass DoS banning.
|
bool fWhitelisted; // This peer can bypass DoS banning.
|
||||||
|
bool fFeeler; // If true this node is being used as a short lived feeler.
|
||||||
bool fOneShot;
|
bool fOneShot;
|
||||||
bool fClient;
|
bool fClient;
|
||||||
bool fInbound;
|
bool fInbound;
|
||||||
|
@ -150,4 +150,26 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
|
|||||||
BOOST_CHECK(addrman2.size() == 0);
|
BOOST_CHECK(addrman2.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
|
{
|
||||||
|
SOCKET hSocket = INVALID_SOCKET;
|
||||||
|
|
||||||
|
in_addr ipv4Addr;
|
||||||
|
ipv4Addr.s_addr = 0xa0b0c001;
|
||||||
|
|
||||||
|
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
|
||||||
|
std::string pszDest = "";
|
||||||
|
bool fInboundIn = false;
|
||||||
|
|
||||||
|
// Test that fFeeler is false by default.
|
||||||
|
CNode* pnode1 = new CNode(hSocket, addr, pszDest, fInboundIn);
|
||||||
|
BOOST_CHECK(pnode1->fInbound == false);
|
||||||
|
BOOST_CHECK(pnode1->fFeeler == false);
|
||||||
|
|
||||||
|
fInboundIn = true;
|
||||||
|
CNode* pnode2 = new CNode(hSocket, addr, pszDest, fInboundIn);
|
||||||
|
BOOST_CHECK(pnode2->fInbound == true);
|
||||||
|
BOOST_CHECK(pnode2->fFeeler == false);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user