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