]>
Commit | Line | Data |
---|---|---|
f914f1a7 | 1 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
72fb3d29 | 2 | // Distributed under the MIT software license, see the accompanying |
70ab73a0 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
b2864d2f | 4 | |
4519a766 | 5 | #include "rpc/server.h" |
b2864d2f | 6 | |
71697f97 | 7 | #include "clientversion.h" |
b2864d2f | 8 | #include "main.h" |
51ed9ec9 BD |
9 | #include "net.h" |
10 | #include "netbase.h" | |
11 | #include "protocol.h" | |
12 | #include "sync.h" | |
14f888ca | 13 | #include "timedata.h" |
51ed9ec9 | 14 | #include "util.h" |
ff36cbe8 | 15 | #include "version.h" |
9d2974ed | 16 | #include "deprecation.h" |
51ed9ec9 | 17 | |
51ed9ec9 | 18 | #include <boost/foreach.hpp> |
611116d4 | 19 | |
a10a6e2a | 20 | #include <univalue.h> |
70ab73a0 | 21 | |
70ab73a0 JG |
22 | using namespace std; |
23 | ||
d014114d | 24 | UniValue getconnectioncount(const UniValue& params, bool fHelp) |
70ab73a0 JG |
25 | { |
26 | if (fHelp || params.size() != 0) | |
27 | throw runtime_error( | |
28 | "getconnectioncount\n" | |
a6099ef3 | 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 | ); | |
70ab73a0 | 36 | |
4401b2d7 EL |
37 | LOCK2(cs_main, cs_vNodes); |
38 | ||
70ab73a0 JG |
39 | return (int)vNodes.size(); |
40 | } | |
41 | ||
d014114d | 42 | UniValue ping(const UniValue& params, bool fHelp) |
971bb3e9 JL |
43 | { |
44 | if (fHelp || params.size() != 0) | |
45 | throw runtime_error( | |
46 | "ping\n" | |
a6099ef3 | 47 | "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" |
971bb3e9 | 48 | "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" |
6943cb9b | 49 | "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n" |
a6099ef3 | 50 | "\nExamples:\n" |
51 | + HelpExampleCli("ping", "") | |
52 | + HelpExampleRpc("ping", "") | |
53 | ); | |
4315ec1a | 54 | |
971bb3e9 | 55 | // Request that each node send a ping during next message processing pass |
4401b2d7 EL |
56 | LOCK2(cs_main, cs_vNodes); |
57 | ||
971bb3e9 JL |
58 | BOOST_FOREACH(CNode* pNode, vNodes) { |
59 | pNode->fPingQueued = true; | |
60 | } | |
61 | ||
ed21d5bd | 62 | return NullUniValue; |
971bb3e9 JL |
63 | } |
64 | ||
1006f070 JG |
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 | ||
d014114d | 78 | UniValue getpeerinfo(const UniValue& params, bool fHelp) |
1006f070 JG |
79 | { |
80 | if (fHelp || params.size() != 0) | |
81 | throw runtime_error( | |
82 | "getpeerinfo\n" | |
a6099ef3 | 83 | "\nReturns data about each connected network node as a json array of objects.\n" |
84 | "\nbResult:\n" | |
85 | "[\n" | |
86 | " {\n" | |
c4a321f5 | 87 | " \"id\": n, (numeric) Peer index\n" |
a6099ef3 | 88 | " \"addr\":\"host:port\", (string) The ip address and port of the peer\n" |
89 | " \"addrlocal\":\"ip:port\", (string) local address\n" | |
99ddc6cb | 90 | " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n" |
a6099ef3 | 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" | |
26a6bae7 | 96 | " \"timeoffset\": ttt, (numeric) The time offset in seconds\n" |
a6099ef3 | 97 | " \"pingtime\": n, (numeric) ping time\n" |
98 | " \"pingwait\": n, (numeric) ping wait\n" | |
5bd677f5 S |
99 | " \"version\": v, (numeric) The peer version, such as 170002\n" |
100 | " \"subver\": \"/MagicBean:x.y.z[-v]/\", (string) The string version\n" | |
a6099ef3 | 101 | " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n" |
102 | " \"startingheight\": n, (numeric) The starting height (block) of the peer\n" | |
ee304b6e | 103 | " \"banscore\": n, (numeric) The ban score\n" |
ad6e6017 PW |
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" | |
a6099ef3 | 110 | " }\n" |
111 | " ,...\n" | |
7de3f1cf | 112 | "]\n" |
a6099ef3 | 113 | "\nExamples:\n" |
114 | + HelpExampleCli("getpeerinfo", "") | |
115 | + HelpExampleRpc("getpeerinfo", "") | |
116 | ); | |
1006f070 | 117 | |
4401b2d7 EL |
118 | LOCK(cs_main); |
119 | ||
1006f070 JG |
120 | vector<CNodeStats> vstats; |
121 | CopyNodeStats(vstats); | |
122 | ||
38fc4b70 | 123 | UniValue ret(UniValue::VARR); |
1006f070 JG |
124 | |
125 | BOOST_FOREACH(const CNodeStats& stats, vstats) { | |
38fc4b70 | 126 | UniValue obj(UniValue::VOBJ); |
b2864d2f PW |
127 | CNodeStateStats statestats; |
128 | bool fStateStats = GetNodeStateStats(stats.nodeid, statestats); | |
c4a321f5 | 129 | obj.push_back(Pair("id", stats.nodeid)); |
1006f070 | 130 | obj.push_back(Pair("addr", stats.addrName)); |
547c61f8 JL |
131 | if (!(stats.addrLocal.empty())) |
132 | obj.push_back(Pair("addrlocal", stats.addrLocal)); | |
99ddc6cb | 133 | obj.push_back(Pair("services", strprintf("%016x", stats.nServices))); |
d56e30ca KD |
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)); | |
26a6bae7 | 139 | obj.push_back(Pair("timeoffset", stats.nTimeOffset)); |
971bb3e9 JL |
140 | obj.push_back(Pair("pingtime", stats.dPingTime)); |
141 | if (stats.dPingWait > 0.0) | |
142 | obj.push_back(Pair("pingwait", stats.dPingWait)); | |
1006f070 | 143 | obj.push_back(Pair("version", stats.nVersion)); |
a946aa8d | 144 | // Use the sanitized form of subver here, to avoid tricksy remote peers from |
c938fb1f | 145 | // corrupting or modifying the JSON output by putting special characters in |
a946aa8d MH |
146 | // their ver message. |
147 | obj.push_back(Pair("subver", stats.cleanSubVer)); | |
1006f070 | 148 | obj.push_back(Pair("inbound", stats.fInbound)); |
18e8e437 | 149 | obj.push_back(Pair("startingheight", stats.nStartingHeight)); |
b2864d2f PW |
150 | if (fStateStats) { |
151 | obj.push_back(Pair("banscore", statestats.nMisbehavior)); | |
ad6e6017 PW |
152 | obj.push_back(Pair("synced_headers", statestats.nSyncHeight)); |
153 | obj.push_back(Pair("synced_blocks", statestats.nCommonHeight)); | |
38fc4b70 | 154 | UniValue heights(UniValue::VARR); |
ad6e6017 PW |
155 | BOOST_FOREACH(int height, statestats.vHeightInFlight) { |
156 | heights.push_back(height); | |
157 | } | |
158 | obj.push_back(Pair("inflight", heights)); | |
b2864d2f | 159 | } |
dc942e6f | 160 | obj.push_back(Pair("whitelisted", stats.fWhitelisted)); |
1006f070 JG |
161 | |
162 | ret.push_back(obj); | |
163 | } | |
ea0796bd | 164 | |
1006f070 JG |
165 | return ret; |
166 | } | |
70ab73a0 | 167 | |
6477ad07 | 168 | int32_t KOMODO_LONGESTCHAIN; |
f595c2e0 | 169 | int32_t komodo_longestchain() |
170 | { | |
171 | int32_t ht,n=0,num=0,maxheight=0,height = 0; | |
6bb74a02 | 172 | vector<CNodeStats> vstats; |
265660f7 | 173 | { |
174 | LOCK(cs_main); | |
265660f7 | 175 | CopyNodeStats(vstats); |
176 | } | |
f595c2e0 | 177 | BOOST_FOREACH(const CNodeStats& stats, vstats) |
178 | { | |
6477ad07 | 179 | //fprintf(stderr,"komodo_longestchain iter.%d\n",n); |
f595c2e0 | 180 | CNodeStateStats statestats; |
181 | bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); | |
182 | ht = 0; | |
183 | if ( stats.nStartingHeight > ht ) | |
184 | ht = stats.nStartingHeight; | |
ffaeceae | 185 | if ( statestats.nSyncHeight > ht ) |
186 | ht = statestats.nSyncHeight; | |
187 | if ( statestats.nCommonHeight > ht ) | |
188 | ht = statestats.nCommonHeight; | |
f595c2e0 | 189 | if ( maxheight == 0 || ht > maxheight*1.01 ) |
190 | maxheight = ht, num = 1; | |
191 | else if ( ht > maxheight*0.99 ) | |
192 | num++; | |
193 | n++; | |
194 | if ( ht > height ) | |
195 | height = ht; | |
196 | } | |
197 | if ( num > (n >> 1) ) | |
6477ad07 | 198 | { |
20e2d0b7 | 199 | extern char ASSETCHAINS_SYMBOL[]; |
6dcd15b5 | 200 | if ( 0 && height != KOMODO_LONGESTCHAIN ) |
c3d91e3b | 201 | fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); |
6477ad07 | 202 | KOMODO_LONGESTCHAIN = height; |
f595c2e0 | 203 | return(height); |
6477ad07 | 204 | } |
205 | KOMODO_LONGESTCHAIN = 0; | |
206 | return(0); | |
f595c2e0 | 207 | } |
208 | ||
d014114d | 209 | UniValue addnode(const UniValue& params, bool fHelp) |
72a348fd MC |
210 | { |
211 | string strCommand; | |
212 | if (params.size() == 2) | |
213 | strCommand = params[1].get_str(); | |
214 | if (fHelp || params.size() != 2 || | |
215 | (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) | |
216 | throw runtime_error( | |
a6099ef3 | 217 | "addnode \"node\" \"add|remove|onetry\"\n" |
218 | "\nAttempts add or remove a node from the addnode list.\n" | |
219 | "Or try a connection to a node once.\n" | |
220 | "\nArguments:\n" | |
221 | "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" | |
222 | "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" | |
223 | "\nExamples:\n" | |
3985a40d JG |
224 | + HelpExampleCli("addnode", "\"192.168.0.6:8233\" \"onetry\"") |
225 | + HelpExampleRpc("addnode", "\"192.168.0.6:8233\", \"onetry\"") | |
a6099ef3 | 226 | ); |
72a348fd MC |
227 | |
228 | string strNode = params[0].get_str(); | |
229 | ||
230 | if (strCommand == "onetry") | |
231 | { | |
232 | CAddress addr; | |
b641c9cd | 233 | OpenNetworkConnection(addr, NULL, strNode.c_str()); |
ed21d5bd | 234 | return NullUniValue; |
72a348fd MC |
235 | } |
236 | ||
237 | LOCK(cs_vAddedNodes); | |
238 | vector<string>::iterator it = vAddedNodes.begin(); | |
239 | for(; it != vAddedNodes.end(); it++) | |
240 | if (strNode == *it) | |
241 | break; | |
242 | ||
243 | if (strCommand == "add") | |
244 | { | |
245 | if (it != vAddedNodes.end()) | |
4315ec1a | 246 | throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added"); |
72a348fd MC |
247 | vAddedNodes.push_back(strNode); |
248 | } | |
249 | else if(strCommand == "remove") | |
250 | { | |
251 | if (it == vAddedNodes.end()) | |
4315ec1a | 252 | throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); |
72a348fd MC |
253 | vAddedNodes.erase(it); |
254 | } | |
255 | ||
ed21d5bd | 256 | return NullUniValue; |
72a348fd MC |
257 | } |
258 | ||
94ee48c4 AP |
259 | UniValue disconnectnode(const UniValue& params, bool fHelp) |
260 | { | |
261 | if (fHelp || params.size() != 1) | |
262 | throw runtime_error( | |
263 | "disconnectnode \"node\" \n" | |
264 | "\nImmediately disconnects from the specified node.\n" | |
265 | "\nArguments:\n" | |
266 | "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" | |
267 | "\nExamples:\n" | |
4acd140e JG |
268 | + HelpExampleCli("disconnectnode", "\"192.168.0.6:8233\"") |
269 | + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8233\"") | |
94ee48c4 AP |
270 | ); |
271 | ||
272 | CNode* pNode = FindNode(params[0].get_str()); | |
273 | if (pNode == NULL) | |
274 | throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); | |
275 | ||
cbf3ab51 | 276 | pNode->fDisconnect = true; |
94ee48c4 AP |
277 | |
278 | return NullUniValue; | |
279 | } | |
280 | ||
d014114d | 281 | UniValue getaddednodeinfo(const UniValue& params, bool fHelp) |
67a11bd6 MC |
282 | { |
283 | if (fHelp || params.size() < 1 || params.size() > 2) | |
284 | throw runtime_error( | |
a6099ef3 | 285 | "getaddednodeinfo dns ( \"node\" )\n" |
286 | "\nReturns information about the given added node, or all added nodes\n" | |
67a11bd6 MC |
287 | "(note that onetry addnodes are not listed here)\n" |
288 | "If dns is false, only a list of added nodes will be provided,\n" | |
a6099ef3 | 289 | "otherwise connected information will also be available.\n" |
290 | "\nArguments:\n" | |
291 | "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n" | |
292 | "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" | |
293 | "\nResult:\n" | |
294 | "[\n" | |
295 | " {\n" | |
296 | " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n" | |
297 | " \"connected\" : true|false, (boolean) If connected\n" | |
298 | " \"addresses\" : [\n" | |
299 | " {\n" | |
a7322d77 | 300 | " \"address\" : \"192.168.0.201:8233\", (string) The Komodo server host and port\n" |
a6099ef3 | 301 | " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n" |
302 | " }\n" | |
303 | " ,...\n" | |
304 | " ]\n" | |
305 | " }\n" | |
306 | " ,...\n" | |
307 | "]\n" | |
308 | "\nExamples:\n" | |
309 | + HelpExampleCli("getaddednodeinfo", "true") | |
310 | + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"") | |
311 | + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"") | |
312 | ); | |
67a11bd6 MC |
313 | |
314 | bool fDns = params[0].get_bool(); | |
315 | ||
316 | list<string> laddedNodes(0); | |
317 | if (params.size() == 1) | |
318 | { | |
319 | LOCK(cs_vAddedNodes); | |
db954a65 | 320 | BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) |
67a11bd6 MC |
321 | laddedNodes.push_back(strAddNode); |
322 | } | |
323 | else | |
324 | { | |
325 | string strNode = params[1].get_str(); | |
326 | LOCK(cs_vAddedNodes); | |
db954a65 | 327 | BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) { |
67a11bd6 MC |
328 | if (strAddNode == strNode) |
329 | { | |
330 | laddedNodes.push_back(strAddNode); | |
331 | break; | |
332 | } | |
db954a65 | 333 | } |
67a11bd6 | 334 | if (laddedNodes.size() == 0) |
4315ec1a | 335 | throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); |
67a11bd6 MC |
336 | } |
337 | ||
38fc4b70 | 338 | UniValue ret(UniValue::VARR); |
67a11bd6 MC |
339 | if (!fDns) |
340 | { | |
db954a65 | 341 | BOOST_FOREACH (const std::string& strAddNode, laddedNodes) { |
38fc4b70 | 342 | UniValue obj(UniValue::VOBJ); |
4412c5a7 WL |
343 | obj.push_back(Pair("addednode", strAddNode)); |
344 | ret.push_back(obj); | |
345 | } | |
67a11bd6 MC |
346 | return ret; |
347 | } | |
348 | ||
67a11bd6 | 349 | list<pair<string, vector<CService> > > laddedAddreses(0); |
db954a65 | 350 | BOOST_FOREACH(const std::string& strAddNode, laddedNodes) { |
67a11bd6 | 351 | vector<CService> vservNode(0); |
0e4b3175 | 352 | if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) |
67a11bd6 MC |
353 | laddedAddreses.push_back(make_pair(strAddNode, vservNode)); |
354 | else | |
355 | { | |
38fc4b70 | 356 | UniValue obj(UniValue::VOBJ); |
67a11bd6 MC |
357 | obj.push_back(Pair("addednode", strAddNode)); |
358 | obj.push_back(Pair("connected", false)); | |
38fc4b70 | 359 | UniValue addresses(UniValue::VARR); |
67a11bd6 MC |
360 | obj.push_back(Pair("addresses", addresses)); |
361 | } | |
362 | } | |
363 | ||
364 | LOCK(cs_vNodes); | |
365 | for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) | |
366 | { | |
38fc4b70 | 367 | UniValue obj(UniValue::VOBJ); |
67a11bd6 MC |
368 | obj.push_back(Pair("addednode", it->first)); |
369 | ||
38fc4b70 | 370 | UniValue addresses(UniValue::VARR); |
67a11bd6 | 371 | bool fConnected = false; |
db954a65 | 372 | BOOST_FOREACH(const CService& addrNode, it->second) { |
67a11bd6 | 373 | bool fFound = false; |
38fc4b70 | 374 | UniValue node(UniValue::VOBJ); |
67a11bd6 | 375 | node.push_back(Pair("address", addrNode.ToString())); |
db954a65 | 376 | BOOST_FOREACH(CNode* pnode, vNodes) { |
67a11bd6 MC |
377 | if (pnode->addr == addrNode) |
378 | { | |
379 | fFound = true; | |
380 | fConnected = true; | |
381 | node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); | |
382 | break; | |
383 | } | |
db954a65 | 384 | } |
67a11bd6 MC |
385 | if (!fFound) |
386 | node.push_back(Pair("connected", "false")); | |
387 | addresses.push_back(node); | |
388 | } | |
389 | obj.push_back(Pair("connected", fConnected)); | |
390 | obj.push_back(Pair("addresses", addresses)); | |
391 | ret.push_back(obj); | |
392 | } | |
393 | ||
394 | return ret; | |
395 | } | |
396 | ||
d014114d | 397 | UniValue getnettotals(const UniValue& params, bool fHelp) |
ce14345a SE |
398 | { |
399 | if (fHelp || params.size() > 0) | |
400 | throw runtime_error( | |
401 | "getnettotals\n" | |
a6099ef3 | 402 | "\nReturns information about network traffic, including bytes in, bytes out,\n" |
403 | "and current time.\n" | |
404 | "\nResult:\n" | |
405 | "{\n" | |
406 | " \"totalbytesrecv\": n, (numeric) Total bytes received\n" | |
38cbeab1 | 407 | " \"totalbytessent\": n, (numeric) Total bytes sent\n" |
a6099ef3 | 408 | " \"timemillis\": t (numeric) Total cpu time\n" |
409 | "}\n" | |
410 | "\nExamples:\n" | |
411 | + HelpExampleCli("getnettotals", "") | |
412 | + HelpExampleRpc("getnettotals", "") | |
413 | ); | |
ce14345a | 414 | |
38fc4b70 | 415 | UniValue obj(UniValue::VOBJ); |
d56e30ca KD |
416 | obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); |
417 | obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); | |
418 | obj.push_back(Pair("timemillis", GetTimeMillis())); | |
ce14345a SE |
419 | return obj; |
420 | } | |
d387b8ec | 421 | |
851f58f9 | 422 | static UniValue GetNetworksInfo() |
aa827951 | 423 | { |
38fc4b70 | 424 | UniValue networks(UniValue::VARR); |
aa827951 WL |
425 | for(int n=0; n<NET_MAX; ++n) |
426 | { | |
427 | enum Network network = static_cast<enum Network>(n); | |
428 | if(network == NET_UNROUTABLE) | |
429 | continue; | |
430 | proxyType proxy; | |
38fc4b70 | 431 | UniValue obj(UniValue::VOBJ); |
aa827951 WL |
432 | GetProxy(network, proxy); |
433 | obj.push_back(Pair("name", GetNetworkName(network))); | |
434 | obj.push_back(Pair("limited", IsLimited(network))); | |
435 | obj.push_back(Pair("reachable", IsReachable(network))); | |
67a79493 WL |
436 | obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())); |
437 | obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials)); | |
aa827951 WL |
438 | networks.push_back(obj); |
439 | } | |
440 | return networks; | |
441 | } | |
442 | ||
9d2974ed JG |
443 | UniValue getdeprecationinfo(const UniValue& params, bool fHelp) |
444 | { | |
df46562f JG |
445 | const CChainParams& chainparams = Params(); |
446 | if (fHelp || params.size() != 0 || chainparams.NetworkIDString() != "main") | |
9d2974ed JG |
447 | throw runtime_error( |
448 | "getdeprecationinfo\n" | |
df46562f | 449 | "Returns an object containing current version and deprecation block height. Applicable only on mainnet.\n" |
9d2974ed JG |
450 | "\nResult:\n" |
451 | "{\n" | |
452 | " \"version\": xxxxx, (numeric) the server version\n" | |
453 | " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n" | |
c74ab335 | 454 | " \"deprecationheight\": xxxxx, (numeric) the block height at which this version will deprecate and shut down\n" |
9d2974ed JG |
455 | "}\n" |
456 | "\nExamples:\n" | |
457 | + HelpExampleCli("getdeprecationinfo", "") | |
458 | + HelpExampleRpc("getdeprecationinfo", "") | |
459 | ); | |
460 | ||
9d2974ed | 461 | UniValue obj(UniValue::VOBJ); |
df46562f | 462 | obj.push_back(Pair("version", CLIENT_VERSION)); |
9d2974ed JG |
463 | obj.push_back(Pair("subversion", |
464 | FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()))); | |
465 | obj.push_back(Pair("deprecationheight", DEPRECATION_HEIGHT)); | |
466 | ||
467 | return obj; | |
468 | } | |
469 | ||
d014114d | 470 | UniValue getnetworkinfo(const UniValue& params, bool fHelp) |
d387b8ec WL |
471 | { |
472 | if (fHelp || params.size() != 0) | |
473 | throw runtime_error( | |
474 | "getnetworkinfo\n" | |
475 | "Returns an object containing various state info regarding P2P networking.\n" | |
476 | "\nResult:\n" | |
477 | "{\n" | |
b5ec5fe0 | 478 | " \"version\": xxxxx, (numeric) the server version\n" |
5bd677f5 | 479 | " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n" |
b5ec5fe0 PK |
480 | " \"protocolversion\": xxxxx, (numeric) the protocol version\n" |
481 | " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" | |
482 | " \"timeoffset\": xxxxx, (numeric) the time offset\n" | |
483 | " \"connections\": xxxxx, (numeric) the number of connections\n" | |
484 | " \"networks\": [ (array) information per network\n" | |
485 | " {\n" | |
486 | " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n" | |
487 | " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n" | |
488 | " \"reachable\": true|false, (boolean) is the network reachable?\n" | |
489 | " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n" | |
490 | " }\n" | |
491 | " ,...\n" | |
aa827951 | 492 | " ],\n" |
091b2116 | 493 | " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" |
b5ec5fe0 PK |
494 | " \"localaddresses\": [ (array) list of local addresses\n" |
495 | " {\n" | |
496 | " \"address\": \"xxxx\", (string) network address\n" | |
497 | " \"port\": xxx, (numeric) network port\n" | |
498 | " \"score\": xxx (numeric) relative score\n" | |
499 | " }\n" | |
500 | " ,...\n" | |
d387b8ec | 501 | " ]\n" |
6699b425 | 502 | " \"warnings\": \"...\" (string) any network warnings (such as alert messages) \n" |
d387b8ec WL |
503 | "}\n" |
504 | "\nExamples:\n" | |
505 | + HelpExampleCli("getnetworkinfo", "") | |
506 | + HelpExampleRpc("getnetworkinfo", "") | |
507 | ); | |
508 | ||
4401b2d7 EL |
509 | LOCK(cs_main); |
510 | ||
38fc4b70 | 511 | UniValue obj(UniValue::VOBJ); |
b5ec5fe0 | 512 | obj.push_back(Pair("version", CLIENT_VERSION)); |
2bc62dc4 | 513 | obj.push_back(Pair("subversion", strSubVersion)); |
b5ec5fe0 | 514 | obj.push_back(Pair("protocolversion",PROTOCOL_VERSION)); |
99ddc6cb | 515 | obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); |
d56e30ca | 516 | obj.push_back(Pair("timeoffset", GetTimeOffset())); |
d387b8ec | 517 | obj.push_back(Pair("connections", (int)vNodes.size())); |
aa827951 | 518 | obj.push_back(Pair("networks", GetNetworksInfo())); |
13fc83c7 | 519 | obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); |
38fc4b70 | 520 | UniValue localAddresses(UniValue::VARR); |
d387b8ec WL |
521 | { |
522 | LOCK(cs_mapLocalHost); | |
523 | BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) | |
524 | { | |
38fc4b70 | 525 | UniValue rec(UniValue::VOBJ); |
d387b8ec WL |
526 | rec.push_back(Pair("address", item.first.ToString())); |
527 | rec.push_back(Pair("port", item.second.nPort)); | |
528 | rec.push_back(Pair("score", item.second.nScore)); | |
529 | localAddresses.push_back(rec); | |
530 | } | |
531 | } | |
532 | obj.push_back(Pair("localaddresses", localAddresses)); | |
6699b425 | 533 | obj.push_back(Pair("warnings", GetWarnings("statusbar"))); |
d387b8ec WL |
534 | return obj; |
535 | } | |
ed3f13a0 | 536 | |
fcc8920f | 537 | UniValue setban(const UniValue& params, bool fHelp) |
ed3f13a0 JS |
538 | { |
539 | string strCommand; | |
540 | if (params.size() >= 2) | |
541 | strCommand = params[1].get_str(); | |
542 | if (fHelp || params.size() < 2 || | |
543 | (strCommand != "add" && strCommand != "remove")) | |
544 | throw runtime_error( | |
fcc8920f | 545 | "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n" |
e5219399 | 546 | "\nAttempts add or remove a IP/Subnet from the banned list.\n" |
ed3f13a0 | 547 | "\nArguments:\n" |
e5219399 JS |
548 | "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n" |
549 | "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n" | |
fcc8920f JS |
550 | "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" |
551 | "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" | |
ed3f13a0 JS |
552 | "\nExamples:\n" |
553 | + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") | |
e5219399 | 554 | + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") |
ed3f13a0 JS |
555 | + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400") |
556 | ); | |
557 | ||
e5219399 JS |
558 | CSubNet subNet; |
559 | CNetAddr netAddr; | |
560 | bool isSubnet = false; | |
561 | ||
562 | if (params[0].get_str().find("/") != string::npos) | |
563 | isSubnet = true; | |
564 | ||
565 | if (!isSubnet) | |
566 | netAddr = CNetAddr(params[0].get_str()); | |
567 | else | |
568 | subNet = CSubNet(params[0].get_str()); | |
569 | ||
570 | if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) | |
571 | throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet"); | |
ed3f13a0 JS |
572 | |
573 | if (strCommand == "add") | |
574 | { | |
e5219399 JS |
575 | if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr)) |
576 | throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); | |
ed3f13a0 JS |
577 | |
578 | int64_t banTime = 0; //use standard bantime if not specified | |
fcc8920f | 579 | if (params.size() >= 3 && !params[2].isNull()) |
ed3f13a0 JS |
580 | banTime = params[2].get_int64(); |
581 | ||
fcc8920f JS |
582 | bool absolute = false; |
583 | if (params.size() == 4 && params[3].isTrue()) | |
584 | absolute = true; | |
585 | ||
586 | isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute); | |
ed3f13a0 JS |
587 | |
588 | //disconnect possible nodes | |
e5219399 | 589 | while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) |
cbf3ab51 | 590 | bannedNode->fDisconnect = true; |
ed3f13a0 JS |
591 | } |
592 | else if(strCommand == "remove") | |
593 | { | |
e5219399 | 594 | if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) |
1cad8c9f | 595 | throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); |
ed3f13a0 JS |
596 | } |
597 | ||
fcc8920f | 598 | return NullUniValue; |
ed3f13a0 JS |
599 | } |
600 | ||
fcc8920f | 601 | UniValue listbanned(const UniValue& params, bool fHelp) |
ed3f13a0 JS |
602 | { |
603 | if (fHelp || params.size() != 0) | |
604 | throw runtime_error( | |
605 | "listbanned\n" | |
e5219399 | 606 | "\nList all banned IPs/Subnets.\n" |
ed3f13a0 JS |
607 | "\nExamples:\n" |
608 | + HelpExampleCli("listbanned", "") | |
609 | + HelpExampleRpc("listbanned", "") | |
610 | ); | |
611 | ||
e5219399 | 612 | std::map<CSubNet, int64_t> banMap; |
ed3f13a0 JS |
613 | CNode::GetBanned(banMap); |
614 | ||
fcc8920f | 615 | UniValue bannedAddresses(UniValue::VARR); |
e5219399 | 616 | for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++) |
ed3f13a0 | 617 | { |
fcc8920f | 618 | UniValue rec(UniValue::VOBJ); |
ed3f13a0 | 619 | rec.push_back(Pair("address", (*it).first.ToString())); |
14454a3a | 620 | rec.push_back(Pair("banned_until", (*it).second)); |
ed3f13a0 JS |
621 | bannedAddresses.push_back(rec); |
622 | } | |
623 | ||
624 | return bannedAddresses; | |
625 | } | |
626 | ||
fcc8920f | 627 | UniValue clearbanned(const UniValue& params, bool fHelp) |
ed3f13a0 JS |
628 | { |
629 | if (fHelp || params.size() != 0) | |
630 | throw runtime_error( | |
631 | "clearbanned\n" | |
632 | "\nClear all banned IPs.\n" | |
633 | "\nExamples:\n" | |
634 | + HelpExampleCli("clearbanned", "") | |
635 | + HelpExampleRpc("clearbanned", "") | |
636 | ); | |
637 | ||
638 | CNode::ClearBanned(); | |
639 | ||
fcc8920f | 640 | return NullUniValue; |
ed3f13a0 | 641 | } |
a9496b08 WL |
642 | |
643 | static const CRPCCommand commands[] = | |
644 | { // category name actor (function) okSafeMode | |
645 | // --------------------- ------------------------ ----------------------- ---------- | |
646 | { "network", "getconnectioncount", &getconnectioncount, true }, | |
647 | { "network", "getdeprecationinfo", &getdeprecationinfo, true }, | |
648 | { "network", "ping", &ping, true }, | |
649 | { "network", "getpeerinfo", &getpeerinfo, true }, | |
650 | { "network", "addnode", &addnode, true }, | |
651 | { "network", "disconnectnode", &disconnectnode, true }, | |
652 | { "network", "getaddednodeinfo", &getaddednodeinfo, true }, | |
653 | { "network", "getnettotals", &getnettotals, true }, | |
654 | { "network", "getnetworkinfo", &getnetworkinfo, true }, | |
655 | { "network", "setban", &setban, true }, | |
656 | { "network", "listbanned", &listbanned, true }, | |
657 | { "network", "clearbanned", &clearbanned, true }, | |
658 | }; | |
659 | ||
660 | void RegisterNetRPCCommands(CRPCTable &tableRPC) | |
661 | { | |
662 | for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) | |
663 | tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); | |
664 | } |