/* * 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 "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) { Q_ASSERT(host != nullptr); 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()) { qCritical() << "D-Bus 'start' request failed, this was the reply:"; qCritical() << reply.error(); if (QDBusError::ServiceUnknown == reply.error().type()) { qCritical() << "The session service was probably just not started!"; } 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) { Q_ASSERT(host != nullptr); Q_ASSERT(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()) { qCritical() << "D-Bus 'stop' request failed, this was the reply:"; qCritical() << reply.error(); if (QDBusError::ServiceUnknown == reply.error().type()) { qCritical() << "The session service was probably just not started!"; } emit serviceStopResponse(nullptr); return; } 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) { Q_ASSERT(host != nullptr); Q_ASSERT(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) { Q_ASSERT(host != nullptr); Q_ASSERT(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()) { qCritical() << "D-Bus '(refresh_)status' request failed, this was the reply:"; qCritical() << reply.error(); if (QDBusError::ServiceUnknown == reply.error().type()) { qCritical() << "The session service was probably just not started!"; } 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, QString host_alias) { Q_ASSERT(host_url != ""); Q_ASSERT(host_alias != ""); qDebug().noquote() << QString("Requesting D-Bus service to register new " "remote web app host '%0' with url '%1'").arg(host_alias).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, host_alias); 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) { Q_ASSERT(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()) { qCritical() << "D-Bus 'get_web_app_hosts' request failed, this was the reply:"; qCritical() << reply.error(); if (QDBusError::ServiceUnknown == reply.error().type()) { qCritical() << "The session service was probably just not started!"; } 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()) { qCritical() << "D-Bus 'add_web_app_host' request failed, this was the reply:"; qCritical() << reply.error(); if (QDBusError::ServiceUnknown == reply.error().type()) { qCritical() << "The session service was probably just not started!"; } 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()) { qCritical() << "D-Bus 'remove_web_app_host' request failed, this was the reply:"; qCritical() << reply.error(); if (QDBusError::ServiceUnknown == reply.error().type()) { qCritical() << "The session service was probably just not started!"; } 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); }