Back to home page

Bitcoin sources

 
 

    


0001 // Copyright (c) 2009-2014 The Bitcoin developers
0002 // Distributed under the MIT software license, see the accompanying
0003 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
0004 
0005 #include "rpcserver.h"
0006 
0007 #include "clientversion.h"
0008 #include "main.h"
0009 #include "net.h"
0010 #include "netbase.h"
0011 #include "protocol.h"
0012 #include "sync.h"
0013 #include "timedata.h"
0014 #include "util.h"
0015 #include "version.h"
0016 
0017 #include <boost/foreach.hpp>
0018 
0019 #include "json/json_spirit_value.h"
0020 
0021 using namespace json_spirit;
0022 using namespace std;
0023 
0024 Value getconnectioncount(const Array& params, bool fHelp)
0025 {
0026     if (fHelp || params.size() != 0)
0027         throw runtime_error(
0028             "getconnectioncount\n"
0029             "\nReturns the number of connections to other nodes.\n"
0030             "\nbResult:\n"
0031             "n          (numeric) The connection count\n"
0032             "\nExamples:\n"
0033             + HelpExampleCli("getconnectioncount", "")
0034             + HelpExampleRpc("getconnectioncount", "")
0035         );
0036 
0037     LOCK(cs_vNodes);
0038     return (int)vNodes.size();
0039 }
0040 
0041 Value ping(const Array& params, bool fHelp)
0042 {
0043     if (fHelp || params.size() != 0)
0044         throw runtime_error(
0045             "ping\n"
0046             "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
0047             "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
0048             "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
0049             "\nExamples:\n"
0050             + HelpExampleCli("ping", "")
0051             + HelpExampleRpc("ping", "")
0052         );
0053 
0054     // Request that each node send a ping during next message processing pass
0055     LOCK(cs_vNodes);
0056     BOOST_FOREACH(CNode* pNode, vNodes) {
0057         pNode->fPingQueued = true;
0058     }
0059 
0060     return Value::null;
0061 }
0062 
0063 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
0064 {
0065     vstats.clear();
0066 
0067     LOCK(cs_vNodes);
0068     vstats.reserve(vNodes.size());
0069     BOOST_FOREACH(CNode* pnode, vNodes) {
0070         CNodeStats stats;
0071         pnode->copyStats(stats);
0072         vstats.push_back(stats);
0073     }
0074 }
0075 
0076 Value getpeerinfo(const Array& params, bool fHelp)
0077 {
0078     if (fHelp || params.size() != 0)
0079         throw runtime_error(
0080             "getpeerinfo\n"
0081             "\nReturns data about each connected network node as a json array of objects.\n"
0082             "\nbResult:\n"
0083             "[\n"
0084             "  {\n"
0085             "    \"id\": n,                   (numeric) Peer index\n"
0086             "    \"addr\":\"host:port\",      (string) The ip address and port of the peer\n"
0087             "    \"addrlocal\":\"ip:port\",   (string) local address\n"
0088             "    \"services\":\"xxxxxxxxxxxxxxxx\",   (string) The services offered\n"
0089             "    \"lastsend\": ttt,           (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
0090             "    \"lastrecv\": ttt,           (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
0091             "    \"bytessent\": n,            (numeric) The total bytes sent\n"
0092             "    \"bytesrecv\": n,            (numeric) The total bytes received\n"
0093             "    \"conntime\": ttt,           (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
0094             "    \"pingtime\": n,             (numeric) ping time\n"
0095             "    \"pingwait\": n,             (numeric) ping wait\n"
0096             "    \"version\": v,              (numeric) The peer version, such as 7001\n"
0097             "    \"subver\": \"/Satoshi:0.8.5/\",  (string) The string version\n"
0098             "    \"inbound\": true|false,     (boolean) Inbound (true) or Outbound (false)\n"
0099             "    \"startingheight\": n,       (numeric) The starting height (block) of the peer\n"
0100             "    \"banscore\": n,             (numeric) The ban score\n"
0101             "    \"synced_headers\": n,       (numeric) The last header we have in common with this peer\n"
0102             "    \"synced_blocks\": n,        (numeric) The last block we have in common with this peer\n"
0103             "    \"inflight\": [\n"
0104             "       n,                        (numeric) The heights of blocks we're currently asking from this peer\n"
0105             "       ...\n"
0106             "    ]\n"
0107             "  }\n"
0108             "  ,...\n"
0109             "]\n"
0110             "\nExamples:\n"
0111             + HelpExampleCli("getpeerinfo", "")
0112             + HelpExampleRpc("getpeerinfo", "")
0113         );
0114 
0115     vector<CNodeStats> vstats;
0116     CopyNodeStats(vstats);
0117 
0118     Array ret;
0119 
0120     BOOST_FOREACH(const CNodeStats& stats, vstats) {
0121         Object obj;
0122         CNodeStateStats statestats;
0123         bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
0124         obj.push_back(Pair("id", stats.nodeid));
0125         obj.push_back(Pair("addr", stats.addrName));
0126         if (!(stats.addrLocal.empty()))
0127             obj.push_back(Pair("addrlocal", stats.addrLocal));
0128         obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
0129         obj.push_back(Pair("lastsend", stats.nLastSend));
0130         obj.push_back(Pair("lastrecv", stats.nLastRecv));
0131         obj.push_back(Pair("bytessent", stats.nSendBytes));
0132         obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
0133         obj.push_back(Pair("conntime", stats.nTimeConnected));
0134         obj.push_back(Pair("pingtime", stats.dPingTime));
0135         if (stats.dPingWait > 0.0)
0136             obj.push_back(Pair("pingwait", stats.dPingWait));
0137         obj.push_back(Pair("version", stats.nVersion));
0138         // Use the sanitized form of subver here, to avoid tricksy remote peers from
0139         // corrupting or modifiying the JSON output by putting special characters in
0140         // their ver message.
0141         obj.push_back(Pair("subver", stats.cleanSubVer));
0142         obj.push_back(Pair("inbound", stats.fInbound));
0143         obj.push_back(Pair("startingheight", stats.nStartingHeight));
0144         if (fStateStats) {
0145             obj.push_back(Pair("banscore", statestats.nMisbehavior));
0146             obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
0147             obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
0148             Array heights;
0149             BOOST_FOREACH(int height, statestats.vHeightInFlight) {
0150                 heights.push_back(height);
0151             }
0152             obj.push_back(Pair("inflight", heights));
0153         }
0154         obj.push_back(Pair("whitelisted", stats.fWhitelisted));
0155 
0156         ret.push_back(obj);
0157     }
0158 
0159     return ret;
0160 }
0161 
0162 Value addnode(const Array& params, bool fHelp)
0163 {
0164     string strCommand;
0165     if (params.size() == 2)
0166         strCommand = params[1].get_str();
0167     if (fHelp || params.size() != 2 ||
0168         (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
0169         throw runtime_error(
0170             "addnode \"node\" \"add|remove|onetry\"\n"
0171             "\nAttempts add or remove a node from the addnode list.\n"
0172             "Or try a connection to a node once.\n"
0173             "\nArguments:\n"
0174             "1. \"node\"     (string, required) The node (see getpeerinfo for nodes)\n"
0175             "2. \"command\"  (string, required) 'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once\n"
0176             "\nExamples:\n"
0177             + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
0178             + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
0179         );
0180 
0181     string strNode = params[0].get_str();
0182 
0183     if (strCommand == "onetry")
0184     {
0185         CAddress addr;
0186         OpenNetworkConnection(addr, NULL, strNode.c_str());
0187         return Value::null;
0188     }
0189 
0190     LOCK(cs_vAddedNodes);
0191     vector<string>::iterator it = vAddedNodes.begin();
0192     for(; it != vAddedNodes.end(); it++)
0193         if (strNode == *it)
0194             break;
0195 
0196     if (strCommand == "add")
0197     {
0198         if (it != vAddedNodes.end())
0199             throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
0200         vAddedNodes.push_back(strNode);
0201     }
0202     else if(strCommand == "remove")
0203     {
0204         if (it == vAddedNodes.end())
0205             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
0206         vAddedNodes.erase(it);
0207     }
0208 
0209     return Value::null;
0210 }
0211 
0212 Value getaddednodeinfo(const Array& params, bool fHelp)
0213 {
0214     if (fHelp || params.size() < 1 || params.size() > 2)
0215         throw runtime_error(
0216             "getaddednodeinfo dns ( \"node\" )\n"
0217             "\nReturns information about the given added node, or all added nodes\n"
0218             "(note that onetry addnodes are not listed here)\n"
0219             "If dns is false, only a list of added nodes will be provided,\n"
0220             "otherwise connected information will also be available.\n"
0221             "\nArguments:\n"
0222             "1. dns        (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
0223             "2. \"node\"   (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
0224             "\nResult:\n"
0225             "[\n"
0226             "  {\n"
0227             "    \"addednode\" : \"192.168.0.201\",   (string) The node ip address\n"
0228             "    \"connected\" : true|false,          (boolean) If connected\n"
0229             "    \"addresses\" : [\n"
0230             "       {\n"
0231             "         \"address\" : \"192.168.0.201:8333\",  (string) The bitcoin server host and port\n"
0232             "         \"connected\" : \"outbound\"           (string) connection, inbound or outbound\n"
0233             "       }\n"
0234             "       ,...\n"
0235             "     ]\n"
0236             "  }\n"
0237             "  ,...\n"
0238             "]\n"
0239             "\nExamples:\n"
0240             + HelpExampleCli("getaddednodeinfo", "true")
0241             + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
0242             + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
0243         );
0244 
0245     bool fDns = params[0].get_bool();
0246 
0247     list<string> laddedNodes(0);
0248     if (params.size() == 1)
0249     {
0250         LOCK(cs_vAddedNodes);
0251         BOOST_FOREACH(string& strAddNode, vAddedNodes)
0252             laddedNodes.push_back(strAddNode);
0253     }
0254     else
0255     {
0256         string strNode = params[1].get_str();
0257         LOCK(cs_vAddedNodes);
0258         BOOST_FOREACH(string& strAddNode, vAddedNodes)
0259             if (strAddNode == strNode)
0260             {
0261                 laddedNodes.push_back(strAddNode);
0262                 break;
0263             }
0264         if (laddedNodes.size() == 0)
0265             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
0266     }
0267 
0268     Array ret;
0269     if (!fDns)
0270     {
0271         BOOST_FOREACH(string& strAddNode, laddedNodes)
0272         {
0273             Object obj;
0274             obj.push_back(Pair("addednode", strAddNode));
0275             ret.push_back(obj);
0276         }
0277         return ret;
0278     }
0279 
0280     list<pair<string, vector<CService> > > laddedAddreses(0);
0281     BOOST_FOREACH(string& strAddNode, laddedNodes)
0282     {
0283         vector<CService> vservNode(0);
0284         if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
0285             laddedAddreses.push_back(make_pair(strAddNode, vservNode));
0286         else
0287         {
0288             Object obj;
0289             obj.push_back(Pair("addednode", strAddNode));
0290             obj.push_back(Pair("connected", false));
0291             Array addresses;
0292             obj.push_back(Pair("addresses", addresses));
0293         }
0294     }
0295 
0296     LOCK(cs_vNodes);
0297     for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
0298     {
0299         Object obj;
0300         obj.push_back(Pair("addednode", it->first));
0301 
0302         Array addresses;
0303         bool fConnected = false;
0304         BOOST_FOREACH(CService& addrNode, it->second)
0305         {
0306             bool fFound = false;
0307             Object node;
0308             node.push_back(Pair("address", addrNode.ToString()));
0309             BOOST_FOREACH(CNode* pnode, vNodes)
0310                 if (pnode->addr == addrNode)
0311                 {
0312                     fFound = true;
0313                     fConnected = true;
0314                     node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
0315                     break;
0316                 }
0317             if (!fFound)
0318                 node.push_back(Pair("connected", "false"));
0319             addresses.push_back(node);
0320         }
0321         obj.push_back(Pair("connected", fConnected));
0322         obj.push_back(Pair("addresses", addresses));
0323         ret.push_back(obj);
0324     }
0325 
0326     return ret;
0327 }
0328 
0329 Value getnettotals(const Array& params, bool fHelp)
0330 {
0331     if (fHelp || params.size() > 0)
0332         throw runtime_error(
0333             "getnettotals\n"
0334             "\nReturns information about network traffic, including bytes in, bytes out,\n"
0335             "and current time.\n"
0336             "\nResult:\n"
0337             "{\n"
0338             "  \"totalbytesrecv\": n,   (numeric) Total bytes received\n"
0339             "  \"totalbytessent\": n,   (numeric) Total bytes sent\n"
0340             "  \"timemillis\": t        (numeric) Total cpu time\n"
0341             "}\n"
0342             "\nExamples:\n"
0343             + HelpExampleCli("getnettotals", "")
0344             + HelpExampleRpc("getnettotals", "")
0345        );
0346 
0347     Object obj;
0348     obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
0349     obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
0350     obj.push_back(Pair("timemillis", GetTimeMillis()));
0351     return obj;
0352 }
0353 
0354 static Array GetNetworksInfo()
0355 {
0356     Array networks;
0357     for(int n=0; n<NET_MAX; ++n)
0358     {
0359         enum Network network = static_cast<enum Network>(n);
0360         if(network == NET_UNROUTABLE)
0361             continue;
0362         proxyType proxy;
0363         Object obj;
0364         GetProxy(network, proxy);
0365         obj.push_back(Pair("name", GetNetworkName(network)));
0366         obj.push_back(Pair("limited", IsLimited(network)));
0367         obj.push_back(Pair("reachable", IsReachable(network)));
0368         obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string()));
0369         networks.push_back(obj);
0370     }
0371     return networks;
0372 }
0373 
0374 Value getnetworkinfo(const Array& params, bool fHelp)
0375 {
0376     if (fHelp || params.size() != 0)
0377         throw runtime_error(
0378             "getnetworkinfo\n"
0379             "Returns an object containing various state info regarding P2P networking.\n"
0380             "\nResult:\n"
0381             "{\n"
0382             "  \"version\": xxxxx,                      (numeric) the server version\n"
0383             "  \"subversion\": \"/Satoshi:x.x.x/\",     (string) the server subversion string\n"
0384             "  \"protocolversion\": xxxxx,              (numeric) the protocol version\n"
0385             "  \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
0386             "  \"timeoffset\": xxxxx,                   (numeric) the time offset\n"
0387             "  \"connections\": xxxxx,                  (numeric) the number of connections\n"
0388             "  \"networks\": [                          (array) information per network\n"
0389             "  {\n"
0390             "    \"name\": \"xxx\",                     (string) network (ipv4, ipv6 or onion)\n"
0391             "    \"limited\": true|false,               (boolean) is the network limited using -onlynet?\n"
0392             "    \"reachable\": true|false,             (boolean) is the network reachable?\n"
0393             "    \"proxy\": \"host:port\"               (string) the proxy that is used for this network, or empty if none\n"
0394             "  }\n"
0395             "  ,...\n"
0396             "  ],\n"
0397             "  \"relayfee\": x.xxxxxxxx,                (numeric) minimum relay fee for non-free transactions in btc/kb\n"
0398             "  \"localaddresses\": [                    (array) list of local addresses\n"
0399             "  {\n"
0400             "    \"address\": \"xxxx\",                 (string) network address\n"
0401             "    \"port\": xxx,                         (numeric) network port\n"
0402             "    \"score\": xxx                         (numeric) relative score\n"
0403             "  }\n"
0404             "  ,...\n"
0405             "  ]\n"
0406             "}\n"
0407             "\nExamples:\n"
0408             + HelpExampleCli("getnetworkinfo", "")
0409             + HelpExampleRpc("getnetworkinfo", "")
0410         );
0411 
0412     Object obj;
0413     obj.push_back(Pair("version",       CLIENT_VERSION));
0414     obj.push_back(Pair("subversion",
0415         FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
0416     obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
0417     obj.push_back(Pair("localservices",       strprintf("%016x", nLocalServices)));
0418     obj.push_back(Pair("timeoffset",    GetTimeOffset()));
0419     obj.push_back(Pair("connections",   (int)vNodes.size()));
0420     obj.push_back(Pair("networks",      GetNetworksInfo()));
0421     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
0422     Array localAddresses;
0423     {
0424         LOCK(cs_mapLocalHost);
0425         BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
0426         {
0427             Object rec;
0428             rec.push_back(Pair("address", item.first.ToString()));
0429             rec.push_back(Pair("port", item.second.nPort));
0430             rec.push_back(Pair("score", item.second.nScore));
0431             localAddresses.push_back(rec);
0432         }
0433     }
0434     obj.push_back(Pair("localaddresses", localAddresses));
0435     return obj;
0436 }