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