aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp88
1 files changed, 70 insertions, 18 deletions
diff --git a/src/net.cpp b/src/net.cpp
index c159198ac6..957388b8fd 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -17,6 +17,7 @@
#include "crypto/sha256.h"
#include "hash.h"
#include "primitives/transaction.h"
+#include "netbase.h"
#include "scheduler.h"
#include "ui_interface.h"
#include "utilstrencodings.h"
@@ -42,6 +43,9 @@
// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
#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)
#define MSG_NOSIGNAL 0
#endif
@@ -60,6 +64,7 @@
namespace {
const int MAX_OUTBOUND_CONNECTIONS = 8;
+ const int MAX_FEELER_CONNECTIONS = 1;
struct ListenSocket {
SOCKET socket;
@@ -175,7 +180,7 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn
// one by discovery.
CAddress GetLocalAddress(const CNetAddr *paddrPeer)
{
- CAddress ret(CService("0.0.0.0",GetListenPort()), NODE_NONE);
+ CAddress ret(CService(CNetAddr(),GetListenPort()), NODE_NONE);
CService addr;
if (GetLocal(addr, paddrPeer))
{
@@ -494,7 +499,7 @@ void CNode::PushVersion()
int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0);
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
- CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices));
+ CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
CAddress addrMe = GetLocalAddress(&addr);
GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
if (fLogIPs)
@@ -1016,7 +1021,8 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
CAddress addr;
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 (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
@@ -1396,8 +1402,11 @@ void ThreadMapPort()
{
if(externalIPAddress[0])
{
- LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
- AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
+ CNetAddr resolved;
+ if(LookupHost(externalIPAddress, resolved, false)) {
+ LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
+ AddLocal(resolved, LOCAL_UPNP);
+ }
}
else
LogPrintf("UPnP: GetExternalIPAddress failed.\n");
@@ -1609,6 +1618,9 @@ void ThreadOpenConnections()
// Initiate network connections
int64_t nStart = GetTime();
+
+ // Minimum time before next feeler connection (in microseconds).
+ int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
while (true)
{
ProcessOneShot();
@@ -1623,7 +1635,9 @@ void ThreadOpenConnections()
static bool done = false;
if (!done) {
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
- addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
+ CNetAddr local;
+ LookupHost("127.0.0.1", local, false);
+ addrman.Add(convertSeed6(Params().FixedSeeds()), local);
done = true;
}
}
@@ -1646,13 +1660,36 @@ void ThreadOpenConnections()
}
}
}
+ assert(nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS));
- int64_t nANow = GetAdjustedTime();
+ // 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();
int nTries = 0;
while (true)
{
- CAddrInfo addr = addrman.Select();
+ CAddrInfo addr = addrman.Select(fFeeler);
// if we selected an invalid address, restart
if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
@@ -1676,7 +1713,7 @@ void ThreadOpenConnections()
if (nANow - addr.nLastTry < 600 && nTries < 30)
continue;
- // only consider nodes missing relevant services after 40 failed attemps
+ // only consider nodes missing relevant services after 40 failed attempts
if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40)
continue;
@@ -1688,8 +1725,17 @@ void ThreadOpenConnections()
break;
}
- if (addrConnect.IsValid())
- OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant);
+ if (addrConnect.IsValid()) {
+
+ 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);
+ }
}
}
@@ -1722,7 +1768,7 @@ std::vector<AddedNodeInfo> GetAddedNodeInfo()
}
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
- CService service(strAddNode, Params().GetDefaultPort());
+ CService service(LookupNumeric(strAddNode.c_str(), Params().GetDefaultPort()));
if (service.IsValid()) {
// strAddNode is an IP:port
auto it = mapConnected.find(service);
@@ -1760,7 +1806,7 @@ void ThreadOpenAddedConnections()
CSemaphoreGrant grant(*semOutbound);
// If strAddedNode is an IP/port, decode it immediately, so
// OpenNetworkConnection can detect existing connections to that IP/port.
- CService service(info.strAddedNode, Params().GetDefaultPort());
+ CService service(LookupNumeric(info.strAddedNode.c_str(), Params().GetDefaultPort()));
OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
MilliSleep(500);
}
@@ -1771,7 +1817,7 @@ void ThreadOpenAddedConnections()
}
// 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
@@ -1795,6 +1841,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSem
pnode->fNetworkNode = true;
if (fOneShot)
pnode->fOneShot = true;
+ if (fFeeler)
+ pnode->fFeeler = true;
return true;
}
@@ -2056,12 +2104,15 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
if (semOutbound == NULL) {
// 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);
}
- if (pnodeLocalHost == NULL)
- pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
+ if (pnodeLocalHost == NULL) {
+ CNetAddr local;
+ LookupHost("127.0.0.1", local, false);
+ pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices));
+ }
Discover(threadGroup);
@@ -2098,7 +2149,7 @@ bool StopNode()
LogPrintf("StopNode()\n");
MapPort(false);
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();
if (fAddressesInitialized)
@@ -2439,6 +2490,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
fWhitelisted = false;
fOneShot = false;
fClient = false; // set by version message
+ fFeeler = false;
fInbound = fInboundIn;
fNetworkNode = false;
fSuccessfullyConnected = false;