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