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