RPC: getaddrmaninfo
[novacoin.git] / src / rpcnet.cpp
1 // Copyright (c) 2009-2012 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 "bitcoinrpc.h"
6 #include "alert.h"
7 #include "wallet.h"
8 #include "db.h"
9 #include "walletdb.h"
10 #include "net.h"
11
12 using namespace json_spirit;
13 using namespace std;
14
15 Value getconnectioncount(const Array& params, bool fHelp)
16 {
17     if (fHelp || params.size() != 0)
18         throw runtime_error(
19             "getconnectioncount\n"
20             "Returns the number of connections to other nodes.");
21
22     LOCK(cs_vNodes);
23     return (int)vNodes.size();
24 }
25
26 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
27 {
28     vstats.clear();
29
30     LOCK(cs_vNodes);
31     vstats.reserve(vNodes.size());
32     BOOST_FOREACH(CNode* pnode, vNodes) {
33         CNodeStats stats;
34         pnode->copyStats(stats);
35         vstats.push_back(stats);
36     }
37 }
38
39 Value getaddrmaninfo(const Array& params, bool fHelp)
40 {
41     if (fHelp || params.size() != 0)
42         throw runtime_error(
43             "getaddrmaninfo\n"
44             "Returns a dump of addrman data.");
45
46     vector<CAddress> vAddr = addrman.GetAddr();
47
48     Array ret;
49
50     BOOST_FOREACH(const CAddress &addr, vAddr) {
51         // Don't return addresses older than nCutOff timestamp
52         int64_t nCutOff = GetTime() - (nNodeLifespan * 24 * 60 * 60);
53
54         if (!addr.IsRoutable() || addr.IsLocal() || addr.nTime > nCutOff)
55             continue;
56
57         Object addrManItem;
58         addrManItem.push_back(Pair("address", addr.ToString()));
59
60         string strNetType;
61         switch(addr.GetNetwork())
62         {
63             case NET_TOR:
64                 strNetType = "tor";
65             break;
66             case NET_I2P:
67                 strNetType = "i2p";
68             case NET_IPV4:
69                 strNetType = "ipv4";
70             break;
71             default:
72             case NET_IPV6:
73                 strNetType = "ipv6";
74
75         }
76         addrManItem.push_back(Pair("type", strNetType));
77         addrManItem.push_back(Pair("time", (int64_t)addr.nTime));
78
79         ret.push_back(addrManItem);
80     }
81
82     return ret;
83 }
84
85 Value getpeerinfo(const Array& params, bool fHelp)
86 {
87     if (fHelp || params.size() != 0)
88         throw runtime_error(
89             "getpeerinfo\n"
90             "Returns data about each connected network node.");
91
92     vector<CNodeStats> vstats;
93     CopyNodeStats(vstats);
94
95     Array ret;
96
97     BOOST_FOREACH(const CNodeStats& stats, vstats) {
98         Object obj;
99
100         obj.push_back(Pair("addr", stats.addrName));
101         obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices)));
102         obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
103         obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
104         obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes));
105         obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes));
106         obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
107         obj.push_back(Pair("version", stats.nVersion));
108         obj.push_back(Pair("subver", stats.strSubVer));
109         obj.push_back(Pair("inbound", stats.fInbound));
110         obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime));
111         obj.push_back(Pair("startingheight", stats.nStartingHeight));
112         obj.push_back(Pair("banscore", stats.nMisbehavior));
113         if (stats.fSyncNode)
114             obj.push_back(Pair("syncnode", true));
115         ret.push_back(obj);
116     }
117
118     return ret;
119 }
120
121 Value addnode(const Array& params, bool fHelp)
122 {
123     string strCommand;
124     if (params.size() == 2)
125         strCommand = params[1].get_str();
126     if (fHelp || params.size() != 2 ||
127         (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
128         throw runtime_error(
129             "addnode <node> <add|remove|onetry>\n"
130             "Attempts add or remove <node> from the addnode list or try a connection to <node> once.");
131
132     string strNode = params[0].get_str();
133
134     if (strCommand == "onetry")
135     {
136         CAddress addr;
137         OpenNetworkConnection(addr, NULL, strNode.c_str());
138         return Value::null;
139     }
140
141     LOCK(cs_vAddedNodes);
142     vector<string>::iterator it = vAddedNodes.begin();
143     for(; it != vAddedNodes.end(); it++)
144         if (strNode == *it)
145             break;
146
147     if (strCommand == "add")
148     {
149         if (it != vAddedNodes.end())
150             throw JSONRPCError(-23, "Error: Node already added");
151         vAddedNodes.push_back(strNode);
152     }
153     else if(strCommand == "remove")
154     {
155         if (it == vAddedNodes.end())
156             throw JSONRPCError(-24, "Error: Node has not been added.");
157         vAddedNodes.erase(it);
158     }
159
160     return Value::null;
161 }
162
163 Value getaddednodeinfo(const Array& params, bool fHelp)
164 {
165     if (fHelp || params.size() < 1 || params.size() > 2)
166         throw runtime_error(
167             "getaddednodeinfo <dns> [node]\n"
168             "Returns information about the given added node, or all added nodes\n"
169             "(note that onetry addnodes are not listed here)\n"
170             "If dns is false, only a list of added nodes will be provided,\n"
171             "otherwise connected information will also be available.");
172
173     bool fDns = params[0].get_bool();
174
175     list<string> laddedNodes(0);
176     if (params.size() == 1)
177     {
178         LOCK(cs_vAddedNodes);
179         BOOST_FOREACH(string& strAddNode, vAddedNodes)
180             laddedNodes.push_back(strAddNode);
181     }
182     else
183     {
184         string strNode = params[1].get_str();
185         LOCK(cs_vAddedNodes);
186         BOOST_FOREACH(string& strAddNode, vAddedNodes)
187             if (strAddNode == strNode)
188             {
189                 laddedNodes.push_back(strAddNode);
190                 break;
191             }
192         if (laddedNodes.size() == 0)
193             throw JSONRPCError(-24, "Error: Node has not been added.");
194         }
195
196         if (!fDns)
197         {
198             Object ret;
199             BOOST_FOREACH(string& strAddNode, laddedNodes)
200                 ret.push_back(Pair("addednode", strAddNode));
201             return ret;
202         }
203
204         Array ret;
205
206         list<pair<string, vector<CService> > > laddedAddreses(0);
207         BOOST_FOREACH(string& strAddNode, laddedNodes)
208         {
209             vector<CService> vservNode(0);
210             if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
211                 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
212             else
213             {
214                 Object obj;
215                 obj.push_back(Pair("addednode", strAddNode));
216                 obj.push_back(Pair("connected", false));
217                 Array addresses;
218                 obj.push_back(Pair("addresses", addresses));
219             }
220         }
221
222     LOCK(cs_vNodes);
223     for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
224     {
225         Object obj;
226         obj.push_back(Pair("addednode", it->first));
227
228         Array addresses;
229         bool fConnected = false;
230         BOOST_FOREACH(CService& addrNode, it->second)
231         {
232             bool fFound = false;
233             Object node;
234             node.push_back(Pair("address", addrNode.ToString()));
235             BOOST_FOREACH(CNode* pnode, vNodes)
236                 if (pnode->addr == addrNode)
237                 {
238                     fFound = true;
239                     fConnected = true;
240                     node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
241                     break;
242                 }
243             if (!fFound)
244                 node.push_back(Pair("connected", "false"));
245             addresses.push_back(node);
246         }
247         obj.push_back(Pair("connected", fConnected));
248         obj.push_back(Pair("addresses", addresses));
249         ret.push_back(obj);
250     }
251
252     return ret;
253 }
254
255 extern CCriticalSection cs_mapAlerts;
256 extern map<uint256, CAlert> mapAlerts;
257  
258 // ppcoin: send alert.  
259 // There is a known deadlock situation with ThreadMessageHandler
260 // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages()
261 // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage()
262 Value sendalert(const Array& params, bool fHelp)
263 {
264     if (fHelp || params.size() < 6)
265         throw runtime_error(
266             "sendalert <message> <privatekey> <minver> <maxver> <priority> <id> [cancelupto]\n"
267             "<message> is the alert text message\n"
268             "<privatekey> is hex string of alert master private key\n"
269             "<minver> is the minimum applicable internal client version\n"
270             "<maxver> is the maximum applicable internal client version\n"
271             "<priority> is integer priority number\n"
272             "<id> is the alert id\n"
273             "[cancelupto] cancels all alert id's up to this number\n"
274             "Returns true or false.");
275
276     CAlert alert;
277     CKey key;
278
279     alert.strStatusBar = params[0].get_str();
280     alert.nMinVer = params[2].get_int();
281     alert.nMaxVer = params[3].get_int();
282     alert.nPriority = params[4].get_int();
283     alert.nID = params[5].get_int();
284     if (params.size() > 6)
285         alert.nCancel = params[6].get_int();
286     alert.nVersion = PROTOCOL_VERSION;
287     alert.nRelayUntil = GetAdjustedTime() + 365*24*60*60;
288     alert.nExpiration = GetAdjustedTime() + 365*24*60*60;
289
290     CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
291     sMsg << (CUnsignedAlert)alert;
292     alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end());
293
294     vector<unsigned char> vchPrivKey = ParseHex(params[1].get_str());
295     key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash
296     if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig))
297         throw runtime_error(
298             "Unable to sign alert, check private key?\n");  
299     if(!alert.ProcessAlert()) 
300         throw runtime_error(
301             "Failed to process alert.\n");
302     // Relay alert
303     {
304         LOCK(cs_vNodes);
305         BOOST_FOREACH(CNode* pnode, vNodes)
306             alert.RelayTo(pnode);
307     }
308
309     Object result;
310     result.push_back(Pair("strStatusBar", alert.strStatusBar));
311     result.push_back(Pair("nVersion", alert.nVersion));
312     result.push_back(Pair("nMinVer", alert.nMinVer));
313     result.push_back(Pair("nMaxVer", alert.nMaxVer));
314     result.push_back(Pair("nPriority", alert.nPriority));
315     result.push_back(Pair("nID", alert.nID));
316     if (alert.nCancel > 0)
317         result.push_back(Pair("nCancel", alert.nCancel));
318     return result;
319 }
320
321 Value getnettotals(const Array& params, bool fHelp)
322 {
323     if (fHelp || params.size() > 0)
324         throw runtime_error(
325             "getnettotals\n"
326             "Returns information about network traffic, including bytes in, bytes out,\n"
327             "and current time.");
328
329     Object obj;
330     obj.push_back(Pair("totalbytesrecv", static_cast< boost::uint64_t>(CNode::GetTotalBytesRecv())));
331     obj.push_back(Pair("totalbytessent", static_cast<boost::uint64_t>(CNode::GetTotalBytesSent())));
332     obj.push_back(Pair("timemillis", static_cast<boost::int64_t>(GetTimeMillis())));
333     return obj;
334 }