danicoinwallet/src/NodeAdapter.cpp
2015-04-30 15:11:48 +03:00

215 lines
6.5 KiB
C++

// Copyright (c) 2011-2015 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <QCoreApplication>
#include <QDateTime>
#include <QDir>
#include <QTimer>
#include <QUrl>
#include <wallet/WalletErrors.h>
#include "CurrencyAdapter.h"
#include "NodeAdapter.h"
#include "Settings.h"
namespace WalletGui {
class InProcessNodeInitializer : public QObject {
Q_OBJECT
Q_DISABLE_COPY(InProcessNodeInitializer)
Q_SIGNALS:
void nodeInitCompletedSignal();
void nodeInitFailedSignal(int _errorCode);
void nodeDeinitCompletedSignal();
public:
InProcessNodeInitializer(QObject* _parent = nullptr) {
}
~InProcessNodeInitializer() {
}
void start(Node** _node, const cryptonote::Currency* currency, INodeCallback* _callback, const cryptonote::CoreConfig& _coreConfig) {
(*_node) = createInprocessNode(*currency, *_callback, _coreConfig);
try {
(*_node)->init([this](std::error_code _err) {
if (_err) {
Q_EMIT nodeInitFailedSignal(_err.value());
QCoreApplication::processEvents();
return;
}
Q_EMIT nodeInitCompletedSignal();
QCoreApplication::processEvents();
});
} catch (std::runtime_error& err) {
Q_EMIT nodeInitFailedSignal(cryptonote::error::INTERNAL_WALLET_ERROR);
QCoreApplication::processEvents();
return;
}
delete *_node;
*_node = nullptr;
Q_EMIT nodeDeinitCompletedSignal();
}
void stop(Node** _node) {
Q_CHECK_PTR(*_node);
(*_node)->deinit();
}
};
NodeAdapter& NodeAdapter::instance() {
static NodeAdapter inst;
return inst;
}
NodeAdapter::NodeAdapter() : QObject(), m_node(nullptr), m_nodeInitializerThread(), m_nodeInitializer(new InProcessNodeInitializer) {
m_nodeInitializer->moveToThread(&m_nodeInitializerThread);
qRegisterMetaType<cryptonote::CoreConfig>("cryptonote::CoreConfig");
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitCompletedSignal, this, &NodeAdapter::nodeInitCompletedSignal, Qt::QueuedConnection);
connect(this, &NodeAdapter::initNodeSignal, m_nodeInitializer, &InProcessNodeInitializer::start, Qt::QueuedConnection);
connect(this, &NodeAdapter::deinitNodeSignal, m_nodeInitializer, &InProcessNodeInitializer::stop, Qt::QueuedConnection);
QString logFileName = QCoreApplication::applicationName() + ".log";
epee::log_space::log_singletone::add_logger(LOGGER_FILE, logFileName.toLocal8Bit(),
Settings::instance().getDataDir().absolutePath().toLocal8Bit());
}
NodeAdapter::~NodeAdapter() {
}
quintptr NodeAdapter::getPeerCount() const {
Q_ASSERT(m_node != nullptr);
return m_node->getPeerCount();
}
std::string NodeAdapter::convertPaymentId(const QString& _paymentIdString) const {
Q_CHECK_PTR(m_node);
try {
return m_node->convertPaymentId(_paymentIdString.toStdString());
} catch (std::runtime_error& err) {
}
return std::string();
}
QString NodeAdapter::extractPaymentId(const std::string& _extra) const {
Q_CHECK_PTR(m_node);
return QString::fromStdString(m_node->extractPaymentId(_extra));
}
CryptoNote::IWallet* NodeAdapter::createWallet() const {
Q_CHECK_PTR(m_node);
return m_node->createWallet();
}
bool NodeAdapter::init() {
Q_ASSERT(m_node == nullptr);
QUrl localNodeUrl = QUrl::fromUserInput(QString("127.0.0.1:%1").arg(cryptonote::RPC_DEFAULT_PORT));
m_node = createRpcNode(CurrencyAdapter::instance().getCurrency(), *this, localNodeUrl.host().toStdString(), localNodeUrl.port());
QTimer initTimer;
initTimer.setInterval(3000);
initTimer.setSingleShot(true);
initTimer.start();
m_node->init([this](std::error_code _err) {
Q_UNUSED(_err);
});
QEventLoop waitLoop;
connect(&initTimer, &QTimer::timeout, &waitLoop, &QEventLoop::quit);
connect(this, &NodeAdapter::peerCountUpdatedSignal, &waitLoop, &QEventLoop::quit);
connect(this, &NodeAdapter::localBlockchainUpdatedSignal, &waitLoop, &QEventLoop::quit);
waitLoop.exec();
if (initTimer.isActive()) {
initTimer.stop();
Q_EMIT nodeInitCompletedSignal();
return true;
}
delete m_node;
m_node = nullptr;
return initInProcessNode();
}
quint64 NodeAdapter::getLastKnownBlockHeight() const {
Q_CHECK_PTR(m_node);
return m_node->getLastKnownBlockHeight();
}
quint64 NodeAdapter::getLastLocalBlockHeight() const {
Q_CHECK_PTR(m_node);
return m_node->getLastLocalBlockHeight();
}
QDateTime NodeAdapter::getLastLocalBlockTimestamp() const {
Q_CHECK_PTR(m_node);
return QDateTime::fromTime_t(m_node->getLastLocalBlockTimestamp(), Qt::UTC);
}
void NodeAdapter::peerCountUpdated(Node& _node, size_t _count) {
Q_UNUSED(_node);
Q_EMIT peerCountUpdatedSignal(_count);
}
void NodeAdapter::localBlockchainUpdated(Node& _node, uint64_t _height) {
Q_UNUSED(_node);
Q_EMIT localBlockchainUpdatedSignal(_height);
}
void NodeAdapter::lastKnownBlockHeightUpdated(Node& _node, uint64_t _height) {
Q_UNUSED(_node);
Q_EMIT lastKnownBlockHeightUpdatedSignal(_height);
}
bool NodeAdapter::initInProcessNode() {
Q_ASSERT(m_node == nullptr);
m_nodeInitializerThread.start();
cryptonote::CoreConfig coreConfig = makeCoreConfig();
Q_EMIT initNodeSignal(&m_node, &CurrencyAdapter::instance().getCurrency(), this, coreConfig);
QEventLoop waitLoop;
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitCompletedSignal, &waitLoop, &QEventLoop::quit);
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitFailedSignal, &waitLoop, &QEventLoop::exit);
if (waitLoop.exec() != 0) {
return false;
}
Q_EMIT localBlockchainUpdatedSignal(getLastLocalBlockHeight());
Q_EMIT lastKnownBlockHeightUpdatedSignal(getLastKnownBlockHeight());
return true;
}
void NodeAdapter::deinit() {
if (m_node != nullptr) {
if (m_nodeInitializerThread.isRunning()) {
m_nodeInitializer->stop(&m_node);
QEventLoop waitLoop;
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeDeinitCompletedSignal, &waitLoop, &QEventLoop::quit, Qt::QueuedConnection);
waitLoop.exec();
m_nodeInitializerThread.quit();
m_nodeInitializerThread.wait();
} else {
delete m_node;
m_node = nullptr;
}
}
}
cryptonote::CoreConfig NodeAdapter::makeCoreConfig() const {
cryptonote::CoreConfig config;
boost::program_options::variables_map options;
boost::any dataDir = Settings::instance().getDataDir().absolutePath().toStdString();
options.insert(std::make_pair("data-dir", boost::program_options::variable_value(dataDir, false)));
config.init(options);
return config;
}
}
#include "NodeAdapter.moc"