diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2013-01-28 11:09:03 -0800 |
---|---|---|
committer | Gavin Andresen <gavinandresen@gmail.com> | 2013-01-28 11:09:03 -0800 |
commit | 79bec38cb490a77e9431716245c645d2aa0c0a87 (patch) | |
tree | 00c321b65438eb02e464c0c26708e056405603d3 | |
parent | f73abdc82dd69c046f7800acd0845002cb20aec5 (diff) | |
parent | f2bd6c28e6bddd75d56d580c28f45d2a8be065ab (diff) |
Merge pull request #1549 from TheBlueMatt/addnoderpc
Addnode optimization and addnode access via RPC
-rw-r--r-- | src/bitcoinrpc.cpp | 3 | ||||
-rw-r--r-- | src/bitcoinrpc.h | 2 | ||||
-rw-r--r-- | src/net.cpp | 57 | ||||
-rw-r--r-- | src/net.h | 3 | ||||
-rw-r--r-- | src/rpcnet.cpp | 134 |
5 files changed, 180 insertions, 19 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index a1e39d7506..7751e4c8b6 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -201,6 +201,8 @@ static const CRPCCommand vRPCCommands[] = { "getblockcount", &getblockcount, true, false }, { "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 }, @@ -1179,6 +1181,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri // Special case non-string parameter types // if (strMethod == "stop" && n > 0) ConvertTo<bool>(params[0]); + if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo<bool>(params[0]); if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]); if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 44050ae1bb..36bfbe3eef 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -132,6 +132,8 @@ 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/net.cpp b/src/net.cpp index 319739429c..f89d2899fe 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -72,6 +72,9 @@ CCriticalSection cs_vOneShots; set<CNetAddr> setservAddNodeAddresses; CCriticalSection cs_setservAddNodeAddresses; +vector<std::string> vAddedNodes; +CCriticalSection cs_vAddedNodes; + static CSemaphore *semOutbound = NULL; void AddOneShot(string strDest) @@ -1523,16 +1526,26 @@ 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<string> 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()); Sleep(500); + if (fShutdown) + return; } vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; Sleep(120000); // Retry every 2 minutes @@ -1541,41 +1554,47 @@ void ThreadOpenAddedConnections2(void* parg) return; } - vector<vector<CService> > vservAddressesToAdd(0); - BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) + for (unsigned int i = 0; true; i++) { - vector<CService> vservNode(0); - if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) + list<string> lAddresses(0); { - vservAddressesToAdd.push_back(vservNode); + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + lAddresses.push_back(strAddNode); + } + + list<vector<CService> > lservAddressesToAdd(0); + BOOST_FOREACH(string& strAddNode, lAddresses) + { + vector<CService> 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<vector<CService> > 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<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++) + for (list<vector<CService> >::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<CService>& vserv, vservConnectAddresses) + BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(CAddress(*(vserv.begin())), &grant); + OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant); Sleep(500); if (fShutdown) return; @@ -102,6 +102,9 @@ extern std::deque<std::pair<int64, CInv> > vRelayExpiration; extern CCriticalSection cs_mapRelay; extern std::map<CInv, int64> mapAlreadyAskedFor; +extern std::vector<std::string> vAddedNodes; +extern CCriticalSection cs_vAddedNodes; + diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 491297eb1d..4db3be9319 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -65,3 +65,137 @@ 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 <node> <add|remove|onetry>\n" + "Attempts add or remove <node> from the addnode list or try a connection to <node> once."); + + string strNode = params[0].get_str(); + + if (strCommand == "onetry") + { + CAddress addr; + ConnectNode(addr, strNode.c_str()); + return Value::null; + } + + LOCK(cs_vAddedNodes); + vector<string>::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; +} + +Value getaddednodeinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getaddednodeinfo <dns> [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<string> 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<pair<string, vector<CService> > > laddedAddreses(0); + BOOST_FOREACH(string& strAddNode, laddedNodes) + { + vector<CService> 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<pair<string, vector<CService> > >::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; +} + |