diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -72,6 +72,7 @@ // not possible as the whole application has too many global state. However, // this is a first step. auto &config = const_cast(GetConfig()); + HTTPRPCRequestProcessor httpRPCRequestProcessor(config); bool fRet = false; @@ -178,7 +179,8 @@ #endif // HAVE_DECL_DAEMON } - fRet = AppInitMain(config, threadGroup, scheduler); + fRet = AppInitMain(config, httpRPCRequestProcessor, threadGroup, + scheduler); } catch (const std::exception &e) { PrintExceptionContinue(&e, "AppInit()"); } catch (...) { diff --git a/src/httprpc.h b/src/httprpc.h --- a/src/httprpc.h +++ b/src/httprpc.h @@ -5,17 +5,36 @@ #ifndef BITCOIN_HTTPRPC_H #define BITCOIN_HTTPRPC_H +#include "httpserver.h" +#include "rpc/server.h" + #include #include class Config; class HTTPRequest; +class HTTPRPCRequestProcessor { +private: + Config &config; + + bool ProcessHTTPRequest(HTTPRequest *request); + +public: + HTTPRPCRequestProcessor(Config &configIn) : config(configIn) {} + + static bool DelegateHTTPRequest(HTTPRPCRequestProcessor *requestProcessor, + HTTPRequest *request) { + return requestProcessor->ProcessHTTPRequest(request); + } +}; + /** * Start HTTP RPC subsystem. * Precondition; HTTP and RPC has been started. */ -bool StartHTTPRPC(Config &config); +bool StartHTTPRPC(Config &config, + HTTPRPCRequestProcessor &httpRPCRequestProcessor); /** Interrupt HTTP RPC subsystem */ void InterruptHTTPRPC(); diff --git a/src/httprpc.cpp b/src/httprpc.cpp --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -266,8 +266,7 @@ return false; } -static bool HTTPReq_JSONRPC(Config &config, HTTPRequest *req, - const std::string &) { +bool HTTPRPCRequestProcessor::ProcessHTTPRequest(HTTPRequest *req) { // First, check and/or set CORS headers if (checkCORS(config, req)) { return true; @@ -365,15 +364,20 @@ return true; } -bool StartHTTPRPC(Config &config) { +bool StartHTTPRPC(Config &config, + HTTPRPCRequestProcessor &httpRPCRequestProcessor) { LogPrint(BCLog::RPC, "Starting HTTP RPC server\n"); if (!InitRPCAuthentication(config)) return false; - RegisterHTTPHandler("/", true, HTTPReq_JSONRPC); + const std::function + &rpcFunction = + std::bind(&HTTPRPCRequestProcessor::DelegateHTTPRequest, + &httpRPCRequestProcessor, std::placeholders::_2); + RegisterHTTPHandler("/", true, rpcFunction); #ifdef ENABLE_WALLET // ifdef can be removed once we switch to better endpoint support and API // versioning - RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC); + RegisterHTTPHandler("/wallet/", false, rpcFunction); #endif assert(EventBase()); httpRPCTimerInterface = new HTTPRPCTimerInterface(EventBase()); diff --git a/src/init.h b/src/init.h --- a/src/init.h +++ b/src/init.h @@ -11,6 +11,7 @@ class Config; class CScheduler; class CWallet; +class HTTPRPCRequestProcessor; namespace boost { class thread_group; @@ -51,8 +52,9 @@ * @pre Parameters should be parsed and config file should be read, * AppInitSanityChecks should have been called. */ -bool AppInitMain(Config &config, boost::thread_group &threadGroup, - CScheduler &scheduler); +bool AppInitMain(Config &config, + HTTPRPCRequestProcessor &httpRPCRequestProcessor, + boost::thread_group &threadGroup, CScheduler &scheduler); /** The help message mode determines what help message to show */ enum HelpMessageMode { HMM_BITCOIND, HMM_BITCOIN_QT }; diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -1114,7 +1114,9 @@ return true; } -static bool AppInitServers(Config &config, boost::thread_group &threadGroup) { +static bool AppInitServers(Config &config, + HTTPRPCRequestProcessor &httpRPCRequestProcessor, + boost::thread_group &threadGroup) { RPCServerSignals::OnStarted(&OnRPCStarted); RPCServerSignals::OnStopped(&OnRPCStopped); RPCServerSignals::OnPreCommand(&OnRPCPreCommand); @@ -1124,7 +1126,7 @@ if (!StartRPC()) { return false; } - if (!StartHTTPRPC(config)) { + if (!StartHTTPRPC(config, httpRPCRequestProcessor)) { return false; } if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST()) { @@ -1727,8 +1729,9 @@ return LockDataDirectory(true); } -bool AppInitMain(Config &config, boost::thread_group &threadGroup, - CScheduler &scheduler) { +bool AppInitMain(Config &config, + HTTPRPCRequestProcessor &httpRPCRequestProcessor, + boost::thread_group &threadGroup, CScheduler &scheduler) { const CChainParams &chainparams = config.GetChainParams(); // Step 4a: application initialization @@ -1796,7 +1799,7 @@ */ if (gArgs.GetBoolArg("-server", false)) { uiInterface.InitMessage.connect(SetRPCWarmupStatus); - if (!AppInitServers(config, threadGroup)) { + if (!AppInitServers(config, httpRPCRequestProcessor, threadGroup)) { return InitError( _("Unable to start HTTP server. See debug log for details.")); } diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -13,6 +13,7 @@ #include "config.h" #include "guiconstants.h" #include "guiutil.h" +#include "httprpc.h" #include "intro.h" #include "networkstyle.h" #include "optionsmodel.h" @@ -191,7 +192,8 @@ explicit BitcoinABC(); public Q_SLOTS: - void initialize(Config *config); + void initialize(Config *config, + HTTPRPCRequestProcessor *httpRPCRequestProcessor); void shutdown(); Q_SIGNALS: @@ -228,7 +230,8 @@ void createSplashScreen(const NetworkStyle *networkStyle); /// Request core initialization - void requestInitialize(Config &config); + void requestInitialize(Config &config, + HTTPRPCRequestProcessor &httpRPCRequestProcessor); /// Request core shutdown void requestShutdown(Config &config); @@ -246,7 +249,8 @@ void handleRunawayException(const QString &message); Q_SIGNALS: - void requestedInitialize(Config *config); + void requestedInitialize(Config *config, + HTTPRPCRequestProcessor *httpRPCRequestProcessor); void requestedShutdown(); void stopThread(); void splashFinished(QWidget *window); @@ -277,7 +281,8 @@ Q_EMIT runawayException(QString::fromStdString(GetWarnings("gui"))); } -void BitcoinABC::initialize(Config *cfg) { +void BitcoinABC::initialize(Config *cfg, + HTTPRPCRequestProcessor *httpRPCRequestProcessor) { Config &config(*cfg); try { qDebug() << __func__ << ": Running AppInit2 in thread"; @@ -296,7 +301,8 @@ return; } - int rv = AppInitMain(config, threadGroup, scheduler); + int rv = AppInitMain(config, *httpRPCRequestProcessor, threadGroup, + scheduler); Q_EMIT initializeResult(rv); } catch (const std::exception &e) { handleRunawayException(&e); @@ -419,8 +425,9 @@ // temporary (eg it lives somewhere aside from the stack) or this will // crash because initialize() gets executed in another thread at some // unspecified time (after) requestedInitialize() is emitted! - connect(this, SIGNAL(requestedInitialize(Config *)), executor, - SLOT(initialize(Config *))); + connect(this, + SIGNAL(requestedInitialize(Config *, HTTPRPCRequestProcessor *)), + executor, SLOT(initialize(Config *, HTTPRPCRequestProcessor *))); connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown())); /* make sure executor object is deleted in its own thread */ @@ -435,13 +442,14 @@ InitParameterInteraction(); } -void BitcoinApplication::requestInitialize(Config &config) { +void BitcoinApplication::requestInitialize( + Config &config, HTTPRPCRequestProcessor &httpRPCRequestProcessor) { qDebug() << __func__ << ": Requesting initialize"; startThread(); // IMPORTANT: config must NOT be a reference to a temporary because below // signal may be connected to a slot that will be executed as a queued // connection in another thread! - Q_EMIT requestedInitialize(&config); + Q_EMIT requestedInitialize(&config, &httpRPCRequestProcessor); } void BitcoinApplication::requestShutdown(Config &config) { @@ -782,9 +790,11 @@ !gArgs.GetBoolArg("-min", false)) app.createSplashScreen(networkStyle.data()); + HTTPRPCRequestProcessor httpRPCRequestProcessor(config); + try { app.createWindow(&config, networkStyle.data()); - app.requestInitialize(config); + app.requestInitialize(config, httpRPCRequestProcessor); #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 WinShutdownMonitor::registerShutdownBlockReason( QObject::tr("%1 didn't yet exit safely...")