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.
5 #include "bitcoinrpc.h"
12 using namespace json_spirit;
15 Value getconnectioncount(const Array& params, bool fHelp)
17 if (fHelp || params.size() != 0)
19 "getconnectioncount\n"
20 "Returns the number of connections to other nodes.");
23 return (int)vNodes.size();
26 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
31 vstats.reserve(vNodes.size());
32 BOOST_FOREACH(CNode* pnode, vNodes) {
34 pnode->copyStats(stats);
35 vstats.push_back(stats);
39 struct addrManItemSort {
40 bool operator()(const CAddrInfo &leftItem, const CAddrInfo &rightItem) {
41 int64_t nTime = GetTime();
42 return leftItem.GetChance(nTime) > rightItem.GetChance(nTime);
46 Value getaddrmaninfo(const Array& params, bool fHelp)
48 if (fHelp || params.size() > 1)
50 "getaddrmaninfo [networkType]\n"
51 "Returns a dump of addrman data.");
53 // Get a full list of "online" address items
54 vector<CAddrInfo> vAddr = addrman.GetOnlineAddr();
56 // Sort by the GetChance result backwardly
57 sort(vAddr.begin(), vAddr.end(), addrManItemSort());
59 string strFilterNetType = "";
60 if (params.size() == 1)
61 strFilterNetType = params[0].get_str();
64 BOOST_FOREACH(const CAddrInfo &addr, vAddr) {
65 if (!addr.IsRoutable() || addr.IsLocal())
69 addrManItem.push_back(Pair("address", addr.ToString()));
72 switch(addr.GetNetwork())
78 // strNetType = "i2p";
89 if (strFilterNetType.size() != 0 && strNetType != strFilterNetType)
92 addrManItem.push_back(Pair("chance", addr.GetChance(GetTime())));
93 addrManItem.push_back(Pair("type", strNetType));
94 addrManItem.push_back(Pair("time", (int64_t)addr.nTime));
96 ret.push_back(addrManItem);
102 Value getpeerinfo(const Array& params, bool fHelp)
104 if (fHelp || params.size() != 0)
107 "Returns data about each connected network node.");
109 vector<CNodeStats> vstats;
110 CopyNodeStats(vstats);
114 BOOST_FOREACH(const CNodeStats& stats, vstats) {
117 obj.push_back(Pair("addr", stats.addrName));
118 obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices)));
119 obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
120 obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
121 obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes));
122 obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes));
123 obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
124 obj.push_back(Pair("version", stats.nVersion));
125 obj.push_back(Pair("subver", stats.strSubVer));
126 obj.push_back(Pair("inbound", stats.fInbound));
127 obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime));
128 obj.push_back(Pair("startingheight", stats.nStartingHeight));
129 obj.push_back(Pair("banscore", stats.nMisbehavior));
131 obj.push_back(Pair("syncnode", true));
138 Value addnode(const Array& params, bool fHelp)
141 if (params.size() == 2)
142 strCommand = params[1].get_str();
143 if (fHelp || params.size() != 2 ||
144 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
146 "addnode <node> <add|remove|onetry>\n"
147 "Attempts add or remove <node> from the addnode list or try a connection to <node> once.");
149 string strNode = params[0].get_str();
151 if (strCommand == "onetry")
154 OpenNetworkConnection(addr, NULL, strNode.c_str());
158 LOCK(cs_vAddedNodes);
159 vector<string>::iterator it = vAddedNodes.begin();
160 for(; it != vAddedNodes.end(); it++)
164 if (strCommand == "add")
166 if (it != vAddedNodes.end())
167 throw JSONRPCError(-23, "Error: Node already added");
168 vAddedNodes.push_back(strNode);
170 else if(strCommand == "remove")
172 if (it == vAddedNodes.end())
173 throw JSONRPCError(-24, "Error: Node has not been added.");
174 vAddedNodes.erase(it);
180 Value getaddednodeinfo(const Array& params, bool fHelp)
182 if (fHelp || params.size() < 1 || params.size() > 2)
184 "getaddednodeinfo <dns> [node]\n"
185 "Returns information about the given added node, or all added nodes\n"
186 "(note that onetry addnodes are not listed here)\n"
187 "If dns is false, only a list of added nodes will be provided,\n"
188 "otherwise connected information will also be available.");
190 bool fDns = params[0].get_bool();
192 list<string> laddedNodes(0);
193 if (params.size() == 1)
195 LOCK(cs_vAddedNodes);
196 BOOST_FOREACH(string& strAddNode, vAddedNodes)
197 laddedNodes.push_back(strAddNode);
201 string strNode = params[1].get_str();
202 LOCK(cs_vAddedNodes);
203 BOOST_FOREACH(string& strAddNode, vAddedNodes)
204 if (strAddNode == strNode)
206 laddedNodes.push_back(strAddNode);
209 if (laddedNodes.size() == 0)
210 throw JSONRPCError(-24, "Error: Node has not been added.");
216 BOOST_FOREACH(string& strAddNode, laddedNodes)
217 ret.push_back(Pair("addednode", strAddNode));
223 list<pair<string, vector<CService> > > laddedAddreses(0);
224 BOOST_FOREACH(string& strAddNode, laddedNodes)
226 vector<CService> vservNode(0);
227 if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
228 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
232 obj.push_back(Pair("addednode", strAddNode));
233 obj.push_back(Pair("connected", false));
235 obj.push_back(Pair("addresses", addresses));
240 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
243 obj.push_back(Pair("addednode", it->first));
246 bool fConnected = false;
247 BOOST_FOREACH(CService& addrNode, it->second)
251 node.push_back(Pair("address", addrNode.ToString()));
252 BOOST_FOREACH(CNode* pnode, vNodes)
253 if (pnode->addr == addrNode)
257 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
261 node.push_back(Pair("connected", "false"));
262 addresses.push_back(node);
264 obj.push_back(Pair("connected", fConnected));
265 obj.push_back(Pair("addresses", addresses));
272 // There is a known deadlock situation with ThreadMessageHandler
273 // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages()
274 // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage()
275 Value sendalert(const Array& params, bool fHelp)
277 if (fHelp || params.size() < 6)
279 "sendalert <message> <privatekey> <minver> <maxver> <priority> <id> [cancelupto]\n"
280 "<message> is the alert text message\n"
281 "<privatekey> is hex string of alert master private key\n"
282 "<minver> is the minimum applicable internal client version\n"
283 "<maxver> is the maximum applicable internal client version\n"
284 "<priority> is integer priority number\n"
285 "<id> is the alert id\n"
286 "[cancelupto] cancels all alert id's up to this number\n"
287 "Returns true or false.");
292 alert.strStatusBar = params[0].get_str();
293 alert.nMinVer = params[2].get_int();
294 alert.nMaxVer = params[3].get_int();
295 alert.nPriority = params[4].get_int();
296 alert.nID = params[5].get_int();
297 if (params.size() > 6)
298 alert.nCancel = params[6].get_int();
299 alert.nVersion = PROTOCOL_VERSION;
300 alert.nRelayUntil = GetAdjustedTime() + 365*24*60*60;
301 alert.nExpiration = GetAdjustedTime() + 365*24*60*60;
303 CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
304 sMsg << (CUnsignedAlert)alert;
305 alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end());
307 vector<unsigned char> vchPrivKey = ParseHex(params[1].get_str());
308 key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash
309 if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig))
311 "Unable to sign alert, check private key?\n");
312 if(!alert.ProcessAlert())
314 "Failed to process alert.\n");
318 BOOST_FOREACH(CNode* pnode, vNodes)
319 alert.RelayTo(pnode);
323 result.push_back(Pair("strStatusBar", alert.strStatusBar));
324 result.push_back(Pair("nVersion", alert.nVersion));
325 result.push_back(Pair("nMinVer", alert.nMinVer));
326 result.push_back(Pair("nMaxVer", alert.nMaxVer));
327 result.push_back(Pair("nPriority", alert.nPriority));
328 result.push_back(Pair("nID", alert.nID));
329 if (alert.nCancel > 0)
330 result.push_back(Pair("nCancel", alert.nCancel));
334 Value getnettotals(const Array& params, bool fHelp)
336 if (fHelp || params.size() > 0)
339 "Returns information about network traffic, including bytes in, bytes out,\n"
340 "and current time.");
343 obj.push_back(Pair("totalbytesrecv", static_cast< boost::uint64_t>(CNode::GetTotalBytesRecv())));
344 obj.push_back(Pair("totalbytessent", static_cast<boost::uint64_t>(CNode::GetTotalBytesSent())));
345 obj.push_back(Pair("timemillis", static_cast<boost::int64_t>(GetTimeMillis())));