Kstars

nodemanager.cpp
1/* EkosLive Node
2
3 SPDX-FileCopyrightText: 2023 Jasem Mutlaq <mutlaqja@ikarustech.com>
4
5 Node Manager
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "nodemanager.h"
11#include "version.h"
12
13#include <QWebSocket>
14#include <QUrlQuery>
15#include <QTimer>
16#include <QJsonDocument>
17
18#include <KActionCollection>
19#include <KLocalizedString>
20#include <basedevice.h>
21#include <QUuid>
22
23namespace EkosLive
24{
25
26///////////////////////////////////////////////////////////////////////////////////////////
27///
28///////////////////////////////////////////////////////////////////////////////////////////
29NodeManager::NodeManager(uint32_t mask)
30{
31 m_NetworkManager = new QNetworkAccessManager(this);
32 connect(m_NetworkManager, &QNetworkAccessManager::finished, this, &NodeManager::onResult);
33
34 // Configure nodes
35 if (mask & Message)
36 m_Nodes[Message] = new Node("message");
37 if (mask & Media)
38 m_Nodes[Media] = new Node("media");
39 if (mask & Cloud)
40 m_Nodes[Cloud] = new Node("cloud");
41
42 for (auto &node : m_Nodes)
43 {
44 connect(node, &Node::connected, this, &NodeManager::setConnected);
45 connect(node, &Node::disconnected, this, &NodeManager::setDisconnected);
46 }
47}
48
49///////////////////////////////////////////////////////////////////////////////////////////
50///
51///////////////////////////////////////////////////////////////////////////////////////////
52void NodeManager::setURLs(const QUrl &service, const QUrl &websocket)
53{
54 m_ServiceURL = service;
55 m_WebsocketURL = websocket;
56 for (auto &node : m_Nodes)
57 node->setProperty("url", m_WebsocketURL);
58}
59
60///////////////////////////////////////////////////////////////////////////////////////////
61///
62///////////////////////////////////////////////////////////////////////////////////////////
63bool NodeManager::isConnected() const
64{
65 return std::all_of(m_Nodes.begin(), m_Nodes.end(), [](const auto & node)
66 {
67 return node->isConnected();
68 });
69}
70
71///////////////////////////////////////////////////////////////////////////////////////////
72///
73///////////////////////////////////////////////////////////////////////////////////////////
74void NodeManager::setConnected()
75{
76 auto node = qobject_cast<Node*>(sender());
77 if (!node)
78 return;
79
80 auto isConnected = std::all_of(m_Nodes.begin(), m_Nodes.end(), [](const auto & node)
81 {
82 return node->isConnected();
83 });
84
85 // Only emit once all nodes are connected.
86 if (isConnected)
87 emit connected();
88}
89
90///////////////////////////////////////////////////////////////////////////////////////////
91///
92///////////////////////////////////////////////////////////////////////////////////////////
93void NodeManager::setDisconnected()
94{
95 auto node = qobject_cast<Node*>(sender());
96 if (!node)
97 return;
98
99 // Only emit once all nodes are disconnected.
100 if (isConnected() == false)
101 emit disconnected();
102}
103
104///////////////////////////////////////////////////////////////////////////////////////////
105///
106///////////////////////////////////////////////////////////////////////////////////////////
107void NodeManager::disconnectNodes()
108{
109 for (auto &node : m_Nodes)
110 node->disconnectServer();
111}
112
113///////////////////////////////////////////////////////////////////////////////////////////
114///
115///////////////////////////////////////////////////////////////////////////////////////////
116void NodeManager::setCredentials(const QString &username, const QString &password)
117{
118 m_Username = username;
119 m_Password = password;
120}
121
122///////////////////////////////////////////////////////////////////////////////////////////
123///
124///////////////////////////////////////////////////////////////////////////////////////////
125void NodeManager::authenticate()
126{
127 QNetworkRequest request;
128 request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
129
130 QUrl authURL(m_ServiceURL);
131 authURL.setPath("/api/authenticate");
132
133 request.setUrl(authURL);
134
135 QJsonObject json = {{"username", m_Username}, {"password", m_Password}, {"machine_id", QString::fromUtf8(QSysInfo::machineUniqueId())}};
136
137 auto postData = QJsonDocument(json).toJson(QJsonDocument::Compact);
138
139 m_NetworkManager->post(request, postData);
140}
141
142///////////////////////////////////////////////////////////////////////////////////////////
143///
144///////////////////////////////////////////////////////////////////////////////////////////
145void NodeManager::onResult(QNetworkReply *reply)
146{
147 if (reply->error() != QNetworkReply::NoError)
148 {
149 // If connection refused, retry up to 3 times
150 if (reply->error() == QNetworkReply::ConnectionRefusedError && m_ReconnectTries++ < RECONNECT_MAX_TRIES)
151 {
152 reply->deleteLater();
153 QTimer::singleShot(RECONNECT_INTERVAL, this, &NodeManager::authenticate);
154 return;
155 }
156
157 m_ReconnectTries = 0;
158 emit authenticationError(i18n("Error authentication with Ekos Live server: %1", reply->errorString()));
159 reply->deleteLater();
160 return;
161 }
162
163 m_ReconnectTries = 0;
165 auto response = QJsonDocument::fromJson(reply->readAll(), &error);
166
167 if (error.error != QJsonParseError::NoError)
168 {
169 emit authenticationError(i18n("Error parsing server response: %1", error.errorString()));
170 reply->deleteLater();
171 return;
172 }
173
174 m_AuthResponse = response.object();
175
176 if (m_AuthResponse["success"].toBool() == false)
177 {
178 emit authenticationError(m_AuthResponse["message"].toString());
179 reply->deleteLater();
180 return;
181 }
182
183 for (auto &node : m_Nodes)
184 {
185 node->setAuthResponse(m_AuthResponse);
186 node->connectServer();
187 }
188
189 reply->deleteLater();
190}
191
192}
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
Generic record interfaces and implementations.
Definition cloud.cpp:22
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QString errorString() const const
QByteArray readAll()
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QByteArray toJson(JsonFormat format) const const
void finished(QNetworkReply *reply)
NetworkError error() const const
void setHeader(KnownHeaders header, const QVariant &value)
void setUrl(const QUrl &url)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
T qobject_cast(QObject *object)
QObject * sender() const const
QString fromUtf8(QByteArrayView str)
QByteArray machineUniqueId()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:40 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.