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>
23 UniValue getconnectioncount(const UniValue& 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", "")
36 LOCK2(cs_main, cs_vNodes);
38 return (int)vNodes.size();
41 UniValue ping(const UniValue& 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
55 LOCK2(cs_main, cs_vNodes);
57 BOOST_FOREACH(CNode* pNode, vNodes) {
58 pNode->fPingQueued = true;
64 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
69 vstats.reserve(vNodes.size());
70 BOOST_FOREACH(CNode* pnode, vNodes) {
72 pnode->copyStats(stats);
73 vstats.push_back(stats);
77 UniValue getpeerinfo(const UniValue& params, bool fHelp)
79 if (fHelp || params.size() != 0)
82 "\nReturns data about each connected network node as a json array of objects.\n"
86 " \"id\": n, (numeric) Peer index\n"
87 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
88 " \"addrlocal\":\"ip:port\", (string) local address\n"
89 " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
90 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
91 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
92 " \"bytessent\": n, (numeric) The total bytes sent\n"
93 " \"bytesrecv\": n, (numeric) The total bytes received\n"
94 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
95 " \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
96 " \"pingtime\": n, (numeric) ping time\n"
97 " \"pingwait\": n, (numeric) ping wait\n"
98 " \"version\": v, (numeric) The peer version, such as 170002\n"
99 " \"subver\": \"/MagicBean:x.y.z[-v]/\", (string) The string version\n"
100 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
101 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
102 " \"banscore\": n, (numeric) The ban score\n"
103 " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
104 " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
106 " n, (numeric) The heights of blocks we're currently asking from this peer\n"
113 + HelpExampleCli("getpeerinfo", "")
114 + HelpExampleRpc("getpeerinfo", "")
119 vector<CNodeStats> vstats;
120 CopyNodeStats(vstats);
122 UniValue ret(UniValue::VARR);
124 BOOST_FOREACH(const CNodeStats& stats, vstats) {
125 UniValue obj(UniValue::VOBJ);
126 CNodeStateStats statestats;
127 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
128 obj.push_back(Pair("id", stats.nodeid));
129 obj.push_back(Pair("addr", stats.addrName));
130 if (!(stats.addrLocal.empty()))
131 obj.push_back(Pair("addrlocal", stats.addrLocal));
132 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
133 obj.push_back(Pair("lastsend", stats.nLastSend));
134 obj.push_back(Pair("lastrecv", stats.nLastRecv));
135 obj.push_back(Pair("bytessent", stats.nSendBytes));
136 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
137 obj.push_back(Pair("conntime", stats.nTimeConnected));
138 obj.push_back(Pair("timeoffset", stats.nTimeOffset));
139 obj.push_back(Pair("pingtime", stats.dPingTime));
140 if (stats.dPingWait > 0.0)
141 obj.push_back(Pair("pingwait", stats.dPingWait));
142 obj.push_back(Pair("version", stats.nVersion));
143 // Use the sanitized form of subver here, to avoid tricksy remote peers from
144 // corrupting or modifiying the JSON output by putting special characters in
145 // their ver message.
146 obj.push_back(Pair("subver", stats.cleanSubVer));
147 obj.push_back(Pair("inbound", stats.fInbound));
148 obj.push_back(Pair("startingheight", stats.nStartingHeight));
150 obj.push_back(Pair("banscore", statestats.nMisbehavior));
151 obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
152 obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
153 UniValue heights(UniValue::VARR);
154 BOOST_FOREACH(int height, statestats.vHeightInFlight) {
155 heights.push_back(height);
157 obj.push_back(Pair("inflight", heights));
159 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
167 int32_t komodo_longestchain()
169 int32_t ht,n=0,num=0,maxheight=0,height = 0;
171 vector<CNodeStats> vstats;
172 CopyNodeStats(vstats);
173 BOOST_FOREACH(const CNodeStats& stats, vstats)
175 CNodeStateStats statestats;
176 bool fStateStats = GetNodeStateStats(stats.nodeid,statestats);
178 if ( stats.nStartingHeight > ht )
179 ht = stats.nStartingHeight;
180 if ( statestats.nSyncHeight > ht )
181 ht = statestats.nSyncHeight;
182 if ( statestats.nCommonHeight > ht )
183 ht = statestats.nCommonHeight;
184 if ( maxheight == 0 || ht > maxheight*1.01 )
185 maxheight = ht, num = 1;
186 else if ( ht > maxheight*0.99 )
192 if ( num > (n >> 1) )
197 UniValue addnode(const UniValue& params, bool fHelp)
200 if (params.size() == 2)
201 strCommand = params[1].get_str();
202 if (fHelp || params.size() != 2 ||
203 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
205 "addnode \"node\" \"add|remove|onetry\"\n"
206 "\nAttempts add or remove a node from the addnode list.\n"
207 "Or try a connection to a node once.\n"
209 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
210 "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"
212 + HelpExampleCli("addnode", "\"192.168.0.6:8233\" \"onetry\"")
213 + HelpExampleRpc("addnode", "\"192.168.0.6:8233\", \"onetry\"")
216 string strNode = params[0].get_str();
218 if (strCommand == "onetry")
221 OpenNetworkConnection(addr, NULL, strNode.c_str());
225 LOCK(cs_vAddedNodes);
226 vector<string>::iterator it = vAddedNodes.begin();
227 for(; it != vAddedNodes.end(); it++)
231 if (strCommand == "add")
233 if (it != vAddedNodes.end())
234 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
235 vAddedNodes.push_back(strNode);
237 else if(strCommand == "remove")
239 if (it == vAddedNodes.end())
240 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
241 vAddedNodes.erase(it);
247 UniValue disconnectnode(const UniValue& params, bool fHelp)
249 if (fHelp || params.size() != 1)
251 "disconnectnode \"node\" \n"
252 "\nImmediately disconnects from the specified node.\n"
254 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
256 + HelpExampleCli("disconnectnode", "\"192.168.0.6:8233\"")
257 + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8233\"")
260 CNode* pNode = FindNode(params[0].get_str());
262 throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
264 pNode->fDisconnect = true;
269 UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
271 if (fHelp || params.size() < 1 || params.size() > 2)
273 "getaddednodeinfo dns ( \"node\" )\n"
274 "\nReturns information about the given added node, or all added nodes\n"
275 "(note that onetry addnodes are not listed here)\n"
276 "If dns is false, only a list of added nodes will be provided,\n"
277 "otherwise connected information will also be available.\n"
279 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
280 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
284 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
285 " \"connected\" : true|false, (boolean) If connected\n"
286 " \"addresses\" : [\n"
288 " \"address\" : \"192.168.0.201:8233\", (string) The bitcoin server host and port\n"
289 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
297 + HelpExampleCli("getaddednodeinfo", "true")
298 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
299 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
302 bool fDns = params[0].get_bool();
304 list<string> laddedNodes(0);
305 if (params.size() == 1)
307 LOCK(cs_vAddedNodes);
308 BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
309 laddedNodes.push_back(strAddNode);
313 string strNode = params[1].get_str();
314 LOCK(cs_vAddedNodes);
315 BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) {
316 if (strAddNode == strNode)
318 laddedNodes.push_back(strAddNode);
322 if (laddedNodes.size() == 0)
323 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
326 UniValue ret(UniValue::VARR);
329 BOOST_FOREACH (const std::string& strAddNode, laddedNodes) {
330 UniValue obj(UniValue::VOBJ);
331 obj.push_back(Pair("addednode", strAddNode));
337 list<pair<string, vector<CService> > > laddedAddreses(0);
338 BOOST_FOREACH(const std::string& strAddNode, laddedNodes) {
339 vector<CService> vservNode(0);
340 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
341 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
344 UniValue obj(UniValue::VOBJ);
345 obj.push_back(Pair("addednode", strAddNode));
346 obj.push_back(Pair("connected", false));
347 UniValue addresses(UniValue::VARR);
348 obj.push_back(Pair("addresses", addresses));
353 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
355 UniValue obj(UniValue::VOBJ);
356 obj.push_back(Pair("addednode", it->first));
358 UniValue addresses(UniValue::VARR);
359 bool fConnected = false;
360 BOOST_FOREACH(const CService& addrNode, it->second) {
362 UniValue node(UniValue::VOBJ);
363 node.push_back(Pair("address", addrNode.ToString()));
364 BOOST_FOREACH(CNode* pnode, vNodes) {
365 if (pnode->addr == addrNode)
369 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
374 node.push_back(Pair("connected", "false"));
375 addresses.push_back(node);
377 obj.push_back(Pair("connected", fConnected));
378 obj.push_back(Pair("addresses", addresses));
385 UniValue getnettotals(const UniValue& params, bool fHelp)
387 if (fHelp || params.size() > 0)
390 "\nReturns information about network traffic, including bytes in, bytes out,\n"
391 "and current time.\n"
394 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
395 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
396 " \"timemillis\": t (numeric) Total cpu time\n"
399 + HelpExampleCli("getnettotals", "")
400 + HelpExampleRpc("getnettotals", "")
403 UniValue obj(UniValue::VOBJ);
404 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
405 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
406 obj.push_back(Pair("timemillis", GetTimeMillis()));
410 static UniValue GetNetworksInfo()
412 UniValue networks(UniValue::VARR);
413 for(int n=0; n<NET_MAX; ++n)
415 enum Network network = static_cast<enum Network>(n);
416 if(network == NET_UNROUTABLE)
419 UniValue obj(UniValue::VOBJ);
420 GetProxy(network, proxy);
421 obj.push_back(Pair("name", GetNetworkName(network)));
422 obj.push_back(Pair("limited", IsLimited(network)));
423 obj.push_back(Pair("reachable", IsReachable(network)));
424 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
425 obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
426 networks.push_back(obj);
431 UniValue getnetworkinfo(const UniValue& params, bool fHelp)
433 if (fHelp || params.size() != 0)
436 "Returns an object containing various state info regarding P2P networking.\n"
439 " \"version\": xxxxx, (numeric) the server version\n"
440 " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n"
441 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
442 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
443 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
444 " \"connections\": xxxxx, (numeric) the number of connections\n"
445 " \"networks\": [ (array) information per network\n"
447 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
448 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
449 " \"reachable\": true|false, (boolean) is the network reachable?\n"
450 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
454 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
455 " \"localaddresses\": [ (array) list of local addresses\n"
457 " \"address\": \"xxxx\", (string) network address\n"
458 " \"port\": xxx, (numeric) network port\n"
459 " \"score\": xxx (numeric) relative score\n"
463 " \"warnings\": \"...\" (string) any network warnings (such as alert messages) \n"
466 + HelpExampleCli("getnetworkinfo", "")
467 + HelpExampleRpc("getnetworkinfo", "")
472 UniValue obj(UniValue::VOBJ);
473 obj.push_back(Pair("version", CLIENT_VERSION));
474 obj.push_back(Pair("subversion",
475 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
476 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
477 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
478 obj.push_back(Pair("timeoffset", GetTimeOffset()));
479 obj.push_back(Pair("connections", (int)vNodes.size()));
480 obj.push_back(Pair("networks", GetNetworksInfo()));
481 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
482 UniValue localAddresses(UniValue::VARR);
484 LOCK(cs_mapLocalHost);
485 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
487 UniValue rec(UniValue::VOBJ);
488 rec.push_back(Pair("address", item.first.ToString()));
489 rec.push_back(Pair("port", item.second.nPort));
490 rec.push_back(Pair("score", item.second.nScore));
491 localAddresses.push_back(rec);
494 obj.push_back(Pair("localaddresses", localAddresses));
495 obj.push_back(Pair("warnings", GetWarnings("statusbar")));
499 UniValue setban(const UniValue& params, bool fHelp)
502 if (params.size() >= 2)
503 strCommand = params[1].get_str();
504 if (fHelp || params.size() < 2 ||
505 (strCommand != "add" && strCommand != "remove"))
507 "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n"
508 "\nAttempts add or remove a IP/Subnet from the banned list.\n"
510 "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n"
511 "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n"
512 "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n"
513 "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
515 + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
516 + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
517 + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400")
522 bool isSubnet = false;
524 if (params[0].get_str().find("/") != string::npos)
528 netAddr = CNetAddr(params[0].get_str());
530 subNet = CSubNet(params[0].get_str());
532 if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
533 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
535 if (strCommand == "add")
537 if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
538 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
540 int64_t banTime = 0; //use standard bantime if not specified
541 if (params.size() >= 3 && !params[2].isNull())
542 banTime = params[2].get_int64();
544 bool absolute = false;
545 if (params.size() == 4 && params[3].isTrue())
548 isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute);
550 //disconnect possible nodes
551 while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
552 bannedNode->fDisconnect = true;
554 else if(strCommand == "remove")
556 if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
557 throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
563 UniValue listbanned(const UniValue& params, bool fHelp)
565 if (fHelp || params.size() != 0)
568 "\nList all banned IPs/Subnets.\n"
570 + HelpExampleCli("listbanned", "")
571 + HelpExampleRpc("listbanned", "")
574 std::map<CSubNet, int64_t> banMap;
575 CNode::GetBanned(banMap);
577 UniValue bannedAddresses(UniValue::VARR);
578 for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++)
580 UniValue rec(UniValue::VOBJ);
581 rec.push_back(Pair("address", (*it).first.ToString()));
582 rec.push_back(Pair("banned_until", (*it).second));
583 bannedAddresses.push_back(rec);
586 return bannedAddresses;
589 UniValue clearbanned(const UniValue& params, bool fHelp)
591 if (fHelp || params.size() != 0)
594 "\nClear all banned IPs.\n"
596 + HelpExampleCli("clearbanned", "")
597 + HelpExampleRpc("clearbanned", "")
600 CNode::ClearBanned();