diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -73,6 +73,8 @@ // this is a first step. auto &config = const_cast(GetConfig()); + HTTPCallbackArgs httpCallbackArgs(&config); + bool fRet = false; // @@ -178,7 +180,7 @@ #endif // HAVE_DECL_DAEMON } - fRet = AppInitMain(config, threadGroup, scheduler); + fRet = AppInitMain(config, httpCallbackArgs, threadGroup, scheduler); } catch (const std::exception &e) { PrintExceptionContinue(&e, "AppInit()"); } catch (...) { diff --git a/src/httpserver.h b/src/httpserver.h --- a/src/httpserver.h +++ b/src/httpserver.h @@ -20,10 +20,17 @@ class CService; class HTTPRequest; -/** Initialize HTTP server. +struct HTTPCallbackArgs { + Config *config; + + HTTPCallbackArgs(Config *configIn) : config(configIn) {} +}; + +/** + * Initialize HTTP server. * Call this before RegisterHTTPHandler or EventBase(). */ -bool InitHTTPServer(Config &config); +bool InitHTTPServer(Config &config, HTTPCallbackArgs &httpCallbackArgs); /** Start HTTP server. * This is separate from InitHTTPServer to give users race-condition-free time * to register their handlers between InitHTTPServer and StartHTTPServer. diff --git a/src/httpserver.cpp b/src/httpserver.cpp --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -232,8 +232,10 @@ } /** HTTP request callback */ -static void http_request_cb(struct evhttp_request *req, void *arg) { - Config &config = *reinterpret_cast(arg); +static void http_request_cb(struct evhttp_request *req, void *args) { + HTTPCallbackArgs &callbackArgs = + *reinterpret_cast(args); + Config &config = *callbackArgs.config; std::unique_ptr hreq(new HTTPRequest(req)); @@ -373,7 +375,7 @@ } } -bool InitHTTPServer(Config &config) { +bool InitHTTPServer(Config &config, HTTPCallbackArgs &httpCallbackArgs) { struct evhttp *http = 0; struct event_base *base = 0; @@ -424,7 +426,7 @@ evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE); evhttp_set_max_body_size( http, MIN_SUPPORTED_BODY_SIZE + 2 * config.GetMaxBlockSize()); - evhttp_set_gencb(http, http_request_cb, &config); + evhttp_set_gencb(http, http_request_cb, &httpCallbackArgs); // Only POST and OPTIONS are supported, but we return HTTP 405 for the // others 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 HTTPCallbackArgs; namespace boost { class thread_group; @@ -46,13 +47,13 @@ */ bool AppInitSanityChecks(); /** - * Bitcoin core main initialization. + * Bitcoin main initialization. * @note This should only be done after daemonization. * @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, HTTPCallbackArgs &httpCallbackArgs, + 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 @@ -1127,11 +1127,12 @@ return true; } -static bool AppInitServers(Config &config, boost::thread_group &threadGroup) { +static bool AppInitServers(Config &config, HTTPCallbackArgs &httpCallbackArgs, + boost::thread_group &threadGroup) { RPCServerSignals::OnStarted(&OnRPCStarted); RPCServerSignals::OnStopped(&OnRPCStopped); RPCServerSignals::OnPreCommand(&OnRPCPreCommand); - if (!InitHTTPServer(config)) { + if (!InitHTTPServer(config, httpCallbackArgs)) { return false; } if (!StartRPC()) { @@ -1739,8 +1740,8 @@ return LockDataDirectory(true); } -bool AppInitMain(Config &config, boost::thread_group &threadGroup, - CScheduler &scheduler) { +bool AppInitMain(Config &config, HTTPCallbackArgs &httpCallbackArgs, + boost::thread_group &threadGroup, CScheduler &scheduler) { const CChainParams &chainparams = config.GetChainParams(); // Step 4a: application initialization @@ -1808,7 +1809,7 @@ */ if (gArgs.GetBoolArg("-server", false)) { uiInterface.InitMessage.connect(SetRPCWarmupStatus); - if (!AppInitServers(config, threadGroup)) { + if (!AppInitServers(config, httpCallbackArgs, 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 @@ -26,6 +26,7 @@ #include "walletmodel.h" #endif +#include "httpserver.h" #include "init.h" #include "rpc/server.h" #include "scheduler.h" @@ -191,7 +192,7 @@ explicit BitcoinABC(); public Q_SLOTS: - void initialize(Config *config); + void initialize(Config *config, HTTPCallbackArgs *httpCallbackArgs); void shutdown(); Q_SIGNALS: @@ -228,7 +229,7 @@ void createSplashScreen(const NetworkStyle *networkStyle); /// Request core initialization - void requestInitialize(Config &config); + void requestInitialize(Config &config, HTTPCallbackArgs &httpCallbackArgs); /// Request core shutdown void requestShutdown(Config &config); @@ -246,7 +247,8 @@ void handleRunawayException(const QString &message); Q_SIGNALS: - void requestedInitialize(Config *config); + void requestedInitialize(Config *config, + HTTPCallbackArgs *httpCallbackArgs); void requestedShutdown(); void stopThread(); void splashFinished(QWidget *window); @@ -277,7 +279,7 @@ Q_EMIT runawayException(QString::fromStdString(GetWarnings("gui"))); } -void BitcoinABC::initialize(Config *cfg) { +void BitcoinABC::initialize(Config *cfg, HTTPCallbackArgs *httpCallbackArgs) { Config &config(*cfg); try { qDebug() << __func__ << ": Running AppInit2 in thread"; @@ -296,7 +298,7 @@ return; } - int rv = AppInitMain(config, threadGroup, scheduler); + int rv = AppInitMain(config, *httpCallbackArgs, threadGroup, scheduler); Q_EMIT initializeResult(rv); } catch (const std::exception &e) { handleRunawayException(&e); @@ -419,8 +421,8 @@ // 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 *, HTTPCallbackArgs *)), + executor, SLOT(initialize(Config *, HTTPCallbackArgs *))); connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown())); /* make sure executor object is deleted in its own thread */ @@ -435,13 +437,14 @@ InitParameterInteraction(); } -void BitcoinApplication::requestInitialize(Config &config) { +void BitcoinApplication::requestInitialize(Config &config, + HTTPCallbackArgs &httpCallbackArgs) { 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, &httpCallbackArgs); } void BitcoinApplication::requestShutdown(Config &config) { @@ -778,13 +781,15 @@ // Get global config Config &config = const_cast(GetConfig()); + HTTPCallbackArgs httpCallbackArgs(&config); + if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false)) app.createSplashScreen(networkStyle.data()); try { app.createWindow(&config, networkStyle.data()); - app.requestInitialize(config); + app.requestInitialize(config, httpCallbackArgs); #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 WinShutdownMonitor::registerShutdownBlockReason( QObject::tr("%1 didn't yet exit safely...")