aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/daemon/DaemonManager.cpp142
-rw-r--r--src/daemon/DaemonManager.h43
-rw-r--r--src/libwalletqt/Wallet.cpp21
-rw-r--r--src/libwalletqt/Wallet.h6
4 files changed, 211 insertions, 1 deletions
diff --git a/src/daemon/DaemonManager.cpp b/src/daemon/DaemonManager.cpp
new file mode 100644
index 00000000..185cde1e
--- /dev/null
+++ b/src/daemon/DaemonManager.cpp
@@ -0,0 +1,142 @@
+#include "DaemonManager.h"
+#include <QFile>
+#include <QFileInfo>
+#include <QDir>
+#include <QDebug>
+#include <QUrl>
+#include <QtConcurrent/QtConcurrent>
+#include <QApplication>
+#include <QProcess>
+
+DaemonManager * DaemonManager::m_instance = nullptr;
+QStringList DaemonManager::m_clArgs;
+
+DaemonManager *DaemonManager::instance(const QStringList *args)
+{
+ if (!m_instance) {
+ m_instance = new DaemonManager;
+ // store command line arguments for later use
+ m_clArgs = *args;
+ m_clArgs.removeFirst();
+ }
+
+ return m_instance;
+}
+
+bool DaemonManager::start()
+{
+ //
+ QString process;
+#ifdef Q_OS_WIN
+ process = QApplication::applicationDirPath() + "/monerod.exe";
+#elif defined(Q_OS_UNIX)
+ process = QApplication::applicationDirPath() + "/monerod";
+#endif
+
+ if (process.length() == 0) {
+ qDebug() << "no daemon binary defined for current platform";
+ return false;
+ }
+
+
+ // prepare command line arguments and pass to monerod
+ QStringList arguments;
+ foreach (const QString &str, m_clArgs) {
+ qDebug() << QString(" [%1] ").arg(str);
+ arguments << str;
+ }
+
+ qDebug() << "starting monerod " + process;
+ qDebug() << "With command line arguments " << arguments;
+
+ m_daemon = new QProcess();
+ initialized = true;
+
+ // Connect output slots
+ connect (m_daemon, SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput()));
+ connect (m_daemon, SIGNAL(readyReadStandardError()), this, SLOT(printError()));
+
+ // Start monerod
+ m_daemon->start(process,arguments);
+ bool started = m_daemon->waitForStarted();
+
+ // add state changed listener
+ connect(m_daemon,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(stateChanged(QProcess::ProcessState)));
+
+ if (!started) {
+ qDebug() << "Daemon start error: " + m_daemon->errorString();
+ } else {
+ emit daemonStarted();
+ }
+
+ return started;
+}
+
+bool DaemonManager::stop()
+{
+ if (initialized) {
+ qDebug() << "stopping daemon";
+ // we can't use QProcess::terminate() on windows console process
+ // write exit command to stdin
+ m_daemon->write("exit\n");
+ }
+
+ return true;
+}
+
+void DaemonManager::stateChanged(QProcess::ProcessState state)
+{
+ qDebug() << "STATE CHANGED: " << state;
+ if (state == QProcess::NotRunning) {
+ emit daemonStopped();
+ }
+}
+
+void DaemonManager::printOutput()
+{
+ QByteArray byteArray = m_daemon->readAllStandardOutput();
+ QStringList strLines = QString(byteArray).split("\n");
+
+ foreach (QString line, strLines) {
+ emit daemonConsoleUpdated(line);
+ qDebug() << "Daemon: " + line;
+ }
+}
+
+void DaemonManager::printError()
+{
+ QByteArray byteArray = m_daemon->readAllStandardError();
+ QStringList strLines = QString(byteArray).split("\n");
+
+ foreach (QString line, strLines) {
+ emit daemonConsoleUpdated(line);
+ qDebug() << "Daemon ERROR: " + line;
+ }
+}
+
+bool DaemonManager::running() const
+{
+ if (initialized) {
+ qDebug() << m_daemon->state();
+ qDebug() << QProcess::NotRunning;
+ // m_daemon->write("status\n");
+ return m_daemon->state() > QProcess::NotRunning;
+ }
+ return false;
+}
+
+DaemonManager::DaemonManager(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+void DaemonManager::closing()
+{
+ qDebug() << __FUNCTION__;
+ stop();
+ // Wait for daemon to stop before exiting (max 10 secs)
+ if (initialized) {
+ m_daemon->waitForFinished(10000);
+ }
+}
diff --git a/src/daemon/DaemonManager.h b/src/daemon/DaemonManager.h
new file mode 100644
index 00000000..8f425fd5
--- /dev/null
+++ b/src/daemon/DaemonManager.h
@@ -0,0 +1,43 @@
+#ifndef DAEMONMANAGER_H
+#define DAEMONMANAGER_H
+
+#include <QObject>
+#include <QUrl>
+#include <QProcess>
+
+class DaemonManager : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ static DaemonManager * instance(const QStringList *args);
+
+ Q_INVOKABLE bool start();
+ Q_INVOKABLE bool stop();
+
+ // return true if daemon process is started
+ Q_INVOKABLE bool running() const;
+
+signals:
+ void daemonStarted();
+ void daemonStopped();
+ void daemonConsoleUpdated(QString message);
+
+public slots:
+ void printOutput();
+ void printError();
+ void closing();
+ void stateChanged(QProcess::ProcessState state);
+
+private:
+
+ explicit DaemonManager(QObject *parent = 0);
+ static DaemonManager * m_instance;
+ static QStringList m_clArgs;
+ QProcess *m_daemon;
+ bool initialized = false;
+
+};
+
+#endif // DAEMONMANAGER_H
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index 9d814d82..915b4d4f 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -15,6 +15,7 @@
namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 60;
+ static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
}
class WalletListenerImpl : public Bitmonero::WalletListener
@@ -89,7 +90,18 @@ Wallet::Status Wallet::status() const
Wallet::ConnectionStatus Wallet::connected() const
{
- return static_cast<ConnectionStatus>(m_walletImpl->connected());
+ // cache connection status
+ if (!m_initialized || m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl) {
+ m_initialized = true;
+ ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
+ if (newStatus != m_connectionStatus) {
+ m_connectionStatus = newStatus;
+ emit connectionStatusChanged();
+ }
+ m_connectionStatusTime.restart();
+ }
+
+ return m_connectionStatus;
}
bool Wallet::synchronized() const
@@ -424,9 +436,16 @@ Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0)
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
+ , m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
{
m_history = new TransactionHistory(m_walletImpl->history(), this);
m_walletImpl->setListener(new WalletListenerImpl(this));
+ m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
+ // start cache timers
+ m_connectionStatusTime.restart();
+ m_daemonBlockChainHeightTime.restart();
+ m_daemonBlockChainTargetHeightTime.restart();
+ m_initialized = false;
}
Wallet::~Wallet()
diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h
index 492080d4..ad4c393e 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -200,6 +200,8 @@ signals:
// emitted when transaction is created async
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
+ void connectionStatusChanged() const;
+
private:
Wallet(QObject * parent = nullptr);
Wallet(Bitmonero::Wallet *w, QObject * parent = 0);
@@ -221,6 +223,10 @@ private:
mutable QTime m_daemonBlockChainTargetHeightTime;
mutable quint64 m_daemonBlockChainTargetHeight;
int m_daemonBlockChainTargetHeightTtl;
+ mutable ConnectionStatus m_connectionStatus;
+ int m_connectionStatusTtl;
+ mutable QTime m_connectionStatusTime;
+ mutable bool m_initialized;
};