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", "")
37 LOCK2(cs_main, cs_vNodes);
39 return (int)vNodes.size();
42 Value ping(const Array& params, bool fHelp)
44 if (fHelp || params.size() != 0)
47 "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
48 "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
49 "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
51 + HelpExampleCli("ping", "")
52 + HelpExampleRpc("ping", "")
55 // Request that each node send a ping during next message processing pass
56 LOCK2(cs_main, cs_vNodes);
58 BOOST_FOREACH(CNode* pNode, vNodes) {
59 pNode->fPingQueued = true;
65 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
70 vstats.reserve(vNodes.size());
71 BOOST_FOREACH(CNode* pnode, vNodes) {
73 pnode->copyStats(stats);
74 vstats.push_back(stats);
78 Value getpeerinfo(const Array& params, bool fHelp)
80 if (fHelp || params.size() != 0)
83 "\nReturns data about each connected network node as a json array of objects.\n"
87 " \"id\": n, (numeric) Peer index\n"
88 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
89 " \"addrlocal\":\"ip:port\", (string) local address\n"
90 " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
91 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
92 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
93 " \"bytessent\": n, (numeric) The total bytes sent\n"
94 " \"bytesrecv\": n, (numeric) The total bytes received\n"
95 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
96 " \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
97 " \"pingtime\": n, (numeric) ping time\n"
98 " \"pingwait\": n, (numeric) ping wait\n"
99 " \"version\": v, (numeric) The peer version, such as 170002\n"
100 " \"subver\": \"/MagicBean:x.y.z[-v]/\", (string) The string version\n"
101 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
102 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
103 " \"banscore\": n, (numeric) The ban score\n"
104 " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
105 " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
107 " n, (numeric) The heights of blocks we're currently asking from this peer\n"
114 + HelpExampleCli("getpeerinfo", "")
115 + HelpExampleRpc("getpeerinfo", "")
120 vector<CNodeStats> vstats;
121 CopyNodeStats(vstats);
125 BOOST_FOREACH(const CNodeStats& stats, vstats) {
127 CNodeStateStats statestats;
128 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
129 obj.push_back(Pair("id", stats.nodeid));
130 obj.push_back(Pair("addr", stats.addrName));
131 if (!(stats.addrLocal.empty()))
132 obj.push_back(Pair("addrlocal", stats.addrLocal));
133 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
134 obj.push_back(Pair("lastsend", stats.nLastSend));
135 obj.push_back(Pair("lastrecv", stats.nLastRecv));
136 obj.push_back(Pair("bytessent", stats.nSendBytes));
137 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
138 obj.push_back(Pair("conntime", stats.nTimeConnected));
139 obj.push_back(Pair("timeoffset", stats.nTimeOffset));
140 obj.push_back(Pair("pingtime", stats.dPingTime));
141 if (stats.dPingWait > 0.0)
142 obj.push_back(Pair("pingwait", stats.dPingWait));
143 obj.push_back(Pair("version", stats.nVersion));
144 // Use the sanitized form of subver here, to avoid tricksy remote peers from
145 // corrupting or modifiying the JSON output by putting special characters in
146 // their ver message.
147 obj.push_back(Pair("subver", stats.cleanSubVer));
148 obj.push_back(Pair("inbound", stats.fInbound));
149 obj.push_back(Pair("startingheight", stats.nStartingHeight));
151 obj.push_back(Pair("banscore", statestats.nMisbehavior));
152 obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
153 obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
155 BOOST_FOREACH(int height, statestats.vHeightInFlight) {
156 heights.push_back(height);
158 obj.push_back(Pair("inflight", heights));
160 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
168 Value addnode(const Array& params, bool fHelp)
171 if (params.size() == 2)
172 strCommand = params[1].get_str();
173 if (fHelp || params.size() != 2 ||
174 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
176 "addnode \"node\" \"add|remove|onetry\"\n"
177 "\nAttempts add or remove a node from the addnode list.\n"
178 "Or try a connection to a node once.\n"
180 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
181 "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"
183 + HelpExampleCli("addnode", "\"192.168.0.6:8233\" \"onetry\"")
184 + HelpExampleRpc("addnode", "\"192.168.0.6:8233\", \"onetry\"")
187 string strNode = params[0].get_str();
189 if (strCommand == "onetry")
192 OpenNetworkConnection(addr, NULL, strNode.c_str());
196 LOCK(cs_vAddedNodes);
197 vector<string>::iterator it = vAddedNodes.begin();
198 for(; it != vAddedNodes.end(); it++)
202 if (strCommand == "add")
204 if (it != vAddedNodes.end())
205 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
206 vAddedNodes.push_back(strNode);
208 else if(strCommand == "remove")
210 if (it == vAddedNodes.end())
211 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
212 vAddedNodes.erase(it);
218 Value getaddednodeinfo(const Array& params, bool fHelp)
220 if (fHelp || params.size() < 1 || params.size() > 2)
222 "getaddednodeinfo dns ( \"node\" )\n"
223 "\nReturns information about the given added node, or all added nodes\n"
224 "(note that onetry addnodes are not listed here)\n"
225 "If dns is false, only a list of added nodes will be provided,\n"
226 "otherwise connected information will also be available.\n"
228 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
229 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
233 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
234 " \"connected\" : true|false, (boolean) If connected\n"
235 " \"addresses\" : [\n"
237 " \"address\" : \"192.168.0.201:8233\", (string) The bitcoin server host and port\n"
238 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
246 + HelpExampleCli("getaddednodeinfo", "true")
247 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
248 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
251 bool fDns = params[0].get_bool();
253 list<string> laddedNodes(0);
254 if (params.size() == 1)
256 LOCK(cs_vAddedNodes);
257 BOOST_FOREACH(string& strAddNode, vAddedNodes)
258 laddedNodes.push_back(strAddNode);
262 string strNode = params[1].get_str();
263 LOCK(cs_vAddedNodes);
264 BOOST_FOREACH(string& strAddNode, vAddedNodes)
265 if (strAddNode == strNode)
267 laddedNodes.push_back(strAddNode);
270 if (laddedNodes.size() == 0)
271 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
277 BOOST_FOREACH(string& strAddNode, laddedNodes)
280 obj.push_back(Pair("addednode", strAddNode));
286 list<pair<string, vector<CService> > > laddedAddreses(0);
287 BOOST_FOREACH(string& strAddNode, laddedNodes)
289 vector<CService> vservNode(0);
290 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
291 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
295 obj.push_back(Pair("addednode", strAddNode));
296 obj.push_back(Pair("connected", false));
298 obj.push_back(Pair("addresses", addresses));
303 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
306 obj.push_back(Pair("addednode", it->first));
309 bool fConnected = false;
310 BOOST_FOREACH(CService& addrNode, it->second)
314 node.push_back(Pair("address", addrNode.ToString()));
315 BOOST_FOREACH(CNode* pnode, vNodes)
316 if (pnode->addr == addrNode)
320 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
324 node.push_back(Pair("connected", "false"));
325 addresses.push_back(node);
327 obj.push_back(Pair("connected", fConnected));
328 obj.push_back(Pair("addresses", addresses));
335 Value getnettotals(const Array& params, bool fHelp)
337 if (fHelp || params.size() > 0)
340 "\nReturns information about network traffic, including bytes in, bytes out,\n"
341 "and current time.\n"
344 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
345 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
346 " \"timemillis\": t (numeric) Total cpu time\n"
349 + HelpExampleCli("getnettotals", "")
350 + HelpExampleRpc("getnettotals", "")
354 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
355 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
356 obj.push_back(Pair("timemillis", GetTimeMillis()));
360 static Array GetNetworksInfo()
363 for(int n=0; n<NET_MAX; ++n)
365 enum Network network = static_cast<enum Network>(n);
366 if(network == NET_UNROUTABLE)
370 GetProxy(network, proxy);
371 obj.push_back(Pair("name", GetNetworkName(network)));
372 obj.push_back(Pair("limited", IsLimited(network)));
373 obj.push_back(Pair("reachable", IsReachable(network)));
374 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
375 obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
376 networks.push_back(obj);
381 Value getnetworkinfo(const Array& params, bool fHelp)
383 if (fHelp || params.size() != 0)
386 "Returns an object containing various state info regarding P2P networking.\n"
389 " \"version\": xxxxx, (numeric) the server version\n"
390 " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n"
391 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
392 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
393 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
394 " \"connections\": xxxxx, (numeric) the number of connections\n"
395 " \"networks\": [ (array) information per network\n"
397 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
398 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
399 " \"reachable\": true|false, (boolean) is the network reachable?\n"
400 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
404 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
405 " \"localaddresses\": [ (array) list of local addresses\n"
407 " \"address\": \"xxxx\", (string) network address\n"
408 " \"port\": xxx, (numeric) network port\n"
409 " \"score\": xxx (numeric) relative score\n"
415 + HelpExampleCli("getnetworkinfo", "")
416 + HelpExampleRpc("getnetworkinfo", "")
422 obj.push_back(Pair("version", CLIENT_VERSION));
423 obj.push_back(Pair("subversion",
424 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
425 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
426 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
427 obj.push_back(Pair("timeoffset", GetTimeOffset()));
428 obj.push_back(Pair("connections", (int)vNodes.size()));
429 obj.push_back(Pair("networks", GetNetworksInfo()));
430 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
431 Array localAddresses;
433 LOCK(cs_mapLocalHost);
434 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
437 rec.push_back(Pair("address", item.first.ToString()));
438 rec.push_back(Pair("port", item.second.nPort));
439 rec.push_back(Pair("score", item.second.nScore));
440 localAddresses.push_back(rec);
443 obj.push_back(Pair("localaddresses", localAddresses));