]> Git Repo - VerusCoin.git/blob - src/rpcnet.cpp
Merge pull request #6062
[VerusCoin.git] / src / rpcnet.cpp
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.
4
5 #include "rpcserver.h"
6
7 #include "clientversion.h"
8 #include "main.h"
9 #include "net.h"
10 #include "netbase.h"
11 #include "protocol.h"
12 #include "sync.h"
13 #include "timedata.h"
14 #include "util.h"
15 #include "version.h"
16
17 #include <boost/foreach.hpp>
18
19 #include "json/json_spirit_value.h"
20
21 using namespace json_spirit;
22 using namespace std;
23
24 Value getconnectioncount(const Array& params, bool fHelp)
25 {
26     if (fHelp || params.size() != 0)
27         throw runtime_error(
28             "getconnectioncount\n"
29             "\nReturns the number of connections to other nodes.\n"
30             "\nbResult:\n"
31             "n          (numeric) The connection count\n"
32             "\nExamples:\n"
33             + HelpExampleCli("getconnectioncount", "")
34             + HelpExampleRpc("getconnectioncount", "")
35         );
36
37     LOCK2(cs_main, cs_vNodes);
38
39     return (int)vNodes.size();
40 }
41
42 Value ping(const Array& params, bool fHelp)
43 {
44     if (fHelp || params.size() != 0)
45         throw runtime_error(
46             "ping\n"
47             "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
48             "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
49             "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
50             "\nExamples:\n"
51             + HelpExampleCli("ping", "")
52             + HelpExampleRpc("ping", "")
53         );
54
55     // Request that each node send a ping during next message processing pass
56     LOCK2(cs_main, cs_vNodes);
57
58     BOOST_FOREACH(CNode* pNode, vNodes) {
59         pNode->fPingQueued = true;
60     }
61
62     return Value::null;
63 }
64
65 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
66 {
67     vstats.clear();
68
69     LOCK(cs_vNodes);
70     vstats.reserve(vNodes.size());
71     BOOST_FOREACH(CNode* pnode, vNodes) {
72         CNodeStats stats;
73         pnode->copyStats(stats);
74         vstats.push_back(stats);
75     }
76 }
77
78 Value getpeerinfo(const Array& params, bool fHelp)
79 {
80     if (fHelp || params.size() != 0)
81         throw runtime_error(
82             "getpeerinfo\n"
83             "\nReturns data about each connected network node as a json array of objects.\n"
84             "\nbResult:\n"
85             "[\n"
86             "  {\n"
87             "    \"id\": n,                   (numeric) Peer index\n"
88             "    \"addr\":\"host:port\",      (string) The ip address and port of the peer\n"
89             "    \"addrlocal\":\"ip:port\",   (string) local address\n"
90             "    \"services\":\"xxxxxxxxxxxxxxxx\",   (string) The services offered\n"
91             "    \"lastsend\": ttt,           (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
92             "    \"lastrecv\": ttt,           (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
93             "    \"bytessent\": n,            (numeric) The total bytes sent\n"
94             "    \"bytesrecv\": n,            (numeric) The total bytes received\n"
95             "    \"conntime\": ttt,           (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
96             "    \"timeoffset\": ttt,         (numeric) The time offset in seconds\n"
97             "    \"pingtime\": n,             (numeric) ping time\n"
98             "    \"pingwait\": n,             (numeric) ping wait\n"
99             "    \"version\": v,              (numeric) The peer version, such as 7001\n"
100             "    \"subver\": \"/Satoshi:0.8.5/\",  (string) The string version\n"
101             "    \"inbound\": true|false,     (boolean) Inbound (true) or Outbound (false)\n"
102             "    \"startingheight\": n,       (numeric) The starting height (block) of the peer\n"
103             "    \"banscore\": n,             (numeric) The ban score\n"
104             "    \"synced_headers\": n,       (numeric) The last header we have in common with this peer\n"
105             "    \"synced_blocks\": n,        (numeric) The last block we have in common with this peer\n"
106             "    \"inflight\": [\n"
107             "       n,                        (numeric) The heights of blocks we're currently asking from this peer\n"
108             "       ...\n"
109             "    ]\n"
110             "  }\n"
111             "  ,...\n"
112             "]\n"
113             "\nExamples:\n"
114             + HelpExampleCli("getpeerinfo", "")
115             + HelpExampleRpc("getpeerinfo", "")
116         );
117
118     LOCK(cs_main);
119
120     vector<CNodeStats> vstats;
121     CopyNodeStats(vstats);
122
123     Array ret;
124
125     BOOST_FOREACH(const CNodeStats& stats, vstats) {
126         Object obj;
127         CNodeStateStats statestats;
128         bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
129         obj.push_back(Pair("id", stats.nodeid));
130         obj.push_back(Pair("addr", stats.addrName));
131         if (!(stats.addrLocal.empty()))
132             obj.push_back(Pair("addrlocal", stats.addrLocal));
133         obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
134         obj.push_back(Pair("lastsend", stats.nLastSend));
135         obj.push_back(Pair("lastrecv", stats.nLastRecv));
136         obj.push_back(Pair("bytessent", stats.nSendBytes));
137         obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
138         obj.push_back(Pair("conntime", stats.nTimeConnected));
139         obj.push_back(Pair("timeoffset", stats.nTimeOffset));
140         obj.push_back(Pair("pingtime", stats.dPingTime));
141         if (stats.dPingWait > 0.0)
142             obj.push_back(Pair("pingwait", stats.dPingWait));
143         obj.push_back(Pair("version", stats.nVersion));
144         // Use the sanitized form of subver here, to avoid tricksy remote peers from
145         // corrupting or modifiying the JSON output by putting special characters in
146         // their ver message.
147         obj.push_back(Pair("subver", stats.cleanSubVer));
148         obj.push_back(Pair("inbound", stats.fInbound));
149         obj.push_back(Pair("startingheight", stats.nStartingHeight));
150         if (fStateStats) {
151             obj.push_back(Pair("banscore", statestats.nMisbehavior));
152             obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
153             obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
154             Array heights;
155             BOOST_FOREACH(int height, statestats.vHeightInFlight) {
156                 heights.push_back(height);
157             }
158             obj.push_back(Pair("inflight", heights));
159         }
160         obj.push_back(Pair("whitelisted", stats.fWhitelisted));
161
162         ret.push_back(obj);
163     }
164
165     return ret;
166 }
167
168 Value addnode(const Array& params, bool fHelp)
169 {
170     string strCommand;
171     if (params.size() == 2)
172         strCommand = params[1].get_str();
173     if (fHelp || params.size() != 2 ||
174         (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
175         throw runtime_error(
176             "addnode \"node\" \"add|remove|onetry\"\n"
177             "\nAttempts add or remove a node from the addnode list.\n"
178             "Or try a connection to a node once.\n"
179             "\nArguments:\n"
180             "1. \"node\"     (string, required) The node (see getpeerinfo for nodes)\n"
181             "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"
182             "\nExamples:\n"
183             + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
184             + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
185         );
186
187     string strNode = params[0].get_str();
188
189     if (strCommand == "onetry")
190     {
191         CAddress addr;
192         OpenNetworkConnection(addr, NULL, strNode.c_str());
193         return Value::null;
194     }
195
196     LOCK(cs_vAddedNodes);
197     vector<string>::iterator it = vAddedNodes.begin();
198     for(; it != vAddedNodes.end(); it++)
199         if (strNode == *it)
200             break;
201
202     if (strCommand == "add")
203     {
204         if (it != vAddedNodes.end())
205             throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
206         vAddedNodes.push_back(strNode);
207     }
208     else if(strCommand == "remove")
209     {
210         if (it == vAddedNodes.end())
211             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
212         vAddedNodes.erase(it);
213     }
214
215     return Value::null;
216 }
217
218 Value getaddednodeinfo(const Array& params, bool fHelp)
219 {
220     if (fHelp || params.size() < 1 || params.size() > 2)
221         throw runtime_error(
222             "getaddednodeinfo dns ( \"node\" )\n"
223             "\nReturns information about the given added node, or all added nodes\n"
224             "(note that onetry addnodes are not listed here)\n"
225             "If dns is false, only a list of added nodes will be provided,\n"
226             "otherwise connected information will also be available.\n"
227             "\nArguments:\n"
228             "1. dns        (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
229             "2. \"node\"   (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
230             "\nResult:\n"
231             "[\n"
232             "  {\n"
233             "    \"addednode\" : \"192.168.0.201\",   (string) The node ip address\n"
234             "    \"connected\" : true|false,          (boolean) If connected\n"
235             "    \"addresses\" : [\n"
236             "       {\n"
237             "         \"address\" : \"192.168.0.201:8333\",  (string) The bitcoin server host and port\n"
238             "         \"connected\" : \"outbound\"           (string) connection, inbound or outbound\n"
239             "       }\n"
240             "       ,...\n"
241             "     ]\n"
242             "  }\n"
243             "  ,...\n"
244             "]\n"
245             "\nExamples:\n"
246             + HelpExampleCli("getaddednodeinfo", "true")
247             + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
248             + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
249         );
250
251     bool fDns = params[0].get_bool();
252
253     list<string> laddedNodes(0);
254     if (params.size() == 1)
255     {
256         LOCK(cs_vAddedNodes);
257         BOOST_FOREACH(string& strAddNode, vAddedNodes)
258             laddedNodes.push_back(strAddNode);
259     }
260     else
261     {
262         string strNode = params[1].get_str();
263         LOCK(cs_vAddedNodes);
264         BOOST_FOREACH(string& strAddNode, vAddedNodes)
265             if (strAddNode == strNode)
266             {
267                 laddedNodes.push_back(strAddNode);
268                 break;
269             }
270         if (laddedNodes.size() == 0)
271             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
272     }
273
274     Array ret;
275     if (!fDns)
276     {
277         BOOST_FOREACH(string& strAddNode, laddedNodes)
278         {
279             Object obj;
280             obj.push_back(Pair("addednode", strAddNode));
281             ret.push_back(obj);
282         }
283         return ret;
284     }
285
286     list<pair<string, vector<CService> > > laddedAddreses(0);
287     BOOST_FOREACH(string& strAddNode, laddedNodes)
288     {
289         vector<CService> vservNode(0);
290         if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
291             laddedAddreses.push_back(make_pair(strAddNode, vservNode));
292         else
293         {
294             Object obj;
295             obj.push_back(Pair("addednode", strAddNode));
296             obj.push_back(Pair("connected", false));
297             Array addresses;
298             obj.push_back(Pair("addresses", addresses));
299         }
300     }
301
302     LOCK(cs_vNodes);
303     for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
304     {
305         Object obj;
306         obj.push_back(Pair("addednode", it->first));
307
308         Array addresses;
309         bool fConnected = false;
310         BOOST_FOREACH(CService& addrNode, it->second)
311         {
312             bool fFound = false;
313             Object node;
314             node.push_back(Pair("address", addrNode.ToString()));
315             BOOST_FOREACH(CNode* pnode, vNodes)
316                 if (pnode->addr == addrNode)
317                 {
318                     fFound = true;
319                     fConnected = true;
320                     node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
321                     break;
322                 }
323             if (!fFound)
324                 node.push_back(Pair("connected", "false"));
325             addresses.push_back(node);
326         }
327         obj.push_back(Pair("connected", fConnected));
328         obj.push_back(Pair("addresses", addresses));
329         ret.push_back(obj);
330     }
331
332     return ret;
333 }
334
335 Value getnettotals(const Array& params, bool fHelp)
336 {
337     if (fHelp || params.size() > 0)
338         throw runtime_error(
339             "getnettotals\n"
340             "\nReturns information about network traffic, including bytes in, bytes out,\n"
341             "and current time.\n"
342             "\nResult:\n"
343             "{\n"
344             "  \"totalbytesrecv\": n,   (numeric) Total bytes received\n"
345             "  \"totalbytessent\": n,   (numeric) Total bytes sent\n"
346             "  \"timemillis\": t        (numeric) Total cpu time\n"
347             "}\n"
348             "\nExamples:\n"
349             + HelpExampleCli("getnettotals", "")
350             + HelpExampleRpc("getnettotals", "")
351        );
352
353     Object obj;
354     obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
355     obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
356     obj.push_back(Pair("timemillis", GetTimeMillis()));
357     return obj;
358 }
359
360 static Array GetNetworksInfo()
361 {
362     Array networks;
363     for(int n=0; n<NET_MAX; ++n)
364     {
365         enum Network network = static_cast<enum Network>(n);
366         if(network == NET_UNROUTABLE)
367             continue;
368         proxyType proxy;
369         Object obj;
370         GetProxy(network, proxy);
371         obj.push_back(Pair("name", GetNetworkName(network)));
372         obj.push_back(Pair("limited", IsLimited(network)));
373         obj.push_back(Pair("reachable", IsReachable(network)));
374         obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
375         obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
376         networks.push_back(obj);
377     }
378     return networks;
379 }
380
381 Value getnetworkinfo(const Array& params, bool fHelp)
382 {
383     if (fHelp || params.size() != 0)
384         throw runtime_error(
385             "getnetworkinfo\n"
386             "Returns an object containing various state info regarding P2P networking.\n"
387             "\nResult:\n"
388             "{\n"
389             "  \"version\": xxxxx,                      (numeric) the server version\n"
390             "  \"subversion\": \"/Satoshi:x.x.x/\",     (string) the server subversion string\n"
391             "  \"protocolversion\": xxxxx,              (numeric) the protocol version\n"
392             "  \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
393             "  \"timeoffset\": xxxxx,                   (numeric) the time offset\n"
394             "  \"connections\": xxxxx,                  (numeric) the number of connections\n"
395             "  \"networks\": [                          (array) information per network\n"
396             "  {\n"
397             "    \"name\": \"xxx\",                     (string) network (ipv4, ipv6 or onion)\n"
398             "    \"limited\": true|false,               (boolean) is the network limited using -onlynet?\n"
399             "    \"reachable\": true|false,             (boolean) is the network reachable?\n"
400             "    \"proxy\": \"host:port\"               (string) the proxy that is used for this network, or empty if none\n"
401             "  }\n"
402             "  ,...\n"
403             "  ],\n"
404             "  \"relayfee\": x.xxxxxxxx,                (numeric) minimum relay fee for non-free transactions in btc/kb\n"
405             "  \"localaddresses\": [                    (array) list of local addresses\n"
406             "  {\n"
407             "    \"address\": \"xxxx\",                 (string) network address\n"
408             "    \"port\": xxx,                         (numeric) network port\n"
409             "    \"score\": xxx                         (numeric) relative score\n"
410             "  }\n"
411             "  ,...\n"
412             "  ]\n"
413             "}\n"
414             "\nExamples:\n"
415             + HelpExampleCli("getnetworkinfo", "")
416             + HelpExampleRpc("getnetworkinfo", "")
417         );
418
419     LOCK(cs_main);
420
421     Object obj;
422     obj.push_back(Pair("version",       CLIENT_VERSION));
423     obj.push_back(Pair("subversion",
424         FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
425     obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
426     obj.push_back(Pair("localservices",       strprintf("%016x", nLocalServices)));
427     obj.push_back(Pair("timeoffset",    GetTimeOffset()));
428     obj.push_back(Pair("connections",   (int)vNodes.size()));
429     obj.push_back(Pair("networks",      GetNetworksInfo()));
430     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
431     Array localAddresses;
432     {
433         LOCK(cs_mapLocalHost);
434         BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
435         {
436             Object rec;
437             rec.push_back(Pair("address", item.first.ToString()));
438             rec.push_back(Pair("port", item.second.nPort));
439             rec.push_back(Pair("score", item.second.nScore));
440             localAddresses.push_back(rec);
441         }
442     }
443     obj.push_back(Pair("localaddresses", localAddresses));
444     return obj;
445 }
This page took 0.05204 seconds and 4 git commands to generate.