Browse Source

Merge pull request #1124 from sipa/rpcobj3

extension of #1103: encapsulate mapCommands in CRPCTable
0.8
Pieter Wuille 12 years ago
parent
commit
457661f640
  1. 193
      src/bitcoinrpc.cpp
  2. 34
      src/bitcoinrpc.h
  3. 9
      src/test/rpc_tests.cpp

193
src/bitcoinrpc.cpp

@ -10,6 +10,7 @@
#include "net.h" #include "net.h"
#include "init.h" #include "init.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "bitcoinrpc.h"
#undef printf #undef printf
#include <boost/asio.hpp> #include <boost/asio.hpp>
@ -22,9 +23,6 @@
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream; typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
#define printf OutputDebugStringF #define printf OutputDebugStringF
// MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
// precompiled in headers.h. The problem might be when the pch file goes over // precompiled in headers.h. The problem might be when the pch file goes over
@ -37,8 +35,6 @@ using namespace boost::asio;
using namespace json_spirit; using namespace json_spirit;
void ThreadRPCServer2(void* parg); void ThreadRPCServer2(void* parg);
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
extern map<string, rpcfn_type> mapCallTable;
static std::string strRPCUserColonPass; static std::string strRPCUserColonPass;
@ -168,23 +164,14 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
/// Note: This interface may still be subject to change. /// Note: This interface may still be subject to change.
/// ///
string CRPCTable::help(string strCommand) const
Value help(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() > 1)
throw runtime_error(
"help [command]\n"
"List commands, or get help for a command.");
string strCommand;
if (params.size() > 0)
strCommand = params[0].get_str();
string strRet; string strRet;
set<rpcfn_type> setDone; set<rpcfn_type> setDone;
for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi) for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
{ {
string strMethod = (*mi).first; const CRPCCommand *pcmd = mi->second;
string strMethod = mi->first;
// We already filter duplicates, but these deprecated screw up the sort order // We already filter duplicates, but these deprecated screw up the sort order
if (strMethod == "getamountreceived" || if (strMethod == "getamountreceived" ||
strMethod == "getallreceived" || strMethod == "getallreceived" ||
@ -196,7 +183,7 @@ Value help(const Array& params, bool fHelp)
try try
{ {
Array params; Array params;
rpcfn_type pfn = (*mi).second; rpcfn_type pfn = pcmd->actor;
if (setDone.insert(pfn).second) if (setDone.insert(pfn).second)
(*pfn)(params, true); (*pfn)(params, true);
} }
@ -216,6 +203,20 @@ Value help(const Array& params, bool fHelp)
return strRet; return strRet;
} }
Value help(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
"help [command]\n"
"List commands, or get help for a command.");
string strCommand;
if (params.size() > 0)
strCommand = params[0].get_str();
return tableRPC.help(strCommand);
}
Value stop(const Array& params, bool fHelp) Value stop(const Array& params, bool fHelp)
{ {
@ -2003,86 +2004,77 @@ Value getblock(const Array& params, bool fHelp)
// Call Table // Call Table
// //
pair<string, rpcfn_type> pCallTable[] =
{ static const CRPCCommand vRPCCommands[] =
make_pair("help", &help), { // name function safe mode?
make_pair("stop", &stop), // ------------------------ ----------------------- ----------
make_pair("getblockcount", &getblockcount), { "help", &help, true },
make_pair("getblocknumber", &getblocknumber), { "stop", &stop, true },
make_pair("getconnectioncount", &getconnectioncount), { "getblockcount", &getblockcount, true },
make_pair("getdifficulty", &getdifficulty), { "getblocknumber", &getblocknumber, true },
make_pair("getgenerate", &getgenerate), { "getconnectioncount", &getconnectioncount, true },
make_pair("setgenerate", &setgenerate), { "getdifficulty", &getdifficulty, true },
make_pair("gethashespersec", &gethashespersec), { "getgenerate", &getgenerate, true },
make_pair("getinfo", &getinfo), { "setgenerate", &setgenerate, true },
make_pair("getmininginfo", &getmininginfo), { "gethashespersec", &gethashespersec, true },
make_pair("getnewaddress", &getnewaddress), { "getinfo", &getinfo, true },
make_pair("getaccountaddress", &getaccountaddress), { "getmininginfo", &getmininginfo, true },
make_pair("setaccount", &setaccount), { "getnewaddress", &getnewaddress, true },
make_pair("getaccount", &getaccount), { "getaccountaddress", &getaccountaddress, true },
make_pair("getaddressesbyaccount", &getaddressesbyaccount), { "setaccount", &setaccount, true },
make_pair("sendtoaddress", &sendtoaddress), { "getaccount", &getaccount, false },
make_pair("getreceivedbyaddress", &getreceivedbyaddress), { "getaddressesbyaccount", &getaddressesbyaccount, true },
make_pair("getreceivedbyaccount", &getreceivedbyaccount), { "sendtoaddress", &sendtoaddress, false },
make_pair("listreceivedbyaddress", &listreceivedbyaddress), { "getreceivedbyaddress", &getreceivedbyaddress, false },
make_pair("listreceivedbyaccount", &listreceivedbyaccount), { "getreceivedbyaccount", &getreceivedbyaccount, false },
make_pair("backupwallet", &backupwallet), { "listreceivedbyaddress", &listreceivedbyaddress, false },
make_pair("keypoolrefill", &keypoolrefill), { "listreceivedbyaccount", &listreceivedbyaccount, false },
make_pair("walletpassphrase", &walletpassphrase), { "backupwallet", &backupwallet, true },
make_pair("walletpassphrasechange", &walletpassphrasechange), { "keypoolrefill", &keypoolrefill, true },
make_pair("walletlock", &walletlock), { "walletpassphrase", &walletpassphrase, true },
make_pair("encryptwallet", &encryptwallet), { "walletpassphrasechange", &walletpassphrasechange, false },
make_pair("validateaddress", &validateaddress), { "walletlock", &walletlock, true },
make_pair("getbalance", &getbalance), { "encryptwallet", &encryptwallet, false },
make_pair("move", &movecmd), { "validateaddress", &validateaddress, true },
make_pair("sendfrom", &sendfrom), { "getbalance", &getbalance, false },
make_pair("sendmany", &sendmany), { "move", &movecmd, false },
make_pair("addmultisigaddress", &addmultisigaddress), { "sendfrom", &sendfrom, false },
make_pair("getblock", &getblock), { "sendmany", &sendmany, false },
make_pair("getblockhash", &getblockhash), { "addmultisigaddress", &addmultisigaddress, false },
make_pair("gettransaction", &gettransaction), { "getblock", &getblock, false },
make_pair("listtransactions", &listtransactions), { "getblockhash", &getblockhash, false },
make_pair("signmessage", &signmessage), { "gettransaction", &gettransaction, false },
make_pair("verifymessage", &verifymessage), { "listtransactions", &listtransactions, false },
make_pair("getwork", &getwork), { "signmessage", &signmessage, false },
make_pair("listaccounts", &listaccounts), { "verifymessage", &verifymessage, false },
make_pair("settxfee", &settxfee), { "getwork", &getwork, true },
make_pair("getmemorypool", &getmemorypool), { "listaccounts", &listaccounts, false },
make_pair("listsinceblock", &listsinceblock), { "settxfee", &settxfee, false },
make_pair("dumpprivkey", &dumpprivkey), { "getmemorypool", &getmemorypool, true },
make_pair("importprivkey", &importprivkey) { "listsinceblock", &listsinceblock, false },
}; { "dumpprivkey", &dumpprivkey, false },
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); { "importprivkey", &importprivkey, false },
string pAllowInSafeMode[] =
{
"help",
"stop",
"getblockcount",
"getblocknumber", // deprecated
"getconnectioncount",
"getdifficulty",
"getgenerate",
"setgenerate",
"gethashespersec",
"getinfo",
"getmininginfo",
"getnewaddress",
"getaccountaddress",
"getaccount",
"getaddressesbyaccount",
"backupwallet",
"keypoolrefill",
"walletpassphrase",
"walletlock",
"validateaddress",
"getwork",
"getmemorypool",
}; };
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
CRPCTable::CRPCTable()
{
unsigned int vcidx;
for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
{
const CRPCCommand *pcmd;
pcmd = &vRPCCommands[vcidx];
mapCommands[pcmd->name] = pcmd;
}
}
const CRPCCommand *CRPCTable::operator[](string name) const
{
map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
if (it == mapCommands.end())
return NULL;
return (*it).second;
}
// //
// HTTP protocol // HTTP protocol
@ -2513,13 +2505,14 @@ void ThreadRPCServer2(void* parg)
throw JSONRPCError(-32600, "Params must be an array"); throw JSONRPCError(-32600, "Params must be an array");
// Find method // Find method
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod); const CRPCCommand *pcmd = tableRPC[strMethod];
if (mi == mapCallTable.end()) if (!pcmd)
throw JSONRPCError(-32601, "Method not found"); throw JSONRPCError(-32601, "Method not found");
// Observe safe mode // Observe safe mode
string strWarning = GetWarnings("rpc"); string strWarning = GetWarnings("rpc");
if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod)) if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
!pcmd->okSafeMode)
throw JSONRPCError(-2, string("Safe mode: ") + strWarning); throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
try try
@ -2528,7 +2521,7 @@ void ThreadRPCServer2(void* parg)
Value result; Value result;
{ {
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
result = (*(*mi).second)(params, false); result = pcmd->actor(params, false);
} }
// Send reply // Send reply
@ -2769,3 +2762,5 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
#endif #endif
const CRPCTable tableRPC;

34
src/bitcoinrpc.h

@ -3,5 +3,39 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef _BITCOINRPC_H_
#define _BITCOINRPC_H_ 1
#include <string>
#include <map>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
void ThreadRPCServer(void* parg); void ThreadRPCServer(void* parg);
int CommandLineRPC(int argc, char *argv[]); int CommandLineRPC(int argc, char *argv[]);
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
class CRPCCommand
{
public:
std::string name;
rpcfn_type actor;
bool okSafeMode;
};
class CRPCTable
{
private:
std::map<std::string, const CRPCCommand*> mapCommands;
public:
CRPCTable();
const CRPCCommand* operator[](std::string name) const;
std::string help(std::string name) const;
};
extern const CRPCTable tableRPC;
#endif

9
src/test/rpc_tests.cpp

@ -3,16 +3,11 @@
#include "base58.h" #include "base58.h"
#include "util.h" #include "util.h"
#include "json/json_spirit_reader_template.h" #include "bitcoinrpc.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
extern map<string, rpcfn_type> mapCallTable;
BOOST_AUTO_TEST_SUITE(rpc_tests) BOOST_AUTO_TEST_SUITE(rpc_tests)
static Array static Array
@ -36,7 +31,7 @@ struct TestNetFixture
BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture) BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture)
{ {
rpcfn_type addmultisig = mapCallTable["addmultisigaddress"]; rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
// old, 65-byte-long: // old, 65-byte-long:
const char* address1Hex = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8"; const char* address1Hex = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";

Loading…
Cancel
Save