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