aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp93
1 files changed, 67 insertions, 26 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 198d8f5fff..75d1719e86 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -340,6 +340,22 @@ bool CConnman::CheckIncomingNonce(uint64_t nonce)
return true;
}
+/** Get the bind address for a socket as CAddress */
+static CAddress GetBindAddress(SOCKET sock)
+{
+ CAddress addr_bind;
+ struct sockaddr_storage sockaddr_bind;
+ socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
+ if (sock != INVALID_SOCKET) {
+ if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
+ addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
+ } else {
+ LogPrint(BCLog::NET, "Warning: getsockname failed\n");
+ }
+ }
+ return addr_bind;
+}
+
CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure)
{
if (pszDest == NULL) {
@@ -393,7 +409,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
// Add node
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
- CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, pszDest ? pszDest : "", false);
+ CAddress addr_bind = GetBindAddress(hSocket);
+ CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false);
pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
pnode->AddRef();
@@ -452,35 +469,31 @@ void CConnman::ClearBanned()
bool CConnman::IsBanned(CNetAddr ip)
{
- bool fResult = false;
+ LOCK(cs_setBanned);
+ for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
{
- LOCK(cs_setBanned);
- for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
- {
- CSubNet subNet = (*it).first;
- CBanEntry banEntry = (*it).second;
+ CSubNet subNet = (*it).first;
+ CBanEntry banEntry = (*it).second;
- if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil)
- fResult = true;
+ if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) {
+ return true;
}
}
- return fResult;
+ return false;
}
bool CConnman::IsBanned(CSubNet subnet)
{
- bool fResult = false;
+ LOCK(cs_setBanned);
+ banmap_t::iterator i = setBanned.find(subnet);
+ if (i != setBanned.end())
{
- LOCK(cs_setBanned);
- banmap_t::iterator i = setBanned.find(subnet);
- if (i != setBanned.end())
- {
- CBanEntry banEntry = (*i).second;
- if (GetTime() < banEntry.nBanUntil)
- fResult = true;
+ CBanEntry banEntry = (*i).second;
+ if (GetTime() < banEntry.nBanUntil) {
+ return true;
}
}
- return fResult;
+ return false;
}
void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
@@ -635,6 +648,7 @@ void CNode::copyStats(CNodeStats &stats)
stats.nodeid = this->GetId();
X(nServices);
X(addr);
+ X(addrBind);
{
LOCK(cs_filter);
X(fRelayTxes);
@@ -1036,9 +1050,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
int nInbound = 0;
int nMaxInbound = nMaxConnections - (nMaxOutbound + nMaxFeeler);
- if (hSocket != INVALID_SOCKET)
- if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
+ if (hSocket != INVALID_SOCKET) {
+ if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
LogPrintf("Warning: Unknown socket family\n");
+ }
+ }
bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr);
{
@@ -1092,8 +1108,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
+ CAddress addr_bind = GetBindAddress(hSocket);
- CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, "", true);
+ CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true);
pnode->AddRef();
pnode->fWhitelisted = whitelisted;
GetNodeSignals().InitializeNode(pnode, *this);
@@ -1721,11 +1738,17 @@ void CConnman::ThreadOpenConnections()
// Only connect out to one peer per network group (/16 for IPv4).
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
int nOutbound = 0;
+ int nOutboundRelevant = 0;
std::set<std::vector<unsigned char> > setConnected;
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) {
if (!pnode->fInbound && !pnode->fAddnode) {
+
+ // Count the peers that have all relevant services
+ if (pnode->fSuccessfullyConnected && !pnode->fFeeler && ((pnode->nServices & nRelevantServices) == nRelevantServices)) {
+ nOutboundRelevant++;
+ }
// Netgroups for inbound and addnode peers are not excluded because our goal here
// is to not use multiple of our limited outbound slots on a single netgroup
// but inbound and addnode peers do not use our outbound slots. Inbound peers
@@ -1743,9 +1766,9 @@ void CConnman::ThreadOpenConnections()
// * 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
+ // * 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
+ // * Start attempting feeler connections only after node finishes making outbound
// connections.
// * Only make a feeler connection once every few minutes.
//
@@ -1789,14 +1812,27 @@ void CConnman::ThreadOpenConnections()
continue;
// only consider nodes missing relevant services after 40 failed attempts and only if less than half the outbound are up.
- if ((addr.nServices & nRelevantServices) != nRelevantServices && (nTries < 40 || nOutbound >= (nMaxOutbound >> 1)))
+ ServiceFlags nRequiredServices = nRelevantServices;
+ if (nTries >= 40 && nOutbound < (nMaxOutbound >> 1)) {
+ nRequiredServices = REQUIRED_SERVICES;
+ }
+
+ if ((addr.nServices & nRequiredServices) != nRequiredServices) {
continue;
+ }
// do not allow non-default ports, unless after 50 invalid addresses selected already
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;
addrConnect = addr;
+
+ // regardless of the services assumed to be available, only require the minimum if half or more outbound have relevant services
+ if (nOutboundRelevant >= (nMaxOutbound >> 1)) {
+ addrConnect.nServices = REQUIRED_SERVICES;
+ } else {
+ addrConnect.nServices = nRequiredServices;
+ }
break;
}
@@ -2212,6 +2248,10 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
SetBestHeight(connOptions.nBestHeight);
+ for (const auto& strDest : connOptions.vSeedNodes) {
+ AddOneShot(strDest);
+ }
+
clientInterface = connOptions.uiInterface;
if (clientInterface) {
clientInterface->InitMessage(_("Loading P2P addresses..."));
@@ -2616,9 +2656,10 @@ int CConnman::GetBestHeight() const
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; }
-CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const std::string& addrNameIn, bool fInboundIn) :
+CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string& addrNameIn, bool fInboundIn) :
nTimeConnected(GetSystemTimeInSeconds()),
addr(addrIn),
+ addrBind(addrBindIn),
fInbound(fInboundIn),
nKeyedNetGroup(nKeyedNetGroupIn),
addrKnown(5000, 0.001),