1 // Copyright (c) 2009-2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #include "clientversion.h"
17 #include <boost/foreach.hpp>
19 #include "json/json_spirit_value.h"
21 using namespace json_spirit;
24 Value getconnectioncount(const Array& params, bool fHelp)
26 if (fHelp || params.size() != 0)
28 "getconnectioncount\n"
29 "\nReturns the number of connections to other nodes.\n"
31 "n (numeric) The connection count\n"
33 + HelpExampleCli("getconnectioncount", "")
34 + HelpExampleRpc("getconnectioncount", "")
38 return (int)vNodes.size();
41 Value ping(const Array& params, bool fHelp)
43 if (fHelp || params.size() != 0)
46 "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
47 "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
48 "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
50 + HelpExampleCli("ping", "")
51 + HelpExampleRpc("ping", "")
54 // Request that each node send a ping during next message processing pass
56 BOOST_FOREACH(CNode* pNode, vNodes) {
57 pNode->fPingQueued = true;
63 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
68 vstats.reserve(vNodes.size());
69 BOOST_FOREACH(CNode* pnode, vNodes) {
71 pnode->copyStats(stats);
72 vstats.push_back(stats);
76 Value getpeerinfo(const Array& params, bool fHelp)
78 if (fHelp || params.size() != 0)
81 "\nReturns data about each connected network node as a json array of objects.\n"
85 " \"id\": n, (numeric) Peer index\n"
86 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
87 " \"addrlocal\":\"ip:port\", (string) local address\n"
88 " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
89 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
90 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
91 " \"bytessent\": n, (numeric) The total bytes sent\n"
92 " \"bytesrecv\": n, (numeric) The total bytes received\n"
93 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
94 " \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
95 " \"pingtime\": n, (numeric) ping time\n"
96 " \"pingwait\": n, (numeric) ping wait\n"
97 " \"version\": v, (numeric) The peer version, such as 7001\n"
98 " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
99 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
100 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
101 " \"banscore\": n, (numeric) The ban score\n"
102 " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
103 " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
105 " n, (numeric) The heights of blocks we're currently asking from this peer\n"
112 + HelpExampleCli("getpeerinfo", "")
113 + HelpExampleRpc("getpeerinfo", "")
116 vector<CNodeStats> vstats;
117 CopyNodeStats(vstats);
121 BOOST_FOREACH(const CNodeStats& stats, vstats) {
123 CNodeStateStats statestats;
124 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
125 obj.push_back(Pair("id", stats.nodeid));
126 obj.push_back(Pair("addr", stats.addrName));
127 if (!(stats.addrLocal.empty()))
128 obj.push_back(Pair("addrlocal", stats.addrLocal));
129 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
130 obj.push_back(Pair("lastsend", stats.nLastSend));
131 obj.push_back(Pair("lastrecv", stats.nLastRecv));
132 obj.push_back(Pair("bytessent", stats.nSendBytes));
133 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
134 obj.push_back(Pair("conntime", stats.nTimeConnected));
135 obj.push_back(Pair("timeoffset", stats.nTimeOffset));
136 obj.push_back(Pair("pingtime", stats.dPingTime));
137 if (stats.dPingWait > 0.0)
138 obj.push_back(Pair("pingwait", stats.dPingWait));
139 obj.push_back(Pair("version", stats.nVersion));
140 // Use the sanitized form of subver here, to avoid tricksy remote peers from
141 // corrupting or modifiying the JSON output by putting special characters in
142 // their ver message.
143 obj.push_back(Pair("subver", stats.cleanSubVer));
144 obj.push_back(Pair("inbound", stats.fInbound));
145 obj.push_back(Pair("startingheight", stats.nStartingHeight));
147 obj.push_back(Pair("banscore", statestats.nMisbehavior));
148 obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
149 obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
151 BOOST_FOREACH(int height, statestats.vHeightInFlight) {
152 heights.push_back(height);
154 obj.push_back(Pair("inflight", heights));
156 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
164 Value addnode(const Array& params, bool fHelp)
167 if (params.size() == 2)
168 strCommand = params[1].get_str();
169 if (fHelp || params.size() != 2 ||
170 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
172 "addnode \"node\" \"add|remove|onetry\"\n"
173 "\nAttempts add or remove a node from the addnode list.\n"
174 "Or try a connection to a node once.\n"
176 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
177 "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"
179 + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
180 + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
183 string strNode = params[0].get_str();
185 if (strCommand == "onetry")
188 OpenNetworkConnection(addr, NULL, strNode.c_str());
192 LOCK(cs_vAddedNodes);
193 vector<string>::iterator it = vAddedNodes.begin();
194 for(; it != vAddedNodes.end(); it++)
198 if (strCommand == "add")
200 if (it != vAddedNodes.end())
201 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
202 vAddedNodes.push_back(strNode);
204 else if(strCommand == "remove")
206 if (it == vAddedNodes.end())
207 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
208 vAddedNodes.erase(it);
214 Value getaddednodeinfo(const Array& params, bool fHelp)
216 if (fHelp || params.size() < 1 || params.size() > 2)
218 "getaddednodeinfo dns ( \"node\" )\n"
219 "\nReturns information about the given added node, or all added nodes\n"
220 "(note that onetry addnodes are not listed here)\n"
221 "If dns is false, only a list of added nodes will be provided,\n"
222 "otherwise connected information will also be available.\n"
224 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
225 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
229 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
230 " \"connected\" : true|false, (boolean) If connected\n"
231 " \"addresses\" : [\n"
233 " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server host and port\n"
234 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
242 + HelpExampleCli("getaddednodeinfo", "true")
243 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
244 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
247 bool fDns = params[0].get_bool();
249 list<string> laddedNodes(0);
250 if (params.size() == 1)
252 LOCK(cs_vAddedNodes);
253 BOOST_FOREACH(string& strAddNode, vAddedNodes)
254 laddedNodes.push_back(strAddNode);
258 string strNode = params[1].get_str();
259 LOCK(cs_vAddedNodes);
260 BOOST_FOREACH(string& strAddNode, vAddedNodes)
261 if (strAddNode == strNode)
263 laddedNodes.push_back(strAddNode);
266 if (laddedNodes.size() == 0)
267 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
273 BOOST_FOREACH(string& strAddNode, laddedNodes)
276 obj.push_back(Pair("addednode", strAddNode));
282 list<pair<string, vector<CService> > > laddedAddreses(0);
283 BOOST_FOREACH(string& strAddNode, laddedNodes)
285 vector<CService> vservNode(0);
286 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
287 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
291 obj.push_back(Pair("addednode", strAddNode));
292 obj.push_back(Pair("connected", false));
294 obj.push_back(Pair("addresses", addresses));
299 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
302 obj.push_back(Pair("addednode", it->first));
305 bool fConnected = false;
306 BOOST_FOREACH(CService& addrNode, it->second)
310 node.push_back(Pair("address", addrNode.ToString()));
311 BOOST_FOREACH(CNode* pnode, vNodes)
312 if (pnode->addr == addrNode)
316 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
320 node.push_back(Pair("connected", "false"));
321 addresses.push_back(node);
323 obj.push_back(Pair("connected", fConnected));
324 obj.push_back(Pair("addresses", addresses));
331 Value getnettotals(const Array& params, bool fHelp)
333 if (fHelp || params.size() > 0)
336 "\nReturns information about network traffic, including bytes in, bytes out,\n"
337 "and current time.\n"
340 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
341 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
342 " \"timemillis\": t (numeric) Total cpu time\n"
345 + HelpExampleCli("getnettotals", "")
346 + HelpExampleRpc("getnettotals", "")
350 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
351 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
352 obj.push_back(Pair("timemillis", GetTimeMillis()));
356 static Array GetNetworksInfo()
359 for(int n=0; n<NET_MAX; ++n)
361 enum Network network = static_cast<enum Network>(n);
362 if(network == NET_UNROUTABLE)
366 GetProxy(network, proxy);
367 obj.push_back(Pair("name", GetNetworkName(network)));
368 obj.push_back(Pair("limited", IsLimited(network)));
369 obj.push_back(Pair("reachable", IsReachable(network)));
370 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string()));
371 networks.push_back(obj);
376 Value getnetworkinfo(const Array& params, bool fHelp)
378 if (fHelp || params.size() != 0)
381 "Returns an object containing various state info regarding P2P networking.\n"
384 " \"version\": xxxxx, (numeric) the server version\n"
385 " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n"
386 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
387 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
388 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
389 " \"connections\": xxxxx, (numeric) the number of connections\n"
390 " \"networks\": [ (array) information per network\n"
392 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
393 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
394 " \"reachable\": true|false, (boolean) is the network reachable?\n"
395 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
399 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
400 " \"localaddresses\": [ (array) list of local addresses\n"
402 " \"address\": \"xxxx\", (string) network address\n"
403 " \"port\": xxx, (numeric) network port\n"
404 " \"score\": xxx (numeric) relative score\n"
410 + HelpExampleCli("getnetworkinfo", "")
411 + HelpExampleRpc("getnetworkinfo", "")
415 obj.push_back(Pair("version", CLIENT_VERSION));
416 obj.push_back(Pair("subversion",
417 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
418 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
419 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
420 obj.push_back(Pair("timeoffset", GetTimeOffset()));
421 obj.push_back(Pair("connections", (int)vNodes.size()));
422 obj.push_back(Pair("networks", GetNetworksInfo()));
423 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
424 Array localAddresses;
426 LOCK(cs_mapLocalHost);
427 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
430 rec.push_back(Pair("address", item.first.ToString()));
431 rec.push_back(Pair("port", item.second.nPort));
432 rec.push_back(Pair("score", item.second.nScore));
433 localAddresses.push_back(rec);
436 obj.push_back(Pair("localaddresses", localAddresses));