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 " \"syncnode\": true|false (boolean) if sync node\n"
105 + HelpExampleCli("getpeerinfo", "")
106 + HelpExampleRpc("getpeerinfo", "")
109 vector<CNodeStats> vstats;
110 CopyNodeStats(vstats);
114 BOOST_FOREACH(const CNodeStats& stats, vstats) {
116 CNodeStateStats statestats;
117 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
118 obj.push_back(Pair("id", stats.nodeid));
119 obj.push_back(Pair("addr", stats.addrName));
120 if (!(stats.addrLocal.empty()))
121 obj.push_back(Pair("addrlocal", stats.addrLocal));
122 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
123 obj.push_back(Pair("lastsend", stats.nLastSend));
124 obj.push_back(Pair("lastrecv", stats.nLastRecv));
125 obj.push_back(Pair("bytessent", stats.nSendBytes));
126 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
127 obj.push_back(Pair("conntime", stats.nTimeConnected));
128 obj.push_back(Pair("pingtime", stats.dPingTime));
129 if (stats.dPingWait > 0.0)
130 obj.push_back(Pair("pingwait", stats.dPingWait));
131 obj.push_back(Pair("version", stats.nVersion));
132 // Use the sanitized form of subver here, to avoid tricksy remote peers from
133 // corrupting or modifiying the JSON output by putting special characters in
134 // their ver message.
135 obj.push_back(Pair("subver", stats.cleanSubVer));
136 obj.push_back(Pair("inbound", stats.fInbound));
137 obj.push_back(Pair("startingheight", stats.nStartingHeight));
139 obj.push_back(Pair("banscore", statestats.nMisbehavior));
140 obj.push_back(Pair("syncheight", statestats.nSyncHeight));
142 obj.push_back(Pair("syncnode", stats.fSyncNode));
143 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
151 Value addnode(const Array& params, bool fHelp)
154 if (params.size() == 2)
155 strCommand = params[1].get_str();
156 if (fHelp || params.size() != 2 ||
157 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
159 "addnode \"node\" \"add|remove|onetry\"\n"
160 "\nAttempts add or remove a node from the addnode list.\n"
161 "Or try a connection to a node once.\n"
163 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
164 "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"
166 + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
167 + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
170 string strNode = params[0].get_str();
172 if (strCommand == "onetry")
175 OpenNetworkConnection(addr, NULL, strNode.c_str());
179 LOCK(cs_vAddedNodes);
180 vector<string>::iterator it = vAddedNodes.begin();
181 for(; it != vAddedNodes.end(); it++)
185 if (strCommand == "add")
187 if (it != vAddedNodes.end())
188 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
189 vAddedNodes.push_back(strNode);
191 else if(strCommand == "remove")
193 if (it == vAddedNodes.end())
194 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
195 vAddedNodes.erase(it);
201 Value getaddednodeinfo(const Array& params, bool fHelp)
203 if (fHelp || params.size() < 1 || params.size() > 2)
205 "getaddednodeinfo dns ( \"node\" )\n"
206 "\nReturns information about the given added node, or all added nodes\n"
207 "(note that onetry addnodes are not listed here)\n"
208 "If dns is false, only a list of added nodes will be provided,\n"
209 "otherwise connected information will also be available.\n"
211 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
212 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
216 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
217 " \"connected\" : true|false, (boolean) If connected\n"
218 " \"addresses\" : [\n"
220 " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server host and port\n"
221 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
229 + HelpExampleCli("getaddednodeinfo", "true")
230 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
231 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
234 bool fDns = params[0].get_bool();
236 list<string> laddedNodes(0);
237 if (params.size() == 1)
239 LOCK(cs_vAddedNodes);
240 BOOST_FOREACH(string& strAddNode, vAddedNodes)
241 laddedNodes.push_back(strAddNode);
245 string strNode = params[1].get_str();
246 LOCK(cs_vAddedNodes);
247 BOOST_FOREACH(string& strAddNode, vAddedNodes)
248 if (strAddNode == strNode)
250 laddedNodes.push_back(strAddNode);
253 if (laddedNodes.size() == 0)
254 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
260 BOOST_FOREACH(string& strAddNode, laddedNodes)
263 obj.push_back(Pair("addednode", strAddNode));
269 list<pair<string, vector<CService> > > laddedAddreses(0);
270 BOOST_FOREACH(string& strAddNode, laddedNodes)
272 vector<CService> vservNode(0);
273 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
274 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
278 obj.push_back(Pair("addednode", strAddNode));
279 obj.push_back(Pair("connected", false));
281 obj.push_back(Pair("addresses", addresses));
286 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
289 obj.push_back(Pair("addednode", it->first));
292 bool fConnected = false;
293 BOOST_FOREACH(CService& addrNode, it->second)
297 node.push_back(Pair("address", addrNode.ToString()));
298 BOOST_FOREACH(CNode* pnode, vNodes)
299 if (pnode->addr == addrNode)
303 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
307 node.push_back(Pair("connected", "false"));
308 addresses.push_back(node);
310 obj.push_back(Pair("connected", fConnected));
311 obj.push_back(Pair("addresses", addresses));
318 Value getnettotals(const Array& params, bool fHelp)
320 if (fHelp || params.size() > 0)
323 "\nReturns information about network traffic, including bytes in, bytes out,\n"
324 "and current time.\n"
327 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
328 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
329 " \"timemillis\": t (numeric) Total cpu time\n"
332 + HelpExampleCli("getnettotals", "")
333 + HelpExampleRpc("getnettotals", "")
337 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
338 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
339 obj.push_back(Pair("timemillis", GetTimeMillis()));
343 static Array GetNetworksInfo()
346 for(int n=0; n<NET_MAX; ++n)
348 enum Network network = static_cast<enum Network>(n);
349 if(network == NET_UNROUTABLE)
353 GetProxy(network, proxy);
354 obj.push_back(Pair("name", GetNetworkName(network)));
355 obj.push_back(Pair("limited", IsLimited(network)));
356 obj.push_back(Pair("reachable", IsReachable(network)));
357 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string()));
358 networks.push_back(obj);
363 Value getnetworkinfo(const Array& params, bool fHelp)
365 if (fHelp || params.size() != 0)
368 "Returns an object containing various state info regarding P2P networking.\n"
371 " \"version\": xxxxx, (numeric) the server version\n"
372 " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n"
373 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
374 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
375 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
376 " \"connections\": xxxxx, (numeric) the number of connections\n"
377 " \"networks\": [ (array) information per network\n"
379 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
380 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
381 " \"reachable\": true|false, (boolean) is the network reachable?\n"
382 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
386 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
387 " \"localaddresses\": [ (array) list of local addresses\n"
389 " \"address\": \"xxxx\", (string) network address\n"
390 " \"port\": xxx, (numeric) network port\n"
391 " \"score\": xxx (numeric) relative score\n"
397 + HelpExampleCli("getnetworkinfo", "")
398 + HelpExampleRpc("getnetworkinfo", "")
402 obj.push_back(Pair("version", CLIENT_VERSION));
403 obj.push_back(Pair("subversion",
404 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
405 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
406 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
407 obj.push_back(Pair("timeoffset", GetTimeOffset()));
408 obj.push_back(Pair("connections", (int)vNodes.size()));
409 obj.push_back(Pair("networks", GetNetworksInfo()));
410 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
411 Array localAddresses;
413 LOCK(cs_mapLocalHost);
414 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
417 rec.push_back(Pair("address", item.first.ToString()));
418 rec.push_back(Pair("port", item.second.nPort));
419 rec.push_back(Pair("score", item.second.nScore));
420 localAddresses.push_back(rec);
423 obj.push_back(Pair("localaddresses", localAddresses));