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