]> Git Repo - VerusCoin.git/blob - src/rpcnet.cpp
test
[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 170002\n"
100             "    \"subver\": \"/MagicBean:x.y.z[-v]/\",  (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 int32_t komodo_longestchain()
169 {
170     int32_t ht,n=0,num=0,maxheight=0,height = 0;
171     LOCK(cs_main);
172     vector<CNodeStats> vstats;
173     CopyNodeStats(vstats);
174     BOOST_FOREACH(const CNodeStats& stats, vstats)
175     {
176         CNodeStateStats statestats;
177         bool fStateStats = GetNodeStateStats(stats.nodeid,statestats);
178         ht = 0;
179         if ( stats.nStartingHeight > ht )
180             ht = stats.nStartingHeight;
181         if ( statestats.nSyncHeight > ht )
182             ht = statestats.nSyncHeight;
183         if ( statestats.nCommonHeight > ht )
184             ht = statestats.nCommonHeight;
185         if ( maxheight == 0 || ht > maxheight*1.01 )
186             maxheight = ht, num = 1;
187         else if ( ht > maxheight*0.99 )
188             num++;
189         n++;
190         if ( ht > height )
191             height = ht;
192     }
193     if ( num > (n >> 1) )
194         return(height);
195     else return(0);
196 }
197
198 Value addnode(const Array& params, bool fHelp)
199 {
200     string strCommand;
201     if (params.size() == 2)
202         strCommand = params[1].get_str();
203     if (fHelp || params.size() != 2 ||
204         (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
205         throw runtime_error(
206             "addnode \"node\" \"add|remove|onetry\"\n"
207             "\nAttempts add or remove a node from the addnode list.\n"
208             "Or try a connection to a node once.\n"
209             "\nArguments:\n"
210             "1. \"node\"     (string, required) The node (see getpeerinfo for nodes)\n"
211             "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"
212             "\nExamples:\n"
213             + HelpExampleCli("addnode", "\"192.168.0.6:8233\" \"onetry\"")
214             + HelpExampleRpc("addnode", "\"192.168.0.6:8233\", \"onetry\"")
215         );
216
217     string strNode = params[0].get_str();
218
219     if (strCommand == "onetry")
220     {
221         CAddress addr;
222         OpenNetworkConnection(addr, NULL, strNode.c_str());
223         return Value::null;
224     }
225
226     LOCK(cs_vAddedNodes);
227     vector<string>::iterator it = vAddedNodes.begin();
228     for(; it != vAddedNodes.end(); it++)
229         if (strNode == *it)
230             break;
231
232     if (strCommand == "add")
233     {
234         if (it != vAddedNodes.end())
235             throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
236         vAddedNodes.push_back(strNode);
237     }
238     else if(strCommand == "remove")
239     {
240         if (it == vAddedNodes.end())
241             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
242         vAddedNodes.erase(it);
243     }
244
245     return Value::null;
246 }
247
248 Value getaddednodeinfo(const Array& params, bool fHelp)
249 {
250     if (fHelp || params.size() < 1 || params.size() > 2)
251         throw runtime_error(
252             "getaddednodeinfo dns ( \"node\" )\n"
253             "\nReturns information about the given added node, or all added nodes\n"
254             "(note that onetry addnodes are not listed here)\n"
255             "If dns is false, only a list of added nodes will be provided,\n"
256             "otherwise connected information will also be available.\n"
257             "\nArguments:\n"
258             "1. dns        (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
259             "2. \"node\"   (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
260             "\nResult:\n"
261             "[\n"
262             "  {\n"
263             "    \"addednode\" : \"192.168.0.201\",   (string) The node ip address\n"
264             "    \"connected\" : true|false,          (boolean) If connected\n"
265             "    \"addresses\" : [\n"
266             "       {\n"
267             "         \"address\" : \"192.168.0.201:8233\",  (string) The bitcoin server host and port\n"
268             "         \"connected\" : \"outbound\"           (string) connection, inbound or outbound\n"
269             "       }\n"
270             "       ,...\n"
271             "     ]\n"
272             "  }\n"
273             "  ,...\n"
274             "]\n"
275             "\nExamples:\n"
276             + HelpExampleCli("getaddednodeinfo", "true")
277             + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
278             + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
279         );
280
281     bool fDns = params[0].get_bool();
282
283     list<string> laddedNodes(0);
284     if (params.size() == 1)
285     {
286         LOCK(cs_vAddedNodes);
287         BOOST_FOREACH(string& strAddNode, vAddedNodes)
288             laddedNodes.push_back(strAddNode);
289     }
290     else
291     {
292         string strNode = params[1].get_str();
293         LOCK(cs_vAddedNodes);
294         BOOST_FOREACH(string& strAddNode, vAddedNodes)
295             if (strAddNode == strNode)
296             {
297                 laddedNodes.push_back(strAddNode);
298                 break;
299             }
300         if (laddedNodes.size() == 0)
301             throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
302     }
303
304     Array ret;
305     if (!fDns)
306     {
307         BOOST_FOREACH(string& strAddNode, laddedNodes)
308         {
309             Object obj;
310             obj.push_back(Pair("addednode", strAddNode));
311             ret.push_back(obj);
312         }
313         return ret;
314     }
315
316     list<pair<string, vector<CService> > > laddedAddreses(0);
317     BOOST_FOREACH(string& strAddNode, laddedNodes)
318     {
319         vector<CService> vservNode(0);
320         if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
321             laddedAddreses.push_back(make_pair(strAddNode, vservNode));
322         else
323         {
324             Object obj;
325             obj.push_back(Pair("addednode", strAddNode));
326             obj.push_back(Pair("connected", false));
327             Array addresses;
328             obj.push_back(Pair("addresses", addresses));
329         }
330     }
331
332     LOCK(cs_vNodes);
333     for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
334     {
335         Object obj;
336         obj.push_back(Pair("addednode", it->first));
337
338         Array addresses;
339         bool fConnected = false;
340         BOOST_FOREACH(CService& addrNode, it->second)
341         {
342             bool fFound = false;
343             Object node;
344             node.push_back(Pair("address", addrNode.ToString()));
345             BOOST_FOREACH(CNode* pnode, vNodes)
346                 if (pnode->addr == addrNode)
347                 {
348                     fFound = true;
349                     fConnected = true;
350                     node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
351                     break;
352                 }
353             if (!fFound)
354                 node.push_back(Pair("connected", "false"));
355             addresses.push_back(node);
356         }
357         obj.push_back(Pair("connected", fConnected));
358         obj.push_back(Pair("addresses", addresses));
359         ret.push_back(obj);
360     }
361
362     return ret;
363 }
364
365 Value getnettotals(const Array& params, bool fHelp)
366 {
367     if (fHelp || params.size() > 0)
368         throw runtime_error(
369             "getnettotals\n"
370             "\nReturns information about network traffic, including bytes in, bytes out,\n"
371             "and current time.\n"
372             "\nResult:\n"
373             "{\n"
374             "  \"totalbytesrecv\": n,   (numeric) Total bytes received\n"
375             "  \"totalbytessent\": n,   (numeric) Total bytes sent\n"
376             "  \"timemillis\": t        (numeric) Total cpu time\n"
377             "}\n"
378             "\nExamples:\n"
379             + HelpExampleCli("getnettotals", "")
380             + HelpExampleRpc("getnettotals", "")
381        );
382
383     Object obj;
384     obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
385     obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
386     obj.push_back(Pair("timemillis", GetTimeMillis()));
387     return obj;
388 }
389
390 static Array GetNetworksInfo()
391 {
392     Array networks;
393     for(int n=0; n<NET_MAX; ++n)
394     {
395         enum Network network = static_cast<enum Network>(n);
396         if(network == NET_UNROUTABLE)
397             continue;
398         proxyType proxy;
399         Object obj;
400         GetProxy(network, proxy);
401         obj.push_back(Pair("name", GetNetworkName(network)));
402         obj.push_back(Pair("limited", IsLimited(network)));
403         obj.push_back(Pair("reachable", IsReachable(network)));
404         obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
405         obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
406         networks.push_back(obj);
407     }
408     return networks;
409 }
410
411 Value getnetworkinfo(const Array& params, bool fHelp)
412 {
413     if (fHelp || params.size() != 0)
414         throw runtime_error(
415             "getnetworkinfo\n"
416             "Returns an object containing various state info regarding P2P networking.\n"
417             "\nResult:\n"
418             "{\n"
419             "  \"version\": xxxxx,                      (numeric) the server version\n"
420             "  \"subversion\": \"/MagicBean:x.y.z[-v]/\",     (string) the server subversion string\n"
421             "  \"protocolversion\": xxxxx,              (numeric) the protocol version\n"
422             "  \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
423             "  \"timeoffset\": xxxxx,                   (numeric) the time offset\n"
424             "  \"connections\": xxxxx,                  (numeric) the number of connections\n"
425             "  \"networks\": [                          (array) information per network\n"
426             "  {\n"
427             "    \"name\": \"xxx\",                     (string) network (ipv4, ipv6 or onion)\n"
428             "    \"limited\": true|false,               (boolean) is the network limited using -onlynet?\n"
429             "    \"reachable\": true|false,             (boolean) is the network reachable?\n"
430             "    \"proxy\": \"host:port\"               (string) the proxy that is used for this network, or empty if none\n"
431             "  }\n"
432             "  ,...\n"
433             "  ],\n"
434             "  \"relayfee\": x.xxxxxxxx,                (numeric) minimum relay fee for non-free transactions in btc/kb\n"
435             "  \"localaddresses\": [                    (array) list of local addresses\n"
436             "  {\n"
437             "    \"address\": \"xxxx\",                 (string) network address\n"
438             "    \"port\": xxx,                         (numeric) network port\n"
439             "    \"score\": xxx                         (numeric) relative score\n"
440             "  }\n"
441             "  ,...\n"
442             "  ]\n"
443             "}\n"
444             "\nExamples:\n"
445             + HelpExampleCli("getnetworkinfo", "")
446             + HelpExampleRpc("getnetworkinfo", "")
447         );
448
449     LOCK(cs_main);
450
451     Object obj;
452     obj.push_back(Pair("version",       CLIENT_VERSION));
453     obj.push_back(Pair("subversion",
454         FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
455     obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
456     obj.push_back(Pair("localservices",       strprintf("%016x", nLocalServices)));
457     obj.push_back(Pair("timeoffset",    GetTimeOffset()));
458     obj.push_back(Pair("connections",   (int)vNodes.size()));
459     obj.push_back(Pair("networks",      GetNetworksInfo()));
460     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
461     Array localAddresses;
462     {
463         LOCK(cs_mapLocalHost);
464         BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
465         {
466             Object rec;
467             rec.push_back(Pair("address", item.first.ToString()));
468             rec.push_back(Pair("port", item.second.nPort));
469             rec.push_back(Pair("score", item.second.nScore));
470             localAddresses.push_back(rec);
471         }
472     }
473     obj.push_back(Pair("localaddresses", localAddresses));
474     return obj;
475 }
This page took 0.051382 seconds and 4 git commands to generate.