mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-11 22:50:59 +01:00
Merge #8113: Rework addnode behaviour
1a5a4e6Randomize name lookup result in ConnectSocketByName (Pieter Wuille)f9f5cfcPrevent duplicate connections where one is by name and another by ip (Pieter Wuille)1111b80Rework addnode behaviour (Pieter Wuille)
This commit is contained in:
133
src/net.cpp
133
src/net.cpp
@@ -400,6 +400,26 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pszDest && addrConnect.IsValid()) {
|
||||
// It is possible that we already have a connection to the IP/port pszDest resolved to.
|
||||
// In that case, drop the connection that was just created, and return the existing CNode instead.
|
||||
// Also store the name we used to connect in that CNode, so that future FindNode() calls to that
|
||||
// name catch this early.
|
||||
CNode* pnode = FindNode((CService)addrConnect);
|
||||
if (pnode)
|
||||
{
|
||||
pnode->AddRef();
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
if (pnode->addrName.empty()) {
|
||||
pnode->addrName = std::string(pszDest);
|
||||
}
|
||||
}
|
||||
CloseSocket(hSocket);
|
||||
return pnode;
|
||||
}
|
||||
}
|
||||
|
||||
addrman.Attempt(addrConnect, fCountFailure);
|
||||
|
||||
// Add node
|
||||
@@ -1659,6 +1679,58 @@ void ThreadOpenConnections()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<AddedNodeInfo> GetAddedNodeInfo()
|
||||
{
|
||||
std::vector<AddedNodeInfo> ret;
|
||||
|
||||
std::list<std::string> lAddresses(0);
|
||||
{
|
||||
LOCK(cs_vAddedNodes);
|
||||
ret.reserve(vAddedNodes.size());
|
||||
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||
lAddresses.push_back(strAddNode);
|
||||
}
|
||||
|
||||
|
||||
// Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
|
||||
std::map<CService, bool> mapConnected;
|
||||
std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
for (const CNode* pnode : vNodes) {
|
||||
if (pnode->addr.IsValid()) {
|
||||
mapConnected[pnode->addr] = pnode->fInbound;
|
||||
}
|
||||
if (!pnode->addrName.empty()) {
|
||||
mapConnectedByName[pnode->addrName] = std::make_pair(pnode->fInbound, static_cast<const CService&>(pnode->addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||
CService service(strAddNode, Params().GetDefaultPort());
|
||||
if (service.IsValid()) {
|
||||
// strAddNode is an IP:port
|
||||
auto it = mapConnected.find(service);
|
||||
if (it != mapConnected.end()) {
|
||||
ret.push_back(AddedNodeInfo{strAddNode, service, true, it->second});
|
||||
} else {
|
||||
ret.push_back(AddedNodeInfo{strAddNode, CService(), false, false});
|
||||
}
|
||||
} else {
|
||||
// strAddNode is a name
|
||||
auto it = mapConnectedByName.find(strAddNode);
|
||||
if (it != mapConnectedByName.end()) {
|
||||
ret.push_back(AddedNodeInfo{strAddNode, it->second.second, true, it->second.first});
|
||||
} else {
|
||||
ret.push_back(AddedNodeInfo{strAddNode, CService(), false, false});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThreadOpenAddedConnections()
|
||||
{
|
||||
{
|
||||
@@ -1666,61 +1738,20 @@ void ThreadOpenAddedConnections()
|
||||
vAddedNodes = mapMultiArgs["-addnode"];
|
||||
}
|
||||
|
||||
if (HaveNameProxy()) {
|
||||
while(true) {
|
||||
std::list<std::string> lAddresses(0);
|
||||
{
|
||||
LOCK(cs_vAddedNodes);
|
||||
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||
lAddresses.push_back(strAddNode);
|
||||
}
|
||||
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||
CAddress addr;
|
||||
CSemaphoreGrant grant(*semOutbound);
|
||||
OpenNetworkConnection(addr, false, &grant, strAddNode.c_str());
|
||||
MilliSleep(500);
|
||||
}
|
||||
MilliSleep(120000); // Retry every 2 minutes
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; true; i++)
|
||||
{
|
||||
std::list<std::string> lAddresses(0);
|
||||
{
|
||||
LOCK(cs_vAddedNodes);
|
||||
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||
lAddresses.push_back(strAddNode);
|
||||
std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
|
||||
for (const AddedNodeInfo& info : vInfo) {
|
||||
if (!info.fConnected) {
|
||||
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());
|
||||
OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
|
||||
MilliSleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<std::vector<CService> > lservAddressesToAdd(0);
|
||||
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||
std::vector<CService> vservNode(0);
|
||||
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
|
||||
lservAddressesToAdd.push_back(vservNode);
|
||||
}
|
||||
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
|
||||
// (keeping in mind that addnode entries can have many IPs if fNameLookup)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
for (std::list<std::vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
|
||||
BOOST_FOREACH(const CService& addrNode, *(it))
|
||||
if (pnode->addr == addrNode)
|
||||
{
|
||||
it = lservAddressesToAdd.erase(it);
|
||||
it--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BOOST_FOREACH(std::vector<CService>& vserv, lservAddressesToAdd)
|
||||
{
|
||||
CSemaphoreGrant grant(*semOutbound);
|
||||
/* We want -addnode to work even for nodes that don't provide all
|
||||
* wanted services, so pass in nServices=NODE_NONE to CAddress. */
|
||||
OpenNetworkConnection(CAddress(vserv[i % vserv.size()], NODE_NONE), false, &grant);
|
||||
MilliSleep(500);
|
||||
}
|
||||
MilliSleep(120000); // Retry every 2 minutes
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user