From 11787ea278bc6ff6d5bc797b597df3f26e2ec9b4 Mon Sep 17 00:00:00 2001 From: Daniel Teichmann Date: Tue, 6 Jul 2021 19:55:13 +0200 Subject: Introduce DBusAPI and RWAHost classes --- qml.qrc | 4 + rwa-support-desktopapp.pro | 12 +- src/DBusAPI.cpp | 351 +++++++++++++++++++++ src/DBusAPI.h | 63 ++++ src/RWAHost.cpp | 71 +++++ src/RWAHost.h | 56 ++++ src/main.cpp | 1 + src/scenes/add_server_wizard/add_server_wizard.cpp | 133 ++++---- src/scenes/add_server_wizard/add_server_wizard.h | 44 ++- src/session.cpp | 270 ++++------------ src/session.h | 57 ++-- 11 files changed, 754 insertions(+), 308 deletions(-) create mode 100644 src/DBusAPI.cpp create mode 100644 src/DBusAPI.h create mode 100644 src/RWAHost.cpp create mode 100644 src/RWAHost.h diff --git a/qml.qrc b/qml.qrc index 3e9d682..e7bf198 100644 --- a/qml.qrc +++ b/qml.qrc @@ -15,6 +15,10 @@ src/RWADBusAdaptor.h src/session.cpp src/session.h + src/RWAHost.h + src/RWAHost.cpp + src/DBusAPI.h + src/DBusAPI.cpp src/ListItem.qml src/ToastManager.qml src/Toast.qml diff --git a/rwa-support-desktopapp.pro b/rwa-support-desktopapp.pro index 095db2d..5c3f24d 100644 --- a/rwa-support-desktopapp.pro +++ b/rwa-support-desktopapp.pro @@ -47,13 +47,17 @@ SOURCES += src/main.cpp \ src/main_qmladaptor.cpp \ src/RWADBusAdaptor.cpp \ src/session.cpp \ - src/scenes/add_server_wizard/add_server_wizard.cpp + src/scenes/add_server_wizard/add_server_wizard.cpp \ + src/RWAHost.cpp \ + src/DBusAPI.cpp HEADERS += src/RWADBusAdaptor.h \ src/main_qmladaptor.h \ src/RWADBusAdaptor.h \ src/session.h \ - src/scenes/add_server_wizard/add_server_wizard.h + src/scenes/add_server_wizard/add_server_wizard.h \ + src/RWAHost.h \ + src/DBusAPI.h RESOURCES += qml.qrc @@ -68,4 +72,6 @@ qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target -DISTFILES += +#DISTFILES += + +CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT diff --git a/src/DBusAPI.cpp b/src/DBusAPI.cpp new file mode 100644 index 0000000..0809a51 --- /dev/null +++ b/src/DBusAPI.cpp @@ -0,0 +1,351 @@ +#include "DBusAPI.h" + +/*! + * \class DBusAPI + * \brief The DBusAPI class provides all necessary D-Bus methods and distributes the response via signals. + */ +DBusAPI::DBusAPI() { + _initDBus(); +} + +/*! + * \brief Initializes private _dbus_rwa object. + */ +void DBusAPI::_initDBus() { + if (!QDBusConnection::sessionBus().isConnected()) { + qCritical() << "Cannot connect to the D-Bus session bus."; + } + + // Create DBus object + _dbus_rwa = new OrgArcticaProjectRWASupportSessionServiceInterface("org.ArcticaProject.RWASupportSessionService", + "/RWASupportSessionService", + QDBusConnection::sessionBus(), + this->parent()); + + qDebug("Initialized DBus object!"); +} + +/*! + * \brief Ask the session service to start a session. + * + * \a host RWAHost object which includes all necessary information about a RWA host. + */ +void DBusAPI::start_request(RWAHost *host) { + qDebug() << "Requesting D-Bus service to start a new session on host:" << host->alias(); + + // Make an asynchrous 'start' call (Response will be sent to 'start_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("start", host->uuid()); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(start_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::start_reply(QDBusPendingCallWatcher *call) { + QString result = ""; + QDBusPendingReply reply = *call; + if (reply.isError()) { + qDebug() << "D-Bus 'start' request failed, this was the reply:"; + qDebug() << reply.error(); + + emit serviceStartResponse(nullptr); + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + qDebug() << "Raw JSON from starting session is:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceStartResponse(&doc); +} + +/*! + * \brief Ask the session service to stop session #. + * + * \a host RWAHost object which includes all necessary information about a RWA host. + * + * \a session_id Unique identifier for a session in a specific host. + */ +void DBusAPI::stop_request(RWAHost *host, QString session_id) { + bool ok; + long long session_id_number = session_id.toLongLong(&ok); + + // Sanity Check + if(ok == false){ + qWarning() << QString("Unable to parse '%0' as long long!").arg(session_id); + return; + } + + qDebug().noquote() << QString("Requesting D-Bus service to stop " + "session #'%0' on host '%1'") + .arg(session_id) + .arg(host->alias()); + + // Make an asynchrous 'start' call (Response will be sent to 'stop_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("stop", host->uuid(), session_id_number); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(stop_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::stop_reply(QDBusPendingCallWatcher *call) { + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qDebug() << "D-Bus 'stop' request failed, this was the reply:"; + qDebug() << reply.error(); + + emit serviceStopResponse(nullptr); + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + qDebug() << "Raw JSON from stopping a session is:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceStopResponse(&doc); +} + +/*! + * \brief Ask the session service for status of . + * + * \a host RWAHost object which includes all necessary information about a RWA host. + * + * \a session_id Unique identifier for a session in a specific host. + */ +void DBusAPI::status_request(RWAHost *host, QString session_id) { + bool ok; + long long session_id_number = session_id.toLongLong(&ok); + + // Sanity Check + if(ok == false){ + qWarning() << QString("Unable to parse '%0' as long long!").arg(session_id); + return; + } + + qDebug().noquote() << QString("Requesting D-Bus service for status of session " + "#'%0' on host '%1'").arg(session_id).arg(host->alias()); + + // Make an asynchrous 'start' call (Response will be sent to 'status_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("status", host->uuid(), session_id_number); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(status_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Forces the session service to refresh it's status of and tell us about it then. + * + * \a host RWAHost object which includes all necessary information about a RWA host. + * + * \a session_id Unique identifier for a session in a specific host. + */ +void DBusAPI::refresh_status_request(RWAHost *host, QString session_id) { + bool ok; + long long session_id_number = session_id.toLongLong(&ok); + + // Sanity Check + if(ok == false){ + qWarning() << QString("Unable to parse '%0' as long long!").arg(session_id); + return; + } + + qDebug().noquote() << QString("Requesting D-Bus service for refresh_status of session " + "#'%0' on host '%1'").arg(session_id).arg(host->alias()); + + // Make an asynchrous 'start' call (Response will be sent to 'status_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("refresh_status", host->uuid(), session_id_number); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(status_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::status_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qDebug() << "D-Bus '(refresh_)status' request failed, this was the reply:"; + qDebug() << reply.error(); + + emit serviceStatusResponse(nullptr); + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from a status request for a session is:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceStatusResponse(&doc); +} + +/*! + * \brief This method requests the session service to list all RWAHosts. + */ +void DBusAPI::get_web_app_hosts_request() { + qDebug().noquote() << QString("Requesting D-Bus service to list " + "all remote web app hosts"); + + // Make an asynchrous 'get_web_app_hosts' call + // Response will be sent to 'get_web_app_hosts_reply' + QDBusPendingCall async = _dbus_rwa->asyncCall("get_web_app_hosts"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(get_web_app_hosts_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief This method requests the session service to add a RWAHost to its configuration files. + * + * \a host_url is the remote web app adress which will be used by the session service to coordinate + * sessions, connections, settings and such. + */ +void DBusAPI::add_web_app_host_request(QString host_url) { + qDebug().noquote() << QString("Requesting D-Bus service to register new " + "remote web app host with url '%0'").arg(host_url); + + // Make an asynchrous 'add_web_app_host' call + // Response will be sent to 'add_web_app_host_reply' + QDBusPendingCall async = _dbus_rwa->asyncCall("add_web_app_host", host_url); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(add_web_app_host_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief This method requests the session service to remove a RWAHost from its configuration files. + * + * \a host_uuid Unique identifier which all hosts have. + */ +void DBusAPI::remove_web_app_host_request(QString host_uuid) { + qDebug().noquote() << QString("Requesting D-Bus service to list " + "all remote web app hosts"); + + // Make an asynchrous 'remove_web_app_host' call + // Response will be sent to 'remove_web_app_host_reply' + QDBusPendingCall async = _dbus_rwa->asyncCall("remove_web_app_host", host_uuid); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(remove_web_app_host_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::get_web_app_hosts_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qDebug() << "D-Bus 'get_web_app_hosts' request failed, this was the reply:"; + qDebug() << reply.error(); + + emit serviceGetWebAppHostsResponse(nullptr); + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from the remote web app host listing request:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceGetWebAppHostsResponse(&doc); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::add_web_app_host_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qDebug() << "D-Bus 'add_web_app_host' request failed, this was the reply:"; + qDebug() << reply.error(); + + emit serviceAddWebAppHostResponse(nullptr); + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from the remote web app host register request:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceAddWebAppHostResponse(&doc); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::remove_web_app_host_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qDebug() << "D-Bus 'remove_web_app_host' request failed, this was the reply:"; + qDebug() << reply.error(); + + emit serviceRemoveWebAppHostResponse(nullptr); + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from the remote web app host deletion request:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceRemoveWebAppHostResponse(&doc); +} diff --git a/src/DBusAPI.h b/src/DBusAPI.h new file mode 100644 index 0000000..1564f57 --- /dev/null +++ b/src/DBusAPI.h @@ -0,0 +1,63 @@ +#ifndef DBUSAPI_H +#define DBUSAPI_H + +#include +#include + +#include "RWAHost.h" +#include "RWADBusAdaptor.h" + +class DBusAPI : public QObject +{ + Q_OBJECT +public: + explicit DBusAPI(); + +signals: + void serviceStartResponse(QJsonDocument*); + void serviceStopResponse(QJsonDocument*); + void serviceStatusResponse(QJsonDocument*); + + void serviceGetWebAppHostsResponse(QJsonDocument*); + void serviceAddWebAppHostResponse(QJsonDocument*); + void serviceRemoveWebAppHostResponse(QJsonDocument*); + +public slots: + void start_reply(QDBusPendingCallWatcher *call); + void stop_reply(QDBusPendingCallWatcher *call); + void status_reply(QDBusPendingCallWatcher *call); + + void get_web_app_hosts_reply(QDBusPendingCallWatcher *call); + void add_web_app_host_reply(QDBusPendingCallWatcher *call); + void remove_web_app_host_reply(QDBusPendingCallWatcher *call); + + + // Starts a remote web app session + void start_request(RWAHost *host); + + // Stop a remote web app session + void stop_request(RWAHost *host, QString session_id); + + // Refreshes a remote web app session's status + void refresh_status_request(RWAHost *host, QString session_id); + + // Gets a remote web app session's status + void status_request(RWAHost *host, QString session_id); + + // Gets all remote web app hosts deposited in the session server + void get_web_app_hosts_request(); + + // Add a specific remote web app host using a url to make sure its contactable + void add_web_app_host_request(QString host_url); + + // Removes a specific remote web app host using the uuid of a host + void remove_web_app_host_request(QString host_uuid); + +private: + OrgArcticaProjectRWASupportSessionServiceInterface* _dbus_rwa; + + void _initDBus(); + +}; + +#endif // DBUSAPI_H diff --git a/src/RWAHost.cpp b/src/RWAHost.cpp new file mode 100644 index 0000000..006ecd9 --- /dev/null +++ b/src/RWAHost.cpp @@ -0,0 +1,71 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "RWAHost.h" + +RWAHost::RWAHost(QString uuid, QString alias, QString url) { + assert(uuid != ""); + assert(alias != ""); + assert(url != ""); + + qDebug() << "Created new RWAHost object.\n\t" + << QString("uuid: '%0'").arg(uuid) << "\n\t" + << QString("alias: '%0'").arg(alias) << "\n\t" + << QString("url: '%0'").arg(url); + + _url = url; + _alias = alias; + _uuid = uuid; +} + +QString RWAHost::url() const +{ + return _url; +} + +void RWAHost::setUrl(const QString &url) +{ + _url = url; +} + +QString RWAHost::alias() const +{ + return _alias; +} + +void RWAHost::setAlias(const QString &alias) +{ + _alias = alias; +} + +QString RWAHost::uuid() const +{ + return _uuid; +} + +void RWAHost::setUuid(const QString &uuid) +{ + _uuid = uuid; +} diff --git a/src/RWAHost.h b/src/RWAHost.h new file mode 100644 index 0000000..c78ef5f --- /dev/null +++ b/src/RWAHost.h @@ -0,0 +1,56 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef RWAHOST_H +#define RWAHOST_H + +#include +#include + +class RWAHost : public QObject +{ + Q_OBJECT +public: + explicit RWAHost(QString uuid = "", QString alias = "", QString url = ""); + + QString uuid() const; + QString alias() const; + QString url() const; + + void setUuid(const QString &uuid); + void setAlias(const QString &alias); + void setUrl(const QString &url); + +private: + QString _uuid; + QString _alias; + QString _url; + +signals: + +public slots: +}; + +#endif // RWAHOST_H diff --git a/src/main.cpp b/src/main.cpp index f6408b3..f23e2c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,6 +39,7 @@ #include "RWADBusAdaptor.cpp" #include "session.h" #include "scenes/add_server_wizard/add_server_wizard.h" +#include "RWAHost.h" #define BUILD_TIME __DATE__ " " __TIME__ diff --git a/src/scenes/add_server_wizard/add_server_wizard.cpp b/src/scenes/add_server_wizard/add_server_wizard.cpp index f8d4b7b..bd1dd3c 100644 --- a/src/scenes/add_server_wizard/add_server_wizard.cpp +++ b/src/scenes/add_server_wizard/add_server_wizard.cpp @@ -1,100 +1,121 @@ -#include "add_server_wizard.h" -#include "../../RWADBusAdaptor.h" +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include #include -Add_Server_wizard::Add_Server_wizard(QObject *parent) : QObject(parent) { - _initDBus(); +#include "add_server_wizard.h" +#include "../../RWADBusAdaptor.h" +#include "../../RWAHost.h" +Add_Server_wizard::Add_Server_wizard(QObject *parent) : QObject(parent) { + _dbus_api = new DBusAPI(); + // _dbus_api --serviceAddWebAppHostResponse-> this.add_web_app_host_response() + QObject::connect(_dbus_api, + SIGNAL(serviceAddWebAppHostResponse(QJsonDocument*)), + this, + SLOT(add_web_app_host_response(QJsonDocument*))); } -bool Add_Server_wizard::processStep1(QString host_url) { +void Add_Server_wizard::processStep1(QString host_url) { qDebug() << "Processing Step 1 with args: " << host_url; if(host_url == "") { emit step1Failed(tr("This field can't be empty!")); - return false; + return; } - return _add_server(host_url); + return add_server(host_url); } -bool Add_Server_wizard::processStep2() { +void Add_Server_wizard::processStep2() { qDebug() << "Processing Step 2 with args: No Args."; - emit step2Failed(tr("The feature you expected here are not yet implemented.")); + emit step2Failed(tr("The features you expected here are not yet implemented.")); // Just show placeholder scene now. emit step2Success(); - return false; } -bool Add_Server_wizard::_add_server(QString host_url) { - return _add_web_app_host(host_url); +void Add_Server_wizard::add_server(QString host_url) { + _dbus_api->add_web_app_host_request(host_url); } -void Add_Server_wizard::_initDBus() { - if (!QDBusConnection::sessionBus().isConnected()) { - qCritical() << "Cannot connect to the D-Bus session bus."; - } - - // Create DBus object - _dbus_rwa = new OrgArcticaProjectRWASupportSessionServiceInterface("org.ArcticaProject.RWASupportSessionService", "/RWASupportSessionService", - QDBusConnection::sessionBus(), this->parent()); - - qDebug("Initialized DBus object!"); -} - -bool Add_Server_wizard::_add_web_app_host(QString host_url) { - qDebug() << "Requesting D-Bus session service to add a new host: " << host_url; - - // Make an asynchrous 'add_web_app_host' call (Response will be sent to '_add_web_app_host_dbus_replied') - QDBusPendingCall async = _dbus_rwa->asyncCall("add_web_app_host", host_url); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); +void Add_Server_wizard::add_web_app_host_response(QJsonDocument *doc) { + // Get the QJsonObject + QJsonObject jObject = doc->object(); + QVariantMap mainMap = jObject.toVariantMap(); - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(_add_web_app_host_dbus_replied(QDBusPendingCallWatcher*))); + // Status of request + QString request_status = mainMap["status"].toString(); + if (request_status == "success") { + // Building host_object + QJsonObject host_object = jObject.value(QString("host")).toObject(); - return true; -} + QString host_uuid = host_object["uuid"].toString(); + QString host_alias = host_object["alias"].toString(); + QString host_url = host_object["url"].toString(); -void Add_Server_wizard::_add_web_app_host_dbus_replied(QDBusPendingCallWatcher *call) { - QString result = ""; + if (host_url == "" || host_uuid == "") { + // This two values are required and can't be omitted. + QString reason = tr("Response of D-Bus service lacks necessary host object."); + qCritical().noquote() << tr("An error occured while adding a new host:") + << reason; + emit step1Failed(reason); - QDBusPendingReply reply = *call; - if (reply.isError()) { - qDebug() << "D-Bus 'add_web_app_host' request failed, this was the reply:"; - qDebug() << reply.error(); - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); + return; + } - qDebug() << "Raw JSON from starting session is:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + if (host_alias == "") { + qDebug().noquote() << QString("An alias for the host wasn't delivered " + "so just use '%0' as alias.").arg(host_url); + host_alias = host_url; + } - // Get the QJsonObject - QJsonObject jObject = doc.object(); - QVariantMap mainMap = jObject.toVariantMap(); + // Now built RWAHost object. + QScopedPointer rwa_host (new RWAHost(host_uuid, host_alias, host_url)); - // Status of request - QString request_status = mainMap["status"].toString(); - if (request_status == "success") { - qDebug() << "Successfully started a Session."; + qInfo() << "Successfully added a new RWAHost."; emit step1Success(); } else { - qCritical() << "An error occured while adding a new host!"; + qCritical().noquote() << tr("An error occured while adding a new host!"); - QString reason = "An error occured while adding a new host!"; + QString reason = tr("An error occured while adding a new host!"); QString type = mainMap["type"].toString(); if(type == "connection"){ reason = tr("Couldn't connect to the specified host!"); + qCritical().noquote() << reason; } else if (type == "duplicate") { reason = tr("The specified host was already added!"); + qCritical().noquote() << reason; } else if (type == "invalid_url") { reason = tr("The specified host address is not valid!"); + qCritical().noquote() << reason; } emit step1Failed(reason); + + return; } } diff --git a/src/scenes/add_server_wizard/add_server_wizard.h b/src/scenes/add_server_wizard/add_server_wizard.h index 1feec9b..554f6af 100644 --- a/src/scenes/add_server_wizard/add_server_wizard.h +++ b/src/scenes/add_server_wizard/add_server_wizard.h @@ -1,21 +1,45 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef ADD_SERVER_WIZARD_H #define ADD_SERVER_WIZARD_H -#include "../../RWADBusAdaptor.h" #include +#include "../../RWADBusAdaptor.h" +#include "../../DBusAPI.h" + class Add_Server_wizard : public QObject { Q_OBJECT public: explicit Add_Server_wizard(QObject *parent = nullptr); + void add_server(QString host_url); private: - bool _add_server(QString host_url); - bool _add_web_app_host(QString host_url); - - OrgArcticaProjectRWASupportSessionServiceInterface *_dbus_rwa; - void _initDBus(); + DBusAPI *_dbus_api; signals: void step1Success(); @@ -24,12 +48,10 @@ signals: void step2Failed(QString reason); public slots: - bool processStep1(QString host_url); - bool processStep2(); + void processStep1(QString host_url); + void processStep2(); - void _add_web_app_host_dbus_replied(QDBusPendingCallWatcher *call); - //void _get_web_app_hosts_dbus_replied(QDBusPendingCallWatcher *call); - //void _remove_web_app_host_dbus_replied(QDBusPendingCallWatcher *call); + void add_web_app_host_response(QJsonDocument *doc); }; #endif // ADD_SERVER_WIZARD_H diff --git a/src/session.cpp b/src/session.cpp index f3aa168..1ee4eef 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -26,51 +26,74 @@ #include "session.h" -Session::Session(QObject *parent, MainQMLAdaptor* main_gui) : QObject(parent) { - _initDBus(); +Session::Session(QObject *parent, MainQMLAdaptor* main_gui, RWAHost *host) : QObject(parent) { + Q_ASSERT(main_gui != nullptr); + Q_ASSERT(host != nullptr); + _dbus_api = new DBusAPI(); _main_gui = main_gui; + _host = host; // QML -> MainQMLAdaptor::handleConnectButtonClick --onConnectButtonClick--> this::handleConnectButtonClick QObject::connect(_main_gui, - SIGNAL(onConnectButtonClick(bool)), - this, - SLOT(handleConnectButtonClick(bool))); + SIGNAL(onConnectButtonClick(bool)), + this, + SLOT(handleConnectButtonClick(bool))); // session::setPin --pinChanged--> MainQMLAdaptor::setPin --pinChanged--> QML QObject::connect(this, - SIGNAL(pinChanged(QString)), - main_gui, - SLOT(setPin(QString))); + SIGNAL(pinChanged(QString)), + main_gui, + SLOT(setPin(QString))); + // session::setURL --urlChanged--> MainQMLAdaptor::setURL --urlChanged--> QML QObject::connect(this, - SIGNAL(urlChanged(QString)), - main_gui, - SLOT(setURL(QString))); + SIGNAL(urlChanged(QString)), + main_gui, + SLOT(setURL(QString))); + // session::setSessionID --sessionIDChanged--> MainQMLAdaptor::setSessionID --sessionIDChanged--> QML QObject::connect(this, - SIGNAL(sessionIDChanged(QString)), - main_gui, - SLOT(setSessionID(QString))); + SIGNAL(sessionIDChanged(QString)), + main_gui, + SLOT(setSessionID(QString))); // QML -> MainQMLAdaptor::onCloseHandler --onCloseSignal--> session::onCloseHandler QObject::connect(main_gui, - SIGNAL(onCloseSignal()), - this, - SLOT(onCloseHandler())); + SIGNAL(onCloseSignal()), + this, + SLOT(onCloseHandler())); + + // _dbus_api --sessionStartResponse-> this.start_response() + QObject::connect(_dbus_api, + SIGNAL(serviceStartResponse(QJsonDocument*)), + this, + SLOT(start_response(QJsonDocument*))); + + // _dbus_api --sessionStopResponse-> this.stop_response() + QObject::connect(_dbus_api, + SIGNAL(serviceStopResponse(QJsonDocument*)), + this, + SLOT(stop_response(QJsonDocument*))); + + // _dbus_api --sessionStatusResponse-> this.status_response() + QObject::connect(_dbus_api, + SIGNAL(serviceStatusResponse(QJsonDocument*)), + this, + SLOT(status_response(QJsonDocument*))); + this->init_vars(); } void Session::statusTimerEvent() { - qDebug() << "Status timer event triggered"; - this->refresh_status_request_dbus(this->getHostID(), this->getID()); + qDebug() << "Status timer event got triggered just now."; + this->status(); } void Session::init_vars() { setPin("-----"); setSessionID("-----"); - setID("-----"); setURL(tr("Not available yet")); setStatus("unknown"); @@ -89,18 +112,10 @@ QString Session::getURL() { return _url; } -QString Session::getID() { - return QString(_id); -} - QString Session::getSessionID() { return QString(_session_id); } -QString Session::getHostID() { - return QString(_host_id); -} - QString Session::getPin() { return _pin; } @@ -201,11 +216,6 @@ void Session::setURL(QString url) { emit urlChanged(url); } -void Session::setID(QString id) { - _id = id; - emit idChanged(id); -} - void Session::setSessionID(QString session_id) { _session_id = session_id; emit sessionIDChanged(session_id); @@ -218,79 +228,33 @@ void Session::setPin(QString pin) { void Session::handleConnectButtonClick(bool checked) { qDebug() << "-----Connect button handler-----" << - "\nCurrent service-session #" << this->getID() << - "\nCurrent support-session #" << this->getSessionID(); + "\nCurrent session #" << this->getSessionID(); // Stopping even if nothing is running - this->stop_request_dbus(this->getID()); + _dbus_api->stop_request(_host, this->getSessionID()); if (checked) { // Start the Session again - this->start_request_dbus(getHostID()); + _dbus_api->start_request(_host); } qDebug() << "-----\\Connect button handler-----"; } -void Session::_initDBus() { - if (!QDBusConnection::sessionBus().isConnected()) { - qCritical() << "Cannot connect to the D-Bus session bus."; - } - - // Create DBus object - _dbus_rwa = new OrgArcticaProjectRWASupportSessionServiceInterface("org.ArcticaProject.RWASupportSessionService", "/RWASupportSessionService", - QDBusConnection::sessionBus(), this->parent()); - - qDebug("Initialized DBus object!"); -} - -void Session::start_request_dbus(QString host_id) { - qDebug() << "Requesting D-Bus session service to start a new session on host: " << host_id; - bool ok; - host_id.toLongLong(&ok); - if(ok == false){ - qErrnoWarning("Unable to convert id to "); - return; - } - - // Make an asynchrous 'start' call (Response will be sent to 'start_dbus_replied') - QDBusPendingCall async = _dbus_rwa->asyncCall("start", host_id); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(start_dbus_replied(QDBusPendingCallWatcher*))); - +void Session::start() { // Disable connect button to reduce spam. // And don't enable it as long there is no status update. // (Or something fails) _main_gui->setConnectButtonEnabled(false); this->setStatus("waiting_start_request_answer"); -} -void Session::start_dbus_replied(QDBusPendingCallWatcher *call) { - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qDebug() << "D-Bus 'start' request failed, this was the reply:"; - qDebug() << reply.error(); - - // The user should have the oportunity to try again. - this->init_vars(); - - qCritical() << "An error occured while creating a new session!"; - this->setStatus("start_session_error"); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); + _dbus_api->start_request(_host); +} - qDebug() << "Raw JSON from starting session is:" << result; - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); +void Session::start_response(QJsonDocument *doc) { + Q_ASSERT(doc != nullptr); // Get the QJsonObject - QJsonObject jObject = doc.object(); + QJsonObject jObject = doc->object(); QVariantMap mainMap = jObject.toVariantMap(); // Status of request @@ -308,16 +272,7 @@ void Session::start_dbus_replied(QDBusPendingCallWatcher *call) { return; } - // Service ID == PID bool ok; - long long service_id = mainMap["id"].toLongLong(&ok); - this->setID(QString::number(service_id)); - // Sanity Check - if(ok == false){ - qErrnoWarning("Unable to parse out of dbus answer!"); - init_vars(); - return; - } // URL of remote web app frontend QString url = mainMap["url"].toString(); @@ -343,37 +298,17 @@ void Session::start_dbus_replied(QDBusPendingCallWatcher *call) { return; } - qDebug() << "Got service_id:" << service_id << - "\nGot session_id:" << session_id << + qDebug() << "Got session_id:" << session_id << "\nGot url:" << url << "\nGot pin:" << pin; emit pinChanged(QString::number(pin)); emit urlChanged(url); - emit idChanged(QString::number(service_id)); emit sessionIDChanged(QString::number(session_id)); } -void Session::stop_request_dbus(QString id) { - bool ok; - if (id.toLongLong(&ok) == 0 ){ - qDebug() << "Won't send a request to D-Bus service to stop a session when session ID == 0"; - return; - } - if(ok == false){ - qErrnoWarning("Unable to convert id to "); - return; - } - - // Stopping now. - qDebug() << "Requesting D-Bus session service to stop session #" << id; - - // Make an asynchrous 'stop' call (Response will be sent to 'stop_dbus_replied') - QDBusPendingCall async = _dbus_rwa->asyncCall("stop", id); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(stop_dbus_replied(QDBusPendingCallWatcher*))); +void Session::stop() { + _dbus_api->stop_request(_host, this->getSessionID()); // Clear current variables this->init_vars(); @@ -384,30 +319,14 @@ void Session::stop_request_dbus(QString id) { _main_gui->setConnectButtonEnabled(false); } -void Session::stop_dbus_replied(QDBusPendingCallWatcher *call) { - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qDebug() << "D-Bus 'stop' request failed, this was the reply:"; - qDebug() << reply.error(); - - this->init_vars(); - this->setStatus("stop_session_error"); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); +void Session::stop_response(QJsonDocument *doc) { + Q_ASSERT(doc != nullptr); - // Get the QJsonObject - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - QJsonObject jObject = doc.object(); + QJsonObject jObject = doc->object(); QVariantMap mainMap = jObject.toVariantMap(); QString new_status = mainMap["status"].toString(); - qDebug() << "stop_dbus_replied(): Refreshed status:" << new_status; + qDebug() << "stop_response() retrieved json. Status now:" << new_status; // Clear current variables this->init_vars(); @@ -416,74 +335,17 @@ void Session::stop_dbus_replied(QDBusPendingCallWatcher *call) { this->setStatus(new_status); } -void Session::status_request_dbus(QString id) { - bool ok; - if (id.toLongLong(&ok) == 0 ){ - qDebug() << "Won't send a request to D-Bus service of a session's status when session ID == 0"; - return; - } - if(ok == false){ - qErrnoWarning("Unable to convert id to "); - return; - } - - // Requesting status now. - qDebug() << "Requesting status for session #" << id; - - // Make an asynchrous 'status' call (Response will be sent to 'status_dbus_replied') - QDBusPendingCall async = _dbus_rwa->asyncCall("status", id); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(stop_dbus_replied(QDBusPendingCallWatcher*))); +void Session::status() { + _dbus_api->status_request(_host, this->getSessionID()); } -void Session::refresh_status_request_dbus(QString host_id, QString id) { - bool ok; - if (id.toLongLong(&ok) == 0){ - qDebug() << "Won't send a request to D-Bus service to refresh the status of a session when session ID == 0"; - return; - } - if(ok == false){ - qErrnoWarning("Unable to convert id to "); - return; - } - - // Refreshing status - qDebug() << "Requesting status refresh for session #" << id; - - // Make an asynchrous 'refresh_status' call (Response will be sent to 'status_dbus_replied') - QDBusPendingCall async = _dbus_rwa->asyncCall("refresh_status", host_id, id); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(status_dbus_replied(QDBusPendingCallWatcher*))); -} +void Session::status_response(QJsonDocument *doc) { + Q_ASSERT(doc != nullptr); -void Session::status_dbus_replied(QDBusPendingCallWatcher *call) { - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qDebug() << "D-Bus '(refresh_)status' request failed, this was the reply:"; - qDebug() << reply.error(); - - this->init_vars(); - - this->setStatus("status_session_error"); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - // Get the QJsonObject - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - QJsonObject jObject = doc.object(); + QJsonObject jObject = doc->object(); QVariantMap mainMap = jObject.toVariantMap(); QString new_status = mainMap["status"].toString(); - qDebug() << "status_dbus_replied(): Refreshed status:" << new_status; + qDebug() << "status_response() retrieved json. Status:" << new_status; // Enable (dis)connect button _main_gui->setConnectButtonEnabled(true); @@ -498,5 +360,5 @@ void Session::status_dbus_replied(QDBusPendingCallWatcher *call) { void Session::onCloseHandler() { // To cleanup things here - this->stop_request_dbus(this->getID()); + _dbus_api->stop_request(_host, this->getSessionID()); } diff --git a/src/session.h b/src/session.h index 1b8b2d6..2c534f4 100644 --- a/src/session.h +++ b/src/session.h @@ -24,26 +24,24 @@ * along with this program. If not, see . */ -#pragma once +#ifndef SESSION_H +#define SESSION_H #include #include #include #include #include -#include -#include "RWADBusAdaptor.h" #include "main_qmladaptor.h" +#include "RWAHost.h" +#include "DBusAPI.h" class Session : public QObject { Q_OBJECT - Q_PROPERTY(QString host_id READ getHostID NOTIFY hostIDChanged) // this makes status available as a QML property Q_PROPERTY(QString status READ getStatus NOTIFY statusChanged) - // this makes service id available as a QML property - Q_PROPERTY(QString id READ getID NOTIFY idChanged) // this makes session_id available as a QML property Q_PROPERTY(QString session_id READ getSessionID NOTIFY sessionIDChanged) // this makes url available as a QML property @@ -52,32 +50,23 @@ class Session : public QObject Q_PROPERTY(QString pin READ getPin NOTIFY pinChanged) public: - explicit Session(QObject *parent, MainQMLAdaptor *main_gui = nullptr); + explicit Session(QObject *parent, MainQMLAdaptor *main_gui = nullptr, + RWAHost *host = nullptr); QString getStatus(); QString getURL(); - QString getID(); - QString getHostID(); QString getSessionID(); QString getPin(); void setStatus(QString status); void setURL(QString url); - void setID(QString id); - void setHostID(QString host_id); void setSessionID(QString session_id); void setPin(QString pin); - // Starts a VNC Session - void start_request_dbus(QString host_id); - // Refreshes a VNC Session's status - void refresh_status_request_dbus(QString host_id, QString id); - // Stop the Session - void stop_request_dbus(QString id); - // Gets a VNC Session's status - void status_request_dbus(QString id); - // Returns true if Session is somewhat usable (Running, Alive, etc..) - bool isSessionAliveOrRunning(QString status); + void start(); + void stop(); + void status(); + void refresh_status(); protected: QString _status; @@ -85,33 +74,33 @@ protected: void init_vars(); private: - MainQMLAdaptor* _main_gui; - QString _id; + MainQMLAdaptor *_main_gui; + RWAHost *_host; + DBusAPI *_dbus_api; + QString _session_id; - QString _host_id; QString _url; QString _pin; - OrgArcticaProjectRWASupportSessionServiceInterface* _dbus_rwa; - void _initDBus(); + + // Returns true if a session is somewhat usable (Running, Alive, etc..) + bool isSessionAliveOrRunning(QString status); bool _minimizedBefore = false; void minimizeWindow(); - signals: void finished(); void statusChanged(QString); - void idChanged(QString); void sessionIDChanged(QString); void urlChanged(QString); void pinChanged(QString); - void hostIDChanged(QString); public slots: void handleConnectButtonClick(bool checked); - - void start_dbus_replied(QDBusPendingCallWatcher *call); - void stop_dbus_replied(QDBusPendingCallWatcher *call); - void status_dbus_replied(QDBusPendingCallWatcher *call); - void onCloseHandler(); + + void start_response(QJsonDocument *doc); + void stop_response(QJsonDocument *doc); + void status_response(QJsonDocument *doc); }; + +#endif // SESSION_H -- cgit v1.2.3