1 // Copyright (c) 2009-2014 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
16 #include <boost/foreach.hpp>
18 #include "json/json_spirit_value.h"
20 using namespace json_spirit;
23 Value getconnectioncount(const Array& params, bool fHelp)
25 if (fHelp || params.size() != 0)
27 "getconnectioncount\n"
28 "\nReturns the number of connections to other nodes.\n"
30 "n (numeric) The connection count\n"
32 + HelpExampleCli("getconnectioncount", "")
33 + HelpExampleRpc("getconnectioncount", "")
37 return (int)vNodes.size();
40 Value ping(const Array& params, bool fHelp)
42 if (fHelp || params.size() != 0)
45 "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
46 "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
47 "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
49 + HelpExampleCli("ping", "")
50 + HelpExampleRpc("ping", "")
53 // Request that each node send a ping during next message processing pass
55 BOOST_FOREACH(CNode* pNode, vNodes) {
56 pNode->fPingQueued = true;
62 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
67 vstats.reserve(vNodes.size());
68 BOOST_FOREACH(CNode* pnode, vNodes) {
70 pnode->copyStats(stats);
71 vstats.push_back(stats);
75 Value getpeerinfo(const Array& params, bool fHelp)
77 if (fHelp || params.size() != 0)
80 "\nReturns data about each connected network node as a json array of objects.\n"
84 " \"id\": n, (numeric) Peer index\n"
85 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
86 " \"addrlocal\":\"ip:port\", (string) local address\n"
87 " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
88 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
89 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
90 " \"bytessent\": n, (numeric) The total bytes sent\n"
91 " \"bytesrecv\": n, (numeric) The total bytes received\n"
92 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
93 " \"pingtime\": n, (numeric) ping time\n"
94 " \"pingwait\": n, (numeric) ping wait\n"
95 " \"version\": v, (numeric) The peer version, such as 7001\n"
96 " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
97 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
98 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
99 " \"banscore\": n, (numeric) The ban score\n"
100 " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
101 " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
103 " n, (numeric) The heights of blocks we're currently asking from this peer\n"
110 + HelpExampleCli("getpeerinfo", "")
111 + HelpExampleRpc("getpeerinfo", "")
114 vector<CNodeStats> vstats;
115 CopyNodeStats(vstats);
119 BOOST_FOREACH(const CNodeStats& stats, vstats) {
121 CNodeStateStats statestats;
122 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
123 obj.push_back(Pair("id", stats.nodeid));
124 obj.push_back(Pair("addr", stats.addrName));
125 if (!(stats.addrLocal.empty()))
126 obj.push_back(Pair("addrlocal", stats.addrLocal));
127 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
128 obj.push_back(Pair("lastsend", stats.nLastSend));
129 obj.push_back(Pair("lastrecv", stats.nLastRecv));
130 obj.push_back(Pair("bytessent", stats.nSendBytes));
131 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
132 obj.push_back(Pair("conntime", stats.nTimeConnected));
133 obj.push_back(Pair("pingtime", stats.dPingTime));
134 if (stats.dPingWait > 0.0)
135 obj.push_back(Pair("pingwait", stats.dPingWait));
136 obj.push_back(Pair("version", stats.nVersion));
137 // Use the sanitized form of subver here, to avoid tricksy remote peers from
138 // corrupting or modifiying the JSON output by putting special characters in
139 // their ver message.
140 obj.push_back(Pair("subver", stats.cleanSubVer));
141 obj.push_back(Pair("inbound", stats.fInbound));
142 obj.push_back(Pair("startingheight", stats.nStartingHeight));
144 obj.push_back(Pair("banscore", statestats.nMisbehavior));
145 obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
146 obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
148 BOOST_FOREACH(int height, statestats.vHeightInFlight) {
149 heights.push_back(height);
151 obj.push_back(Pair("inflight", heights));
153 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
161 Value addnode(const Array& params, bool fHelp)
164 if (params.size() == 2)
165 strCommand = params[1].get_str();
166 if (fHelp || params.size() != 2 ||
167 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
169 "addnode \"node\" \"add|remove|onetry\"\n"
170 "\nAttempts add or remove a node from the addnode list.\n"
171 "Or try a connection to a node once.\n"
173 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
174 "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"
176 + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
177 + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
180 string strNode = params[0].get_str();
182 if (strCommand == "onetry")
185 OpenNetworkConnection(addr, NULL, strNode.c_str());
189 LOCK(cs_vAddedNodes);
190 vector<string>::iterator it = vAddedNodes.begin();
191 for(; it != vAddedNodes.end(); it++)
195 if (strCommand == "add")
197 if (it != vAddedNodes.end())
198 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
199 vAddedNodes.push_back(strNode);
201 else if(strCommand == "remove")
203 if (it == vAddedNodes.end())
204 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
205 vAddedNodes.erase(it);
211 Value getaddednodeinfo(const Array& params, bool fHelp)
213 if (fHelp || params.size() < 1 || params.size() > 2)
215 "getaddednodeinfo dns ( \"node\" )\n"
216 "\nReturns information about the given added node, or all added nodes\n"
217 "(note that onetry addnodes are not listed here)\n"
218 "If dns is false, only a list of added nodes will be provided,\n"
219 "otherwise connected information will also be available.\n"
221 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
222 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
226 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
227 " \"connected\" : true|false, (boolean) If connected\n"
228 " \"addresses\" : [\n"
230 " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server host and port\n"
231 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
239 + HelpExampleCli("getaddednodeinfo", "true")
240 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
241 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
244 bool fDns = params[0].get_bool();
246 list<string> laddedNodes(0);
247 if (params.size() == 1)
249 LOCK(cs_vAddedNodes);
250 BOOST_FOREACH(string& strAddNode, vAddedNodes)
251 laddedNodes.push_back(strAddNode);
255 string strNode = params[1].get_str();
256 LOCK(cs_vAddedNodes);
257 BOOST_FOREACH(string& strAddNode, vAddedNodes)
258 if (strAddNode == strNode)
260 laddedNodes.push_back(strAddNode);
263 if (laddedNodes.size() == 0)
264 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
270 BOOST_FOREACH(string& strAddNode, laddedNodes)
273 obj.push_back(Pair("addednode", strAddNode));
279 list<pair<string, vector<CService> > > laddedAddreses(0);
280 BOOST_FOREACH(string& strAddNode, laddedNodes)
282 vector<CService> vservNode(0);
283 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
284 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
288 obj.push_back(Pair("addednode", strAddNode));
289 obj.push_back(Pair("connected", false));
291 obj.push_back(Pair("addresses", addresses));
296 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
299 obj.push_back(Pair("addednode", it->first));
302 bool fConnected = false;
303 BOOST_FOREACH(CService& addrNode, it->second)
307 node.push_back(Pair("address", addrNode.ToString()));
308 BOOST_FOREACH(CNode* pnode, vNodes)
309 if (pnode->addr == addrNode)
313 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
317 node.push_back(Pair("connected", "false"));
318 addresses.push_back(node);
320 obj.push_back(Pair("connected", fConnected));
321 obj.push_back(Pair("addresses", addresses));
328 Value getnettotals(const Array& params, bool fHelp)
330 if (fHelp || params.size() > 0)
333 "\nReturns information about network traffic, including bytes in, bytes out,\n"
334 "and current time.\n"
337 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
338 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
339 " \"timemillis\": t (numeric) Total cpu time\n"
342 + HelpExampleCli("getnettotals", "")
343 + HelpExampleRpc("getnettotals", "")
347 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
348 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
349 obj.push_back(Pair("timemillis", GetTimeMillis()));
353 static Array GetNetworksInfo()
356 for(int n=0; n<NET_MAX; ++n)
358 enum Network network = static_cast<enum Network>(n);
359 if(network == NET_UNROUTABLE)
363 GetProxy(network, proxy);
364 obj.push_back(Pair("name", GetNetworkName(network)));
365 obj.push_back(Pair("limited", IsLimited(network)));
366 obj.push_back(Pair("reachable", IsReachable(network)));
367 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string()));
368 networks.push_back(obj);
373 Value getnetworkinfo(const Array& params, bool fHelp)
375 if (fHelp || params.size() != 0)
378 "Returns an object containing various state info regarding P2P networking.\n"
381 " \"version\": xxxxx, (numeric) the server version\n"
382 " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n"
383 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
384 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
385 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
386 " \"connections\": xxxxx, (numeric) the number of connections\n"
387 " \"networks\": [ (array) information per network\n"
389 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
390 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
391 " \"reachable\": true|false, (boolean) is the network reachable?\n"
392 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
396 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
397 " \"localaddresses\": [ (array) list of local addresses\n"
399 " \"address\": \"xxxx\", (string) network address\n"
400 " \"port\": xxx, (numeric) network port\n"
401 " \"score\": xxx (numeric) relative score\n"
407 + HelpExampleCli("getnetworkinfo", "")
408 + HelpExampleRpc("getnetworkinfo", "")
412 obj.push_back(Pair("version", CLIENT_VERSION));
413 obj.push_back(Pair("subversion",
414 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
415 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
416 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
417 obj.push_back(Pair("timeoffset", GetTimeOffset()));
418 obj.push_back(Pair("connections", (int)vNodes.size()));
419 obj.push_back(Pair("networks", GetNetworksInfo()));
420 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
421 Array localAddresses;
423 LOCK(cs_mapLocalHost);
424 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
427 rec.push_back(Pair("address", item.first.ToString()));
428 rec.push_back(Pair("port", item.second.nPort));
429 rec.push_back(Pair("score", item.second.nScore));
430 localAddresses.push_back(rec);
433 obj.push_back(Pair("localaddresses", localAddresses));