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