// Copyright (c) 2009-2012 Bitcoin Developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "net.h" #include "bitcoinrpc.h" using namespace json_spirit; using namespace std; Value getconnectioncount(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getconnectioncount\n" "Returns the number of connections to other nodes."); LOCK(cs_vNodes); return (int)vNodes.size(); } static void CopyNodeStats(std::vector& vstats) { vstats.clear(); LOCK(cs_vNodes); vstats.reserve(vNodes.size()); BOOST_FOREACH(CNode* pnode, vNodes) { CNodeStats stats; pnode->copyStats(stats); vstats.push_back(stats); } } Value getpeerinfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getpeerinfo\n" "Returns data about each connected network node."); vector vstats; CopyNodeStats(vstats); Array ret; BOOST_FOREACH(const CNodeStats& stats, vstats) { Object obj; obj.push_back(Pair("addr", stats.addrName)); obj.push_back(Pair("services", strprintf("%08" PRI64x, stats.nServices))); obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend)); obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv)); obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes)); obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes)); obj.push_back(Pair("blocksrequested", (boost::int64_t)stats.nBlocksRequested)); obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected)); obj.push_back(Pair("version", stats.nVersion)); obj.push_back(Pair("subver", stats.strSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); obj.push_back(Pair("startingheight", stats.nStartingHeight)); obj.push_back(Pair("banscore", stats.nMisbehavior)); if (stats.fSyncNode) obj.push_back(Pair("syncnode", true)); ret.push_back(obj); } 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; } 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; }