From 74088e862e29821562652986c6bd7c14c3783327 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 2 Jul 2012 19:55:16 +0200 Subject: Use a copy in place of mapMultiArgs["-addnode"]. Also moves the DNS lookup of -addnode nodes into the repeated loop, allowing -addnode to follow DNS changes. --- src/net.cpp | 53 +++++++++++++++++++++++++++++++++++------------------ src/net.h | 3 +++ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 319739429c..46700bd154 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -72,6 +72,9 @@ CCriticalSection cs_vOneShots; set setservAddNodeAddresses; CCriticalSection cs_setservAddNodeAddresses; +vector vAddedNodes; +CCriticalSection cs_vAddedNodes; + static CSemaphore *semOutbound = NULL; void AddOneShot(string strDest) @@ -1523,12 +1526,20 @@ void ThreadOpenAddedConnections2(void* parg) { printf("ThreadOpenAddedConnections started\n"); - if (mapArgs.count("-addnode") == 0) - return; + { + LOCK(cs_vAddedNodes); + vAddedNodes = mapMultiArgs["-addnode"]; + } if (HaveNameProxy()) { while(!fShutdown) { - BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) { + list lAddresses(0); + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + lAddresses.push_back(strAddNode); + } + BOOST_FOREACH(string& strAddNode, lAddresses) { CAddress addr; CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(addr, &grant, strAddNode.c_str()); @@ -1541,38 +1552,44 @@ void ThreadOpenAddedConnections2(void* parg) return; } - vector > vservAddressesToAdd(0); - BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) + loop { - vector vservNode(0); - if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) + list lAddresses(0); + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + lAddresses.push_back(strAddNode); + } + + list > lservAddressesToAdd(0); + BOOST_FOREACH(string& strAddNode, lAddresses) { - vservAddressesToAdd.push_back(vservNode); + vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) { - LOCK(cs_setservAddNodeAddresses); - BOOST_FOREACH(CService& serv, vservNode) - setservAddNodeAddresses.insert(serv); + lservAddressesToAdd.push_back(vservNode); + { + LOCK(cs_setservAddNodeAddresses); + BOOST_FOREACH(CService& serv, vservNode) + setservAddNodeAddresses.insert(serv); + } } } - } - loop - { - vector > vservConnectAddresses = vservAddressesToAdd; // 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 (vector >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++) + for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) BOOST_FOREACH(CService& addrNode, *(it)) if (pnode->addr == addrNode) { - it = vservConnectAddresses.erase(it); + it = lservAddressesToAdd.erase(it); it--; break; } } - BOOST_FOREACH(vector& vserv, vservConnectAddresses) + BOOST_FOREACH(vector& vserv, lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(CAddress(*(vserv.begin())), &grant); diff --git a/src/net.h b/src/net.h index 99f41161b1..14e12aa102 100644 --- a/src/net.h +++ b/src/net.h @@ -102,6 +102,9 @@ extern std::deque > vRelayExpiration; extern CCriticalSection cs_mapRelay; extern std::map mapAlreadyAskedFor; +extern std::vector vAddedNodes; +extern CCriticalSection cs_vAddedNodes; + -- cgit v1.2.3 From f339e9e3391465de4921aea3194f3021016f07d1 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 2 Jul 2012 20:14:02 +0200 Subject: Make ThreadOpenAddedConnections2 exit quicker if(GetNameProxy()). --- src/net.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 46700bd154..4a32859dc6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1544,6 +1544,8 @@ void ThreadOpenAddedConnections2(void* parg) CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(addr, &grant, strAddNode.c_str()); Sleep(500); + if (fShutdown) + return; } vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; Sleep(120000); // Retry every 2 minutes -- cgit v1.2.3 From 72a348fd9a7015aa039f9cbdc9166f388f4725e0 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 23 Jan 2013 11:45:00 -0500 Subject: Add addnode RPC command. --- src/bitcoinrpc.cpp | 1 + src/bitcoinrpc.h | 1 + src/rpcnet.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index a1e39d7506..910d52a9fe 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -201,6 +201,7 @@ static const CRPCCommand vRPCCommands[] = { "getblockcount", &getblockcount, true, false }, { "getconnectioncount", &getconnectioncount, true, false }, { "getpeerinfo", &getpeerinfo, true, false }, + { "addnode", &addnode, true, true }, { "getdifficulty", &getdifficulty, true, false }, { "getgenerate", &getgenerate, true, false }, { "setgenerate", &setgenerate, true, false }, diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 44050ae1bb..4e4ac4ff81 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -132,6 +132,7 @@ extern void EnsureWalletIsUnlocked(); extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 491297eb1d..f3b41e5be7 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -65,3 +65,45 @@ Value getpeerinfo(const Array& params, bool fHelp) return ret; } +Value addnode(const Array& params, bool fHelp) +{ + string strCommand; + if (params.size() == 2) + strCommand = params[1].get_str(); + if (fHelp || params.size() != 2 || + (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) + throw runtime_error( + "addnode \n" + "Attempts add or remove from the addnode list or try a connection to once."); + + string strNode = params[0].get_str(); + + if (strCommand == "onetry") + { + CAddress addr; + ConnectNode(addr, strNode.c_str()); + return Value::null; + } + + LOCK(cs_vAddedNodes); + vector::iterator it = vAddedNodes.begin(); + for(; it != vAddedNodes.end(); it++) + if (strNode == *it) + break; + + if (strCommand == "add") + { + if (it != vAddedNodes.end()) + throw JSONRPCError(-23, "Error: Node already added"); + vAddedNodes.push_back(strNode); + } + else if(strCommand == "remove") + { + if (it == vAddedNodes.end()) + throw JSONRPCError(-24, "Error: Node has not been added."); + vAddedNodes.erase(it); + } + + return Value::null; +} + -- cgit v1.2.3 From 67a11bd6c5c28edc5f24574595380c1ddf8becf4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 23 Jan 2013 11:48:17 -0500 Subject: Add a getaddednodeinfo RPC. --- src/bitcoinrpc.cpp | 2 ++ src/bitcoinrpc.h | 1 + src/rpcnet.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 910d52a9fe..7751e4c8b6 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -202,6 +202,7 @@ static const CRPCCommand vRPCCommands[] = { "getconnectioncount", &getconnectioncount, true, false }, { "getpeerinfo", &getpeerinfo, true, false }, { "addnode", &addnode, true, true }, + { "getaddednodeinfo", &getaddednodeinfo, true, true }, { "getdifficulty", &getdifficulty, true, false }, { "getgenerate", &getgenerate, true, false }, { "setgenerate", &setgenerate, true, false }, @@ -1180,6 +1181,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); + if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo(params[0]); if (strMethod == "setgenerate" && n > 0) ConvertTo(params[0]); if (strMethod == "setgenerate" && n > 1) ConvertTo(params[1]); if (strMethod == "sendtoaddress" && n > 1) ConvertTo(params[1]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 4e4ac4ff81..36bfbe3eef 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -133,6 +133,7 @@ extern void EnsureWalletIsUnlocked(); extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index f3b41e5be7..4db3be9319 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -107,3 +107,95 @@ Value addnode(const Array& params, bool fHelp) return Value::null; } +Value getaddednodeinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getaddednodeinfo [node]\n" + "Returns information about the given added node, or all added nodes\n" + "(note that onetry addnodes are not listed here)\n" + "If dns is false, only a list of added nodes will be provided,\n" + "otherwise connected information will also be available."); + + bool fDns = params[0].get_bool(); + + list laddedNodes(0); + if (params.size() == 1) + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + laddedNodes.push_back(strAddNode); + } + else + { + string strNode = params[1].get_str(); + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + if (strAddNode == strNode) + { + laddedNodes.push_back(strAddNode); + break; + } + if (laddedNodes.size() == 0) + throw JSONRPCError(-24, "Error: Node has not been added."); + } + + if (!fDns) + { + Object ret; + BOOST_FOREACH(string& strAddNode, laddedNodes) + ret.push_back(Pair("addednode", strAddNode)); + return ret; + } + + Array ret; + + list > > laddedAddreses(0); + BOOST_FOREACH(string& strAddNode, laddedNodes) + { + vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) + laddedAddreses.push_back(make_pair(strAddNode, vservNode)); + else + { + Object obj; + obj.push_back(Pair("addednode", strAddNode)); + obj.push_back(Pair("connected", false)); + Array addresses; + obj.push_back(Pair("addresses", addresses)); + } + } + + LOCK(cs_vNodes); + for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) + { + Object obj; + obj.push_back(Pair("addednode", it->first)); + + Array addresses; + bool fConnected = false; + BOOST_FOREACH(CService& addrNode, it->second) + { + bool fFound = false; + Object node; + node.push_back(Pair("address", addrNode.ToString())); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->addr == addrNode) + { + fFound = true; + fConnected = true; + node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); + break; + } + if (!fFound) + node.push_back(Pair("connected", "false")); + addresses.push_back(node); + } + obj.push_back(Pair("connected", fConnected)); + obj.push_back(Pair("addresses", addresses)); + ret.push_back(obj); + } + + return ret; +} + -- cgit v1.2.3 From f2bd6c28e6bddd75d56d580c28f45d2a8be065ab Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 2 Jul 2012 21:11:57 +0200 Subject: Try more than the first address for a DNS -addnode. --- src/net.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 4a32859dc6..f89d2899fe 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1554,7 +1554,7 @@ void ThreadOpenAddedConnections2(void* parg) return; } - loop + for (unsigned int i = 0; true; i++) { list lAddresses(0); { @@ -1594,7 +1594,7 @@ void ThreadOpenAddedConnections2(void* parg) BOOST_FOREACH(vector& vserv, lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(CAddress(*(vserv.begin())), &grant); + OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant); Sleep(500); if (fShutdown) return; -- cgit v1.2.3