mirror of
https://git.wownero.com/wowlet/wowlet.git
synced 2024-08-15 01:03:14 +00:00
137 lines
3.9 KiB
C++
137 lines
3.9 KiB
C++
// SPDX-License-Identifier: BSD-3-Clause
|
|
// Copyright (c) 2020-2021, The Monero Project.
|
|
|
|
#ifndef WOWLET_NODES_H
|
|
#define WOWLET_NODES_H
|
|
|
|
#include <QTimer>
|
|
#include <QRegExp>
|
|
#include <QApplication>
|
|
#include <QtNetwork>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkReply>
|
|
|
|
#include "model/NodeModel.h"
|
|
#include "utils/utils.h"
|
|
#include "utils/config.h"
|
|
|
|
enum NodeSource {
|
|
websocket = 0,
|
|
custom
|
|
};
|
|
|
|
struct WowletNode {
|
|
explicit WowletNode(QString _address = "", int height = 0, int target_height = 0, bool online = false)
|
|
: height(height), target_height(target_height), online(online){
|
|
// wonky ipv4/host parsing, should be fine(tm)(c).
|
|
if(_address.isEmpty()) return;
|
|
if(_address.contains("https://")) {
|
|
this->isHttps = true;
|
|
}
|
|
_address = _address.replace("https://", "");
|
|
_address = _address.replace("http://", "");
|
|
if(_address.contains("@")){ // authentication, user/pass
|
|
const auto spl = _address.split("@");
|
|
const auto &creds = spl.at(0);
|
|
if(creds.contains(":")) {
|
|
const auto _spl = creds.split(":");
|
|
this->username = _spl.at(0).trimmed().replace(" ", "");
|
|
this->password = _spl.at(1).trimmed().replace(" ", "");
|
|
}
|
|
_address = spl.at(1);
|
|
}
|
|
if(!_address.contains(":"))
|
|
_address += ":18081";
|
|
this->address = _address;
|
|
if(this->address.contains(".onion"))
|
|
tor = true;
|
|
this->full = this->generateFull();
|
|
};
|
|
|
|
QString address;
|
|
QString full;
|
|
int height;
|
|
int target_height;
|
|
bool online = false;
|
|
QString username;
|
|
QString password;
|
|
bool cached = false;
|
|
bool custom = false;
|
|
bool tor = false;
|
|
bool isConnecting = false;
|
|
bool isActive = false;
|
|
bool isHttps = false;
|
|
|
|
QString generateFull() {
|
|
QString auth;
|
|
if(!this->username.isEmpty() && !this->password.isEmpty())
|
|
auth = QString("%1:%2@").arg(this->username).arg(this->password);
|
|
return QString("%1%2").arg(auth).arg(this->address);
|
|
}
|
|
|
|
QString as_url() {
|
|
return QString("%1://%2/get_info").arg(this->isHttps ? "https": "http",this->full);
|
|
}
|
|
|
|
bool operator == (const WowletNode &other) const {
|
|
return this->full == other.full;
|
|
}
|
|
};
|
|
|
|
class Nodes : public QObject {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit Nodes(AppContext *ctx, QNetworkAccessManager *networkAccessManager, QObject *parent = nullptr);
|
|
void loadConfig();
|
|
void writeConfig();
|
|
|
|
NodeSource source();
|
|
WowletNode connection();
|
|
QList<WowletNode> customNodes();
|
|
|
|
NodeModel *modelWebsocket;
|
|
NodeModel *modelCustom;
|
|
|
|
public slots:
|
|
void connectToNode();
|
|
void connectToNode(const WowletNode &node);
|
|
void onWSNodesReceived(const QList<QSharedPointer<WowletNode>>& nodes);
|
|
void onNodeSourceChanged(NodeSource nodeSource);
|
|
void setCustomNodes(const QList<WowletNode>& nodes);
|
|
void autoConnect(bool forceReconnect = false);
|
|
|
|
signals:
|
|
void WSNodeExhausted();
|
|
void nodeExhausted();
|
|
void updateStatus(const QString &msg);
|
|
|
|
private:
|
|
AppContext *m_ctx = nullptr;
|
|
NodeSource m_source = NodeSource::websocket;
|
|
QNetworkAccessManager *m_networkAccessManager = nullptr;
|
|
QJsonObject m_configJson;
|
|
|
|
QStringList m_recentFailures;
|
|
|
|
QList<WowletNode> m_customNodes;
|
|
QList<WowletNode> m_websocketNodes;
|
|
|
|
WowletNode m_connection; // current active connection, if any
|
|
|
|
bool m_wsNodesReceived = false;
|
|
bool m_wsExhaustedWarningEmitted = true;
|
|
bool m_customExhaustedWarningEmitted = true;
|
|
bool m_enableAutoconnect = true;
|
|
|
|
WowletNode pickEligibleNode();
|
|
|
|
void updateModels();
|
|
void resetLocalState();
|
|
void exhausted();
|
|
void WSNodeExhaustedWarning();
|
|
void nodeExhaustedWarning();
|
|
int modeHeight(const QList<WowletNode> &nodes);
|
|
};
|
|
|
|
#endif //WOWLET_NODES_H
|