#include "Controller.h" Controller::Controller(const std::shared_ptr &o) : Mgr(nullptr), options(o) { setObjectName("Controller"); _thread.setObjectName(objectName()); } Controller::~Controller() { Debug(__FUNCTION__); cleanup(); } auto Controller::stats() const -> Stats { auto st = srvmgr->statsSafe(); Util::updateMap(st, bitcoindmgr->statsSafe()); return st; } void Controller::startup() { bitcoindmgr = std::make_unique(options->bitcoind.first, options->bitcoind.second, options->rpcuser, options->rpcpassword); { // some setup code that waits for bitcoind to be ready before kicking off our "process" method auto waitForBitcoinD = [this] { auto constexpr waitTimer = "wait4bitcoind", callProcessTimer = "callProcess"; int constexpr msgPeriod = 10000, // 10sec smallDelay = 100; stopTimer(callProcessTimer); callOnTimerSoon(msgPeriod, waitTimer, []{ Log("Waiting for bitcoind..."); return true; }, false, Qt::TimerType::VeryCoarseTimer); // connection to kick off our 'process' method once the first auth is received auto connPtr = std::make_shared(); *connPtr = connect(bitcoindmgr.get(), &BitcoinDMgr::gotFirstGoodConnection, this, [this, connPtr](quint64 id) mutable { if (connPtr) { stopTimer(waitTimer); if (!disconnect(*connPtr)) Fatal() << "Failed to disconnect 'authenticated' signal! FIXME!"; // this should never happen but if it does, app quits. connPtr.reset(); // clear connPtr right away to 1. delte it asap and 2. so we are guaranteed not to reenter this block for this connection should there be a spurious signal emitted. Debug() << "Auth recvd from bicoind with id: " << id << ", proceeding with processing ..."; callOnTimerSoonNoRepeat(smallDelay, callProcessTimer, [this]{process();}, true); } }); }; waitForBitcoinD(); conns += connect(bitcoindmgr.get(), &BitcoinDMgr::allConnectionsLost, this, waitForBitcoinD); } bitcoindmgr->startup(); // may throw srvmgr = std::make_unique(options->interfaces, nullptr /* we are not parent so it won't follow us to our thread*/); srvmgr->startup(); // may throw Exception, waits for servers to bind start(); // start our thread } void Controller::cleanup() { stop(); if (srvmgr) { Log("Stopping SrvMgr ... "); srvmgr->cleanup(); srvmgr.reset(); } if (bitcoindmgr) { Log("Stopping BitcoinDMgr ... "); bitcoindmgr->cleanup(); bitcoindmgr.reset(); } sm.reset(); } struct Controller::StateMachine { // TODO: put state stuff here }; void Controller::process() { Debug() << "Process called..."; if (!sm) sm = std::make_unique(); // create statemachine if doest not exist bitcoindmgr->submitRequest(this, IdMixin::newId(), "getmempoolinfo", {}, [](auto resp){ // testing Trace() << resp.id.toString() << ": result reply: " << resp.toJsonString(); }, [](auto resp){ Trace() << resp.id.toString() << ": error response: " << resp.toJsonString(); }, [](auto id, auto msg) { Warning() << id.toString() << ": FAIL: " << msg; }); }