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.
15 #include <boost/foreach.hpp>
17 #include "json/json_spirit_value.h"
19 using namespace json_spirit;
22 Value getconnectioncount(const Array& params, bool fHelp)
24 if (fHelp || params.size() != 0)
26 "getconnectioncount\n"
27 "\nReturns the number of connections to other nodes.\n"
29 "n (numeric) The connection count\n"
31 + HelpExampleCli("getconnectioncount", "")
32 + HelpExampleRpc("getconnectioncount", "")
36 return (int)vNodes.size();
39 Value ping(const Array& params, bool fHelp)
41 if (fHelp || params.size() != 0)
44 "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
45 "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
46 "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
48 + HelpExampleCli("ping", "")
49 + HelpExampleRpc("ping", "")
52 // Request that each node send a ping during next message processing pass
54 BOOST_FOREACH(CNode* pNode, vNodes) {
55 pNode->fPingQueued = true;
61 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
66 vstats.reserve(vNodes.size());
67 BOOST_FOREACH(CNode* pnode, vNodes) {
69 pnode->copyStats(stats);
70 vstats.push_back(stats);
74 Value getpeerinfo(const Array& params, bool fHelp)
76 if (fHelp || params.size() != 0)
79 "\nReturns data about each connected network node as a json array of objects.\n"
83 " \"id\": n, (numeric) Peer index\n"
84 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
85 " \"addrlocal\":\"ip:port\", (string) local address\n"
86 " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
87 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
88 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
89 " \"bytessent\": n, (numeric) The total bytes sent\n"
90 " \"bytesrecv\": n, (numeric) The total bytes received\n"
91 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
92 " \"pingtime\": n, (numeric) ping time\n"
93 " \"pingwait\": n, (numeric) ping wait\n"
94 " \"version\": v, (numeric) The peer version, such as 7001\n"
95 " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
96 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
97 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
98 " \"banscore\": n, (numeric) The ban score (stats.nMisbehavior)\n"
99 " \"syncnode\" : true|false (booleamn) if sync node\n"
104 + HelpExampleCli("getpeerinfo", "")
105 + HelpExampleRpc("getpeerinfo", "")
108 vector<CNodeStats> vstats;
109 CopyNodeStats(vstats);
113 BOOST_FOREACH(const CNodeStats& stats, vstats) {
115 CNodeStateStats statestats;
116 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
117 obj.push_back(Pair("id", stats.nodeid));
118 obj.push_back(Pair("addr", stats.addrName));
119 if (!(stats.addrLocal.empty()))
120 obj.push_back(Pair("addrlocal", stats.addrLocal));
121 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
122 obj.push_back(Pair("lastsend", stats.nLastSend));
123 obj.push_back(Pair("lastrecv", stats.nLastRecv));
124 obj.push_back(Pair("bytessent", stats.nSendBytes));
125 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
126 obj.push_back(Pair("conntime", stats.nTimeConnected));
127 obj.push_back(Pair("pingtime", stats.dPingTime));
128 if (stats.dPingWait > 0.0)
129 obj.push_back(Pair("pingwait", stats.dPingWait));
130 obj.push_back(Pair("version", stats.nVersion));
131 // Use the sanitized form of subver here, to avoid tricksy remote peers from
132 // corrupting or modifiying the JSON output by putting special characters in
133 // their ver message.
134 obj.push_back(Pair("subver", stats.cleanSubVer));
135 obj.push_back(Pair("inbound", stats.fInbound));
136 obj.push_back(Pair("startingheight", stats.nStartingHeight));
138 obj.push_back(Pair("banscore", statestats.nMisbehavior));
139 obj.push_back(Pair("syncheight", statestats.nSyncHeight));
141 obj.push_back(Pair("syncnode", stats.fSyncNode));
142 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
150 Value addnode(const Array& params, bool fHelp)
153 if (params.size() == 2)
154 strCommand = params[1].get_str();
155 if (fHelp || params.size() != 2 ||
156 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
158 "addnode \"node\" \"add|remove|onetry\"\n"
159 "\nAttempts add or remove a node from the addnode list.\n"
160 "Or try a connection to a node once.\n"
162 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
163 "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"
165 + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
166 + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
169 string strNode = params[0].get_str();
171 if (strCommand == "onetry")
174 OpenNetworkConnection(addr, NULL, strNode.c_str());
178 LOCK(cs_vAddedNodes);
179 vector<string>::iterator it = vAddedNodes.begin();
180 for(; it != vAddedNodes.end(); it++)
184 if (strCommand == "add")
186 if (it != vAddedNodes.end())
187 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
188 vAddedNodes.push_back(strNode);
190 else if(strCommand == "remove")
192 if (it == vAddedNodes.end())
193 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
194 vAddedNodes.erase(it);
200 Value getaddednodeinfo(const Array& params, bool fHelp)
202 if (fHelp || params.size() < 1 || params.size() > 2)
204 "getaddednodeinfo dns ( \"node\" )\n"
205 "\nReturns information about the given added node, or all added nodes\n"
206 "(note that onetry addnodes are not listed here)\n"
207 "If dns is false, only a list of added nodes will be provided,\n"
208 "otherwise connected information will also be available.\n"
210 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
211 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
215 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
216 " \"connected\" : true|false, (boolean) If connected\n"
217 " \"addresses\" : [\n"
219 " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server host and port\n"
220 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
228 + HelpExampleCli("getaddednodeinfo", "true")
229 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
230 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
233 bool fDns = params[0].get_bool();
235 list<string> laddedNodes(0);
236 if (params.size() == 1)
238 LOCK(cs_vAddedNodes);
239 BOOST_FOREACH(string& strAddNode, vAddedNodes)
240 laddedNodes.push_back(strAddNode);
244 string strNode = params[1].get_str();
245 LOCK(cs_vAddedNodes);
246 BOOST_FOREACH(string& strAddNode, vAddedNodes)
247 if (strAddNode == strNode)
249 laddedNodes.push_back(strAddNode);
252 if (laddedNodes.size() == 0)
253 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
259 BOOST_FOREACH(string& strAddNode, laddedNodes)
262 obj.push_back(Pair("addednode", strAddNode));
268 list<pair<string, vector<CService> > > laddedAddreses(0);
269 BOOST_FOREACH(string& strAddNode, laddedNodes)
271 vector<CService> vservNode(0);
272 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
273 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
277 obj.push_back(Pair("addednode", strAddNode));
278 obj.push_back(Pair("connected", false));
280 obj.push_back(Pair("addresses", addresses));
285 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
288 obj.push_back(Pair("addednode", it->first));
291 bool fConnected = false;
292 BOOST_FOREACH(CService& addrNode, it->second)
296 node.push_back(Pair("address", addrNode.ToString()));
297 BOOST_FOREACH(CNode* pnode, vNodes)
298 if (pnode->addr == addrNode)
302 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
306 node.push_back(Pair("connected", "false"));
307 addresses.push_back(node);
309 obj.push_back(Pair("connected", fConnected));
310 obj.push_back(Pair("addresses", addresses));
317 Value getnettotals(const Array& params, bool fHelp)
319 if (fHelp || params.size() > 0)
322 "\nReturns information about network traffic, including bytes in, bytes out,\n"
323 "and current time.\n"
326 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
327 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
328 " \"timemillis\": t (numeric) Total cpu time\n"
331 + HelpExampleCli("getnettotals", "")
332 + HelpExampleRpc("getnettotals", "")
336 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
337 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
338 obj.push_back(Pair("timemillis", GetTimeMillis()));
342 static Array GetNetworksInfo()
345 for(int n=0; n<NET_MAX; ++n)
347 enum Network network = static_cast<enum Network>(n);
348 if(network == NET_UNROUTABLE)
352 GetProxy(network, proxy);
353 obj.push_back(Pair("name", GetNetworkName(network)));
354 obj.push_back(Pair("limited", IsLimited(network)));
355 obj.push_back(Pair("reachable", IsReachable(network)));
356 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string()));
357 networks.push_back(obj);
362 Value getnetworkinfo(const Array& params, bool fHelp)
364 if (fHelp || params.size() != 0)
367 "Returns an object containing various state info regarding P2P networking.\n"
370 " \"version\": xxxxx, (numeric) the server version\n"
371 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
372 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
373 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
374 " \"connections\": xxxxx, (numeric) the number of connections\n"
375 " \"networks\": [ (array) information per network\n"
376 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
377 " \"limited\": xxx, (boolean) is the network limited using -onlynet?\n"
378 " \"reachable\": xxx, (boolean) is the network reachable?\n"
379 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
382 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
383 " \"localaddresses\": [, (array) list of local addresses\n"
384 " \"address\": \"xxxx\", (string) network address\n"
385 " \"port\": xxx, (numeric) network port\n"
386 " \"score\": xxx (numeric) relative score\n"
390 + HelpExampleCli("getnetworkinfo", "")
391 + HelpExampleRpc("getnetworkinfo", "")
395 obj.push_back(Pair("version", (int)CLIENT_VERSION));
396 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
397 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
398 obj.push_back(Pair("timeoffset", GetTimeOffset()));
399 obj.push_back(Pair("connections", (int)vNodes.size()));
400 obj.push_back(Pair("networks", GetNetworksInfo()));
401 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
402 Array localAddresses;
404 LOCK(cs_mapLocalHost);
405 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
408 rec.push_back(Pair("address", item.first.ToString()));
409 rec.push_back(Pair("port", item.second.nPort));
410 rec.push_back(Pair("score", item.second.nScore));
411 localAddresses.push_back(rec);
414 obj.push_back(Pair("localaddresses", localAddresses));