@@ -400,6 +400,26 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure
400
400
return NULL ;
401
401
}
402
402
403
+ if (pszDest && addrConnect.IsValid ()) {
404
+ // It is possible that we already have a connection to the IP/port pszDest resolved to.
405
+ // In that case, drop the connection that was just created, and return the existing CNode instead.
406
+ // Also store the name we used to connect in that CNode, so that future FindNode() calls to that
407
+ // name catch this early.
408
+ CNode* pnode = FindNode ((CService)addrConnect);
409
+ if (pnode)
410
+ {
411
+ pnode->AddRef ();
412
+ {
413
+ LOCK (cs_vNodes);
414
+ if (pnode->addrName .empty ()) {
415
+ pnode->addrName = std::string (pszDest);
416
+ }
417
+ }
418
+ CloseSocket (hSocket);
419
+ return pnode;
420
+ }
421
+ }
422
+
403
423
addrman.Attempt (addrConnect, fCountFailure );
404
424
405
425
// Add node
@@ -1659,68 +1679,79 @@ void ThreadOpenConnections()
1659
1679
}
1660
1680
}
1661
1681
1662
- void ThreadOpenAddedConnections ()
1682
+ std::vector<AddedNodeInfo> GetAddedNodeInfo ()
1663
1683
{
1684
+ std::vector<AddedNodeInfo> ret;
1685
+
1686
+ std::list<std::string> lAddresses (0 );
1664
1687
{
1665
1688
LOCK (cs_vAddedNodes);
1666
- vAddedNodes = mapMultiArgs[" -addnode" ];
1689
+ ret.reserve (vAddedNodes.size ());
1690
+ BOOST_FOREACH (const std::string& strAddNode, vAddedNodes)
1691
+ lAddresses.push_back (strAddNode);
1667
1692
}
1668
1693
1669
- if (HaveNameProxy ()) {
1670
- while (true ) {
1671
- std::list<std::string> lAddresses (0 );
1672
- {
1673
- LOCK (cs_vAddedNodes);
1674
- BOOST_FOREACH (const std::string& strAddNode, vAddedNodes)
1675
- lAddresses.push_back (strAddNode);
1694
+
1695
+ // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
1696
+ std::map<CService, bool > mapConnected;
1697
+ std::map<std::string, std::pair<bool , CService>> mapConnectedByName;
1698
+ {
1699
+ LOCK (cs_vNodes);
1700
+ for (const CNode* pnode : vNodes) {
1701
+ if (pnode->addr .IsValid ()) {
1702
+ mapConnected[pnode->addr ] = pnode->fInbound ;
1676
1703
}
1677
- BOOST_FOREACH (const std::string& strAddNode, lAddresses) {
1678
- CAddress addr;
1679
- CSemaphoreGrant grant (*semOutbound);
1680
- OpenNetworkConnection (addr, false , &grant, strAddNode.c_str ());
1681
- MilliSleep (500 );
1704
+ if (!pnode->addrName .empty ()) {
1705
+ mapConnectedByName[pnode->addrName ] = std::make_pair (pnode->fInbound , static_cast <const CService&>(pnode->addr ));
1706
+ }
1707
+ }
1708
+ }
1709
+
1710
+ BOOST_FOREACH (const std::string& strAddNode, lAddresses) {
1711
+ CService service (strAddNode, Params ().GetDefaultPort ());
1712
+ if (service.IsValid ()) {
1713
+ // strAddNode is an IP:port
1714
+ auto it = mapConnected.find (service);
1715
+ if (it != mapConnected.end ()) {
1716
+ ret.push_back (AddedNodeInfo{strAddNode, service, true , it->second });
1717
+ } else {
1718
+ ret.push_back (AddedNodeInfo{strAddNode, CService (), false , false });
1719
+ }
1720
+ } else {
1721
+ // strAddNode is a name
1722
+ auto it = mapConnectedByName.find (strAddNode);
1723
+ if (it != mapConnectedByName.end ()) {
1724
+ ret.push_back (AddedNodeInfo{strAddNode, it->second .second , true , it->second .first });
1725
+ } else {
1726
+ ret.push_back (AddedNodeInfo{strAddNode, CService (), false , false });
1682
1727
}
1683
- MilliSleep (120000 ); // Retry every 2 minutes
1684
1728
}
1685
1729
}
1686
1730
1731
+ return ret;
1732
+ }
1733
+
1734
+ void ThreadOpenAddedConnections ()
1735
+ {
1736
+ {
1737
+ LOCK (cs_vAddedNodes);
1738
+ vAddedNodes = mapMultiArgs[" -addnode" ];
1739
+ }
1740
+
1687
1741
for (unsigned int i = 0 ; true ; i++)
1688
1742
{
1689
- std::list<std::string> lAddresses (0 );
1690
- {
1691
- LOCK (cs_vAddedNodes);
1692
- BOOST_FOREACH (const std::string& strAddNode, vAddedNodes)
1693
- lAddresses.push_back (strAddNode);
1743
+ std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo ();
1744
+ for (const AddedNodeInfo& info : vInfo) {
1745
+ if (!info.fConnected ) {
1746
+ CSemaphoreGrant grant (*semOutbound);
1747
+ // If strAddedNode is an IP/port, decode it immediately, so
1748
+ // OpenNetworkConnection can detect existing connections to that IP/port.
1749
+ CService service (info.strAddedNode , Params ().GetDefaultPort ());
1750
+ OpenNetworkConnection (CAddress (service, NODE_NONE), false , &grant, info.strAddedNode .c_str (), false );
1751
+ MilliSleep (500 );
1752
+ }
1694
1753
}
1695
1754
1696
- std::list<std::vector<CService> > lservAddressesToAdd (0 );
1697
- BOOST_FOREACH (const std::string& strAddNode, lAddresses) {
1698
- std::vector<CService> vservNode (0 );
1699
- if (Lookup (strAddNode.c_str (), vservNode, Params ().GetDefaultPort (), fNameLookup , 0 ))
1700
- lservAddressesToAdd.push_back (vservNode);
1701
- }
1702
- // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1703
- // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1704
- {
1705
- LOCK (cs_vNodes);
1706
- BOOST_FOREACH (CNode* pnode, vNodes)
1707
- for (std::list<std::vector<CService> >::iterator it = lservAddressesToAdd.begin (); it != lservAddressesToAdd.end (); it++)
1708
- BOOST_FOREACH (const CService& addrNode, *(it))
1709
- if (pnode->addr == addrNode)
1710
- {
1711
- it = lservAddressesToAdd.erase (it);
1712
- it--;
1713
- break ;
1714
- }
1715
- }
1716
- BOOST_FOREACH (std::vector<CService>& vserv, lservAddressesToAdd)
1717
- {
1718
- CSemaphoreGrant grant (*semOutbound);
1719
- /* We want -addnode to work even for nodes that don't provide all
1720
- * wanted services, so pass in nServices=NODE_NONE to CAddress. */
1721
- OpenNetworkConnection (CAddress (vserv[i % vserv.size ()], NODE_NONE), false , &grant);
1722
- MilliSleep (500 );
1723
- }
1724
1755
MilliSleep (120000 ); // Retry every 2 minutes
1725
1756
}
1726
1757
}
0 commit comments