Merge pull request #4048 from sipa/nobigb58
[bitcoinplatinum.git] / src / rpcnet.cpp
blob1b56d9ae7d032114d737e5902e147ac475d1f8a8
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.
5 #include "rpcserver.h"
7 #include "main.h"
8 #include "net.h"
9 #include "netbase.h"
10 #include "protocol.h"
11 #include "sync.h"
12 #include "util.h"
14 #include <boost/foreach.hpp>
15 #include "json/json_spirit_value.h"
17 using namespace json_spirit;
18 using namespace std;
20 Value getconnectioncount(const Array& params, bool fHelp)
22 if (fHelp || params.size() != 0)
23 throw runtime_error(
24 "getconnectioncount\n"
25 "\nReturns the number of connections to other nodes.\n"
26 "\nbResult:\n"
27 "n (numeric) The connection count\n"
28 "\nExamples:\n"
29 + HelpExampleCli("getconnectioncount", "")
30 + HelpExampleRpc("getconnectioncount", "")
33 LOCK(cs_vNodes);
34 return (int)vNodes.size();
37 Value ping(const Array& params, bool fHelp)
39 if (fHelp || params.size() != 0)
40 throw runtime_error(
41 "ping\n"
42 "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
43 "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
44 "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
45 "\nExamples:\n"
46 + HelpExampleCli("ping", "")
47 + HelpExampleRpc("ping", "")
50 // Request that each node send a ping during next message processing pass
51 LOCK(cs_vNodes);
52 BOOST_FOREACH(CNode* pNode, vNodes) {
53 pNode->fPingQueued = true;
56 return Value::null;
59 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
61 vstats.clear();
63 LOCK(cs_vNodes);
64 vstats.reserve(vNodes.size());
65 BOOST_FOREACH(CNode* pnode, vNodes) {
66 CNodeStats stats;
67 pnode->copyStats(stats);
68 vstats.push_back(stats);
72 Value getpeerinfo(const Array& params, bool fHelp)
74 if (fHelp || params.size() != 0)
75 throw runtime_error(
76 "getpeerinfo\n"
77 "\nReturns data about each connected network node as a json array of objects.\n"
78 "\nbResult:\n"
79 "[\n"
80 " {\n"
81 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
82 " \"addrlocal\":\"ip:port\", (string) local address\n"
83 " \"services\":\"00000001\", (string) The services\n"
84 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
85 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
86 " \"bytessent\": n, (numeric) The total bytes sent\n"
87 " \"bytesrecv\": n, (numeric) The total bytes received\n"
88 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
89 " \"pingtime\": n, (numeric) ping time\n"
90 " \"pingwait\": n, (numeric) ping wait\n"
91 " \"version\": v, (numeric) The peer version, such as 7001\n"
92 " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
93 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
94 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
95 " \"banscore\": n, (numeric) The ban score (stats.nMisbehavior)\n"
96 " \"syncnode\" : true|false (booleamn) if sync node\n"
97 " }\n"
98 " ,...\n"
99 "}\n"
101 "\nExamples:\n"
102 + HelpExampleCli("getpeerinfo", "")
103 + HelpExampleRpc("getpeerinfo", "")
106 vector<CNodeStats> vstats;
107 CopyNodeStats(vstats);
109 Array ret;
111 BOOST_FOREACH(const CNodeStats& stats, vstats) {
112 Object obj;
113 CNodeStateStats statestats;
114 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
115 obj.push_back(Pair("addr", stats.addrName));
116 if (!(stats.addrLocal.empty()))
117 obj.push_back(Pair("addrlocal", stats.addrLocal));
118 obj.push_back(Pair("services", strprintf("%08x", stats.nServices)));
119 obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
120 obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
121 obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes));
122 obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes));
123 obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
124 obj.push_back(Pair("pingtime", stats.dPingTime));
125 if (stats.dPingWait > 0.0)
126 obj.push_back(Pair("pingwait", stats.dPingWait));
127 obj.push_back(Pair("version", stats.nVersion));
128 // Use the sanitized form of subver here, to avoid tricksy remote peers from
129 // corrupting or modifiying the JSON output by putting special characters in
130 // their ver message.
131 obj.push_back(Pair("subver", stats.cleanSubVer));
132 obj.push_back(Pair("inbound", stats.fInbound));
133 obj.push_back(Pair("startingheight", stats.nStartingHeight));
134 if (fStateStats) {
135 obj.push_back(Pair("banscore", statestats.nMisbehavior));
137 obj.push_back(Pair("syncnode", stats.fSyncNode));
139 ret.push_back(obj);
142 return ret;
145 Value addnode(const Array& params, bool fHelp)
147 string strCommand;
148 if (params.size() == 2)
149 strCommand = params[1].get_str();
150 if (fHelp || params.size() != 2 ||
151 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
152 throw runtime_error(
153 "addnode \"node\" \"add|remove|onetry\"\n"
154 "\nAttempts add or remove a node from the addnode list.\n"
155 "Or try a connection to a node once.\n"
156 "\nArguments:\n"
157 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
158 "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"
159 "\nExamples:\n"
160 + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
161 + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
164 string strNode = params[0].get_str();
166 if (strCommand == "onetry")
168 CAddress addr;
169 ConnectNode(addr, strNode.c_str());
170 return Value::null;
173 LOCK(cs_vAddedNodes);
174 vector<string>::iterator it = vAddedNodes.begin();
175 for(; it != vAddedNodes.end(); it++)
176 if (strNode == *it)
177 break;
179 if (strCommand == "add")
181 if (it != vAddedNodes.end())
182 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
183 vAddedNodes.push_back(strNode);
185 else if(strCommand == "remove")
187 if (it == vAddedNodes.end())
188 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
189 vAddedNodes.erase(it);
192 return Value::null;
195 Value getaddednodeinfo(const Array& params, bool fHelp)
197 if (fHelp || params.size() < 1 || params.size() > 2)
198 throw runtime_error(
199 "getaddednodeinfo dns ( \"node\" )\n"
200 "\nReturns information about the given added node, or all added nodes\n"
201 "(note that onetry addnodes are not listed here)\n"
202 "If dns is false, only a list of added nodes will be provided,\n"
203 "otherwise connected information will also be available.\n"
204 "\nArguments:\n"
205 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
206 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
207 "\nResult:\n"
208 "[\n"
209 " {\n"
210 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
211 " \"connected\" : true|false, (boolean) If connected\n"
212 " \"addresses\" : [\n"
213 " {\n"
214 " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server host and port\n"
215 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
216 " }\n"
217 " ,...\n"
218 " ]\n"
219 " }\n"
220 " ,...\n"
221 "]\n"
222 "\nExamples:\n"
223 + HelpExampleCli("getaddednodeinfo", "true")
224 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
225 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
228 bool fDns = params[0].get_bool();
230 list<string> laddedNodes(0);
231 if (params.size() == 1)
233 LOCK(cs_vAddedNodes);
234 BOOST_FOREACH(string& strAddNode, vAddedNodes)
235 laddedNodes.push_back(strAddNode);
237 else
239 string strNode = params[1].get_str();
240 LOCK(cs_vAddedNodes);
241 BOOST_FOREACH(string& strAddNode, vAddedNodes)
242 if (strAddNode == strNode)
244 laddedNodes.push_back(strAddNode);
245 break;
247 if (laddedNodes.size() == 0)
248 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
251 Array ret;
252 if (!fDns)
254 BOOST_FOREACH(string& strAddNode, laddedNodes)
256 Object obj;
257 obj.push_back(Pair("addednode", strAddNode));
258 ret.push_back(obj);
260 return ret;
263 list<pair<string, vector<CService> > > laddedAddreses(0);
264 BOOST_FOREACH(string& strAddNode, laddedNodes)
266 vector<CService> vservNode(0);
267 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
268 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
269 else
271 Object obj;
272 obj.push_back(Pair("addednode", strAddNode));
273 obj.push_back(Pair("connected", false));
274 Array addresses;
275 obj.push_back(Pair("addresses", addresses));
279 LOCK(cs_vNodes);
280 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
282 Object obj;
283 obj.push_back(Pair("addednode", it->first));
285 Array addresses;
286 bool fConnected = false;
287 BOOST_FOREACH(CService& addrNode, it->second)
289 bool fFound = false;
290 Object node;
291 node.push_back(Pair("address", addrNode.ToString()));
292 BOOST_FOREACH(CNode* pnode, vNodes)
293 if (pnode->addr == addrNode)
295 fFound = true;
296 fConnected = true;
297 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
298 break;
300 if (!fFound)
301 node.push_back(Pair("connected", "false"));
302 addresses.push_back(node);
304 obj.push_back(Pair("connected", fConnected));
305 obj.push_back(Pair("addresses", addresses));
306 ret.push_back(obj);
309 return ret;
312 Value getnettotals(const Array& params, bool fHelp)
314 if (fHelp || params.size() > 0)
315 throw runtime_error(
316 "getnettotals\n"
317 "\nReturns information about network traffic, including bytes in, bytes out,\n"
318 "and current time.\n"
319 "\nResult:\n"
320 "{\n"
321 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
322 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
323 " \"timemillis\": t (numeric) Total cpu time\n"
324 "}\n"
325 "\nExamples:\n"
326 + HelpExampleCli("getnettotals", "")
327 + HelpExampleRpc("getnettotals", "")
330 Object obj;
331 obj.push_back(Pair("totalbytesrecv", static_cast< boost::uint64_t>(CNode::GetTotalBytesRecv())));
332 obj.push_back(Pair("totalbytessent", static_cast<boost::uint64_t>(CNode::GetTotalBytesSent())));
333 obj.push_back(Pair("timemillis", static_cast<boost::int64_t>(GetTimeMillis())));
334 return obj;