redo lmq commit to not remove bootstrap code

This commit is contained in:
Jeff Becker 2020-08-24 06:44:48 -04:00
parent 945c559bf6
commit fb11e90fa2
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
10 changed files with 130 additions and 53 deletions

View File

@ -12,6 +12,7 @@ ColumnLayout {
property var isRunning: false
property var lokiVersion: ""
property var lokiAddress: ""
property var lokiExit: ""
property int lokiUptime: 0
property var numPathsBuilt: 0
property var numRoutersKnown: 0
@ -43,6 +44,11 @@ ColumnLayout {
address: lokiAddress
}
// exit panel
ExitPanel {
id: exit
}
// router stats
RouteStatsPanel {
paths: numPathsBuilt

60
res/qml/ExitPanel.qml Normal file
View File

@ -0,0 +1,60 @@
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
import QClipboard 1.0
import "."
Container {
property var address: ""
Layout.preferredHeight: 79
Layout.preferredWidth: Style.appWidth
contentItem: Rectangle {
id: connectedStatusRect
color: Style.panelBackgroundColor
}
Text {
id: exitLabelText
anchors.left: parent.left
anchors.leftMargin: 20
anchors.right: parent.right
anchors.rightMargin: 20
y: 18
text: "Exit Node"
font.family: Style.weakTextFont
color: Style.weakTextColor
font.pointSize: Style.weakTextSize
font.capitalization: Font.AllUppercase
}
TextInput {
id: exitTextInput
anchors.left: parent.left
anchors.leftMargin: 20
anchors.right: parent.right
anchors.rightMargin: 20
y: 40
text: address
font.family: Style.weakTextFont
color: Style.strongTextColor
font.pointSize: Style.weakTextSize
onAccepted: {
let lokiExit = text;
apiClient.llarpExit(lokiExit, function(result, error) {
if(error)
console.log(error);
else
console.log(JSON.stringify(result));
});
}
}
}

View File

@ -188,15 +188,17 @@ ApplicationWindow {
ApiPoller {
id: stateApiPoller
Component.onCompleted: {
stateApiPoller.setApiEndpoint("llarp.admin.dumpstate");
stateApiPoller.setApiEndpoint("llarp.status");
}
}
ApiPoller {
ApiPoller {
id: statusApiPoller
Component.onCompleted: {
statusApiPoller.setApiEndpoint("llarp.admin.status");
statusApiPoller.setApiEndpoint("llarp.version");
}
}
LokinetApiClient {
id: apiClient
}

View File

@ -9,6 +9,7 @@
<file>qml/ConnectionButtonPanel.qml</file>
<file>qml/VersionPanel.qml</file>
<file>qml/AddressPanel.qml</file>
<file>qml/ExitPanel.qml</file>
<file>qml/RouteStatsPanel.qml</file>
<file>qml/UsagePanel.qml</file>
<file>qml/DismissPanel.qml</file>

View File

@ -3,11 +3,13 @@
#include <string>
#include <QObject>
#include <QDebug>
constexpr auto LOKI_DAEMON_URL = "http://localhost:1190/";
// ApiPoller Constructor
ApiPoller::ApiPoller() {
m_lmq.start();
m_timer = new QTimer();
m_timer->setInterval(DEFAULT_POLLING_INTERVAL_MS);
connect(m_timer, &QTimer::timeout, this, &ApiPoller::pollDaemon);
@ -21,16 +23,7 @@ ApiPoller::~ApiPoller() {
// ApiPoller::setApiEndpoint
void ApiPoller::setApiEndpoint(const QString& endpoint) {
// we make the same API call every time, so build our payload once
char buffer[256];
snprintf(buffer, sizeof(buffer), R"JSON({
"jsonrpc": "2.0",
"method": "%s",
"params": {},
"id": "empty"
})JSON",
endpoint.toStdString().data());
m_rpcPayload = buffer;
m_rpcMethod = endpoint.toStdString();
}
// ApiPoller::setIntervalMs
@ -55,26 +48,25 @@ void ApiPoller::pollImmediately() {
// ApiPoller::pollDaemon
void ApiPoller::pollDaemon() {
if (m_rpcPayload.empty()) {
qDebug() << "Warning: No endpoint; call ApiPoller::setApiEndpoint() before polling";
return;
if (m_rpcMethod.empty()) {
qDebug() << "Warning: No endpoint; call ApiPoller::setApiEndpoint() before polling";
return;
}
m_httpClient.postJson(LOKI_DAEMON_URL, m_rpcPayload, [=](QNetworkReply* reply) {
static bool lastAttemptWasError = false;
if (reply->error()) {
if (! lastAttemptWasError) {
qDebug() << "JSON-RPC error: " << reply->error();
qDebug() << " in response to query: " << m_rpcPayload.c_str();
if (reply->error() > 100)
{
qDebug() << " server replied: " << reply->readAll();
}
if(not m_Conn.has_value())
{
m_Conn = m_lmq.connect_remote(LOKI_DAEMON_URL, [](auto &&){},
[=](auto,auto msg) {
qInfo() << std::string{msg}.c_str();
m_Conn = std::nullopt;
});
}
m_lmq.request(*m_Conn, m_rpcMethod,
[=](bool success, std::vector<std::string> data)
{
if(success and not data.empty())
{
emit statusAvailable(QString::fromStdString(data[0]));
}
lastAttemptWasError = true;
emit statusAvailable("", reply->error());
} else {
lastAttemptWasError = false;
emit statusAvailable(reply->readAll(), reply->error());
}
});
});
}

View File

@ -9,7 +9,7 @@
#include <QObject>
#include <QTimer>
#include "HttpClient.hpp"
#include <lokimq/lokimq.h>
/**
* The ApiPoller periodically requests a JSON-RPC endpoint from the Loki daemon.
@ -67,7 +67,7 @@ signals:
* @param error is a QNetworkReply::NetworkError enum representing the
* error, if any
*/
void statusAvailable(const QByteArray& payload, QNetworkReply::NetworkError error);
void statusAvailable(QString data);
private:
@ -77,8 +77,9 @@ private:
void pollDaemon();
QTimer* m_timer;
HttpClient m_httpClient;
std::string m_rpcPayload;
lokimq::LokiMQ m_lmq;
std::optional<lokimq::ConnectionID> m_Conn;
std::string m_rpcMethod;
};
#endif // __LOKI_STAT_FETCHER_H__

View File

@ -1,9 +1,11 @@
#include "LokinetApiClient.hpp"
#include <QJsonDocument>
#include <stdexcept>
#include <cstdio>
#include <QDebug>
bool LokinetApiClient::invoke(const std::string& endpoint, ReplyCallback callback) {
bool LokinetApiClient::invoke(const std::string& endpoint, QJsonObject args, ReplyCallback callback) {
std::cout << "call " << endpoint;
if(not m_lmqConnection.has_value())
{
m_lmqClient.start();
@ -16,6 +18,8 @@ bool LokinetApiClient::invoke(const std::string& endpoint, ReplyCallback callbac
m_lmqConnection = std::nullopt;
});
}
QJsonDocument doc(args);
const auto req = doc.toJson();
m_lmqClient.request(
*m_lmqConnection,
std::string_view{endpoint},
@ -29,18 +33,18 @@ bool LokinetApiClient::invoke(const std::string& endpoint, ReplyCallback callbac
{
cb(std::nullopt);
}
});
}, req.toStdString());
return true;
}
Q_INVOKABLE bool LokinetApiClient::invoke(const std::string& endpoint, QJSValue callback) {
Q_INVOKABLE bool LokinetApiClient::invoke(const std::string& endpoint,QJsonObject callargs, QJSValue callback) {
if (! callback.isUndefined() && ! callback.isCallable()) {
// qDebug() << "callback should be a function (if present)";
qWarning() << "callback should be a function (if present)";
return false;
}
return invoke(endpoint, [=](std::optional<std::string> reply) mutable {
return invoke(endpoint, callargs, [=](std::optional<std::string> reply) mutable {
QJSValueList args;
if(reply.has_value())
{

View File

@ -3,6 +3,7 @@
#include <QObject>
#include <QJSValue>
#include <QJsonObject>
#include <lokimq/lokimq.h>
#include <optional>
@ -44,8 +45,8 @@ public:
* @param callback is a callback that will receive the reply or error
* @return true on success, false otherwise
*/
bool invoke(const std::string& endpoint, ReplyCallback callback);
Q_INVOKABLE bool invoke(const std::string& endpoint, QJSValue callback);
bool invoke(const std::string& endpoint, QJsonObject args, ReplyCallback callback);
Q_INVOKABLE bool invoke(const std::string& endpoint, QJsonObject args ,QJSValue callback);
/**
* The following functions are conveniences for invoking particular API
@ -54,21 +55,29 @@ public:
* @param callback is an optional JS function to invoke on success
* @return true if the asynchronous request could be made, false otherwise
*/
Q_INVOKABLE bool llarpAdminWakeup(QJSValue callback) {
/*
Q_INVOKABLE bool llarpAdminWakeup(QJSValue callback) {
return invoke("llarp.admin.wakeup", callback);
}
*/
Q_INVOKABLE bool llarpVersion(QJSValue callback) {
return invoke("llarp.version", callback);
return invoke("llarp.version", QJsonObject{}, callback);
}
Q_INVOKABLE bool llarpAdminStatus(QJSValue callback) {
return invoke("llarp.admin.status", callback);
Q_INVOKABLE bool llarpExit(QString exitAddress, QJSValue callback) {
if(exitAddress.isEmpty())
{
return invoke("llarp.exit", QJsonObject{{"unmap", true}}, callback);
}
else
{
return invoke("llarp.exit", QJsonObject{{"exit", exitAddress}}, callback);
}
}
bool llarpAdminDie(ReplyCallback callback) {
return invoke("llarp.admin.die", callback);
return invoke("llarp.halt", QJsonObject{}, callback);
}
private:

View File

@ -3,6 +3,7 @@
#include <QPoint>
#include <QCursor>
#include <QJSEngine>
#include <QDebug>
#include "process/LokinetProcessManager.hpp"

View File

@ -1,6 +1,7 @@
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QIcon>
#include <QDebug>
#include "QmlClipboardAdapter.hpp"
#include "LokinetApiClient.hpp"