aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
authorWladimir J. van der Laan <[email protected]>2016-06-16 12:06:40 +0200
committerWladimir J. van der Laan <[email protected]>2016-06-16 12:06:51 +0200
commit3f89a534acfe91896555439ed3a754cfd430d202 (patch)
tree1823230ff9f6df57d1077516821d929420cf02ff /src/net.cpp
parentMerge #8171: [RPC] Fix createrawtx sequence number unsigned int parsing (diff)
parentRandomize name lookup result in ConnectSocketByName (diff)
downloaddiscoin-3f89a534acfe91896555439ed3a754cfd430d202.tar.xz
discoin-3f89a534acfe91896555439ed3a754cfd430d202.zip
Merge #8113: Rework addnode behaviour
1a5a4e6 Randomize name lookup result in ConnectSocketByName (Pieter Wuille) f9f5cfc Prevent duplicate connections where one is by name and another by ip (Pieter Wuille) 1111b80 Rework addnode behaviour (Pieter Wuille)
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp127
1 files changed, 79 insertions, 48 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 1c63d5174..4eca3d75c 100644
--- a/src/net.cpp
+++ b/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,68 +1679,79 @@ void ThreadOpenConnections()
}
}
-void ThreadOpenAddedConnections()
+std::vector<AddedNodeInfo> GetAddedNodeInfo()
{
+ std::vector<AddedNodeInfo> ret;
+
+ std::list<std::string> lAddresses(0);
{
LOCK(cs_vAddedNodes);
- vAddedNodes = mapMultiArgs["-addnode"];
+ ret.reserve(vAddedNodes.size());
+ BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
+ lAddresses.push_back(strAddNode);
}
- if (HaveNameProxy()) {
- while(true) {
- std::list<std::string> lAddresses(0);
- {
- LOCK(cs_vAddedNodes);
- 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;
}
- BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
- CAddress addr;
- CSemaphoreGrant grant(*semOutbound);
- OpenNetworkConnection(addr, false, &grant, strAddNode.c_str());
- MilliSleep(500);
+ 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});
}
- MilliSleep(120000); // Retry every 2 minutes
}
}
+ return ret;
+}
+
+void ThreadOpenAddedConnections()
+{
+ {
+ LOCK(cs_vAddedNodes);
+ vAddedNodes = mapMultiArgs["-addnode"];
+ }
+
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
}
}