aboutsummaryrefslogtreecommitdiff
path: root/src/session.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/session.cpp')
-rw-r--r--src/session.cpp489
1 files changed, 129 insertions, 360 deletions
diff --git a/src/session.cpp b/src/session.cpp
index f3aa168..25a8512 100644
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -1,8 +1,8 @@
/*
* This file is part of Remote Support Desktop
* https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp
- * Copyright 2020-2021 Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de>
- * Copyright 2020-2021 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+ * Copyright 2020, 2021 Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de>
+ * Copyright 2020, 2021 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program is free software; you can redistribute it and/or modify
@@ -26,174 +26,60 @@
#include "session.h"
-Session::Session(QObject *parent, MainQMLAdaptor* main_gui) : QObject(parent) {
- _initDBus();
-
- _main_gui = main_gui;
-
- // QML -> MainQMLAdaptor::handleConnectButtonClick --onConnectButtonClick--> this::handleConnectButtonClick
- QObject::connect(_main_gui,
- 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)));
- // session::setURL --urlChanged--> MainQMLAdaptor::setURL --urlChanged--> QML
- QObject::connect(this,
- 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)));
-
- // QML -> MainQMLAdaptor::onCloseHandler --onCloseSignal--> session::onCloseHandler
- QObject::connect(main_gui,
- SIGNAL(onCloseSignal()),
- this,
- SLOT(onCloseHandler()));
-
- this->init_vars();
-}
+Session::Session(DBusAPI *dbus_api, RWAHost *host) : QObject() {
+ Q_ASSERT(host != nullptr);
+ Q_ASSERT(dbus_api != nullptr);
-void Session::statusTimerEvent() {
- qDebug() << "Status timer event triggered";
- this->refresh_status_request_dbus(this->getHostID(), this->getID());
-}
+ _dbus_api = dbus_api;
+ _host = host;
-void Session::init_vars() {
setPin("-----");
setSessionID("-----");
- setID("-----");
setURL(tr("Not available yet"));
setStatus("unknown");
-
- _main_gui->setConnectButtonChecked(false);
- _main_gui->setConnectButtonEnabled(true);
- _main_gui->setStatusIndicator(false);
-
- _minimizedBefore = false;
-}
-
-QString Session::getStatus() {
- return _status;
-}
-
-QString Session::getURL() {
- return _url;
+ started = false;
}
-QString Session::getID() {
- return QString(_id);
+Session::~Session() {
+ qDebug().noquote() << QString("Session #'%0' on host '%1' will be deconstructed.")
+ .arg(getSessionID())
+ .arg(getHost()->alias());
+ stop();
+ disconnect();
}
-QString Session::getSessionID() {
- return QString(_session_id);
-}
-
-QString Session::getHostID() {
- return QString(_host_id);
-}
+void Session::statusTimerEvent() {
+ qDebug() << "Status timer event triggered";
-QString Session::getPin() {
- return _pin;
+ refresh_status();
}
-bool Session::isSessionAliveOrRunning(QString status) {
- if (status == "running" || status == "active") {
+bool Session::isSessionAliveOrRunning() {
+ if (getStatus() == "running" || getStatus() == "active") {
return true;
} else {
return false;
}
}
-void Session::minimizeWindow() {
- if (!_minimizedBefore) {
- qDebug() << "Minimizing window now...";
- emit _main_gui->minimizeWindow();
- _minimizedBefore = true;
- }
+RWAHost* Session::getHost() {
+ return _host;
}
-void Session::setStatus(QString status) {
- _status = status;
+QString Session::getStatus() {
+ return _status;
+}
- QString guiString = tr("Unknown state of service");
- _main_gui->setStatusIndicator(false);
-
- qDebug() << "setStatus(): Setting status to " << status;
-
- if (status == "running") {
- /* Session is running but no one is connected yet */
- guiString = tr("Remote Support session is ready to be connected to");
- _main_gui->setStatusIndicator(true, QColor(255, 255, 0, 127));
- } else if (status == "dead") {
- /* Session died */
- guiString = tr("Remote Support session was stopped ungracefully");
-
- // Clear current variables
- this->init_vars();
- _main_gui->setStatusIndicator(true, QColor(255, 0, 0, 127));
-
- emit _main_gui->showWindow();
-
- _main_gui->showToast(tr("Remote Support session was stopped ungracefully"), 5000);
- } else if (status == "stopped") {
- /* Session is stopped */
- guiString = tr("Remote Support session was stopped");
-
- // Clear current variables
- this->init_vars();
-
- emit _main_gui->showWindow();
-
- _main_gui->showToast(tr("Remote Support session was stopped"), 5000);
- } else if (status == "active") {
- /* Partner is connected */
- QTimer::singleShot(1000, this, &Session::minimizeWindow);
- guiString = tr("Your partner is connected to the Remote Support session");
- _main_gui->setStatusIndicator(true, QColor(0, 255, 0, 127));
-
- } else if (status == "waiting_start_request_answer") {
- /* When pressing on start button display following message while waiting */
- guiString = tr("Trying to reach session service...");
- } else if (status == "start_session_error") {
- /* Session couldn't be started */
- guiString = tr("Remote Support session couldn't be started!");
- _main_gui->setStatusIndicator(true, QColor(255, 0, 0, 127));
-
- _main_gui->showToast(tr("An error occured while trying to start a session!"), 5000);
- } else if (status == "start_session_success") {
- /* Session successfully started */
- guiString = tr("Remote Support session successfully started!");
- _main_gui->setStatusIndicator(true, QColor(255, 255, 0, 127));
-
- _main_gui->showToast(tr("Session was started successfully"));
- } else if (status == "status_session_error") {
- /* Session's status couldn't be refreshed */
- _main_gui->showToast(tr("Session status could not be refreshed!"), 5000);
- guiString = tr("Session status could not be refreshed!") + "\n" + tr("remote support partner could still be connected!");
- _main_gui->setStatusIndicator(true, QColor(255, 0, 0, 127));
-
- emit _main_gui->showWindow();
- } else if (status == "stop_session_error") {
- /* Session couldn't be stopped */
- _main_gui->showToast(tr("Session could not be stopped!"), 5000);
- guiString = tr("Session could not be stopped!") + "\n" + tr("remote support partner could still be connected!");
- _main_gui->setStatusIndicator(true, QColor(255, 0, 0, 127));
-
- emit _main_gui->showWindow();
- }
+QString Session::getURL() {
+ return _url;
+}
- _main_gui->setStatus(guiString);
+QString Session::getSessionID() {
+ return _session_id;
+}
- emit statusChanged(_status);
+QString Session::getPin() {
+ return _pin;
}
void Session::setURL(QString url) {
@@ -201,11 +87,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);
@@ -216,108 +97,66 @@ void Session::setPin(QString pin) {
emit pinChanged(pin);
}
-void Session::handleConnectButtonClick(bool checked) {
- qDebug() << "-----Connect button handler-----" <<
- "\nCurrent service-session #" << this->getID() <<
- "\nCurrent support-session #" << this->getSessionID();
-
- // Stopping even if nothing is running
- this->stop_request_dbus(this->getID());
-
- if (checked) {
- // Start the Session again
- this->start_request_dbus(getHostID());
- }
- qDebug() << "-----\\Connect button handler-----";
+void Session::setHost(RWAHost *host) {
+ _host = host;
+ emit hostChanged(host);
}
-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::setStatus(QString status) {
+ _status = status;
+ emit statusChanged(status);
}
-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 <QString> id to <long long>");
- 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*)));
-
- // 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_api->start_request(_host);
}
-void Session::start_dbus_replied(QDBusPendingCallWatcher *call) {
- QString result = "";
-
- QDBusPendingReply<QString> 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");
-
+void Session::start_response(QJsonDocument *doc) {
+ // Q_ASSERT lets the program crash immediatly after method call
+ // when the session service is not started.
+ // Don't use Q_ASSERT(doc != nullptr); instead use:
+ if (doc == nullptr) {
+ emit startFailed(tr("Can't connect to underlying session service! "
+ "Is the session service started?"));
return;
- } else {
- result = reply.argumentAt<0>();
}
- call->deleteLater();
-
- qDebug() << "Raw JSON from starting session is:" << result;
- QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8());
// Get the QJsonObject
- QJsonObject jObject = doc.object();
+ QJsonObject jObject = doc->object();
QVariantMap mainMap = jObject.toVariantMap();
// Status of request
- QString request_status = mainMap["status"].toString();
- if (request_status == "success") {
- qDebug() << "Successfully started a Session.";
- this->setStatus("start_session_success");
-
- // Immediately ask for the status of the session
- QTimer::singleShot(0, this, &Session::statusTimerEvent);
- } else {
- qCritical() << "An error occured while creating a new session!";
- this->init_vars();
- this->setStatus("start_session_error");
+ QString status = mainMap["status"].toString();
+ if (status != "success") {
+ QString type = mainMap["type"].toString();
+ QString error_message = tr("An error occured while creating a new session!");
+
+ if (type == "multiple") {
+ // TODO: Ask to stop other session via a message dialog.
+ error_message = tr("The session service is configured "
+ "to not support multiple sessions "
+ "and there is already a session running.");
+ } else if (type == "connection") {
+ error_message = tr("Couldn't connect to host '%0'.")
+ .arg(getHost()->alias());
+ } else if (type == "host_not_found") {
+ error_message = tr("The RWA host '%0' couldn't be found.")
+ .arg(getHost()->alias());
+ } else if (type == "permission_denid") {
+ error_message = tr("The RWA host '%0' doesn't grant access.")
+ .arg(getHost()->alias());
+ } else if (type == "unsupported_server") {
+ error_message = tr("The RWA host '%0' is not supported.")
+ .arg(getHost()->alias());
+ }
+
+ setStatus("start_session_error");
+ qCritical().noquote() << error_message;
+ emit startFailed(error_message);
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 <service_id> out of dbus answer!");
- init_vars();
- return;
- }
// URL of remote web app frontend
QString url = mainMap["url"].toString();
@@ -325,178 +164,108 @@ void Session::start_dbus_replied(QDBusPendingCallWatcher *call) {
// PIN
long long pin = mainMap["pin"].toLongLong(&ok);
- this->setPin(QString::number(pin));
// Sanity Check
if(ok == false){
- qErrnoWarning("Unable to parse <pin> out of dbus answer!");
- init_vars();
+ QString error_message = "Unable to parse <pin> into longo long out of dbus answer!";
+ qCritical().noquote() << error_message;
+ emit startFailed(error_message);
return;
}
+ this->setPin(QString::number(pin));
// session_id = remote support id from the rwa-server
long long session_id = mainMap["session_id"].toLongLong();
- this->setSessionID(QString::number(session_id));
// Sanity Check
if(ok == false){
- qErrnoWarning("Unable to parse <pin> out of dbus answer!");
- init_vars();
+ QString error_message = "Unable to parse <session_id> into long long out of dbus answer!";
+ qCritical().noquote() << error_message;
+ emit startFailed(error_message);
return;
}
+ this->setSessionID(QString::number(session_id));
- 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 <QString> id to <long long>");
- return;
- }
-
- // Stopping now.
- qDebug() << "Requesting D-Bus session service to stop session #" << id;
+ started = true;
- // 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);
+ // Ask status every 1000 millisecond
- QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
- this, SLOT(stop_dbus_replied(QDBusPendingCallWatcher*)));
+ QTimer *timer = new QTimer(this);
+ connect(timer, &QTimer::timeout, this,
+ QOverload<>::of(&Session::statusTimerEvent));
+ timer->start(1000);
- // Clear current variables
- this->init_vars();
+ qDebug() << "Successfully started a session.";
+ this->setStatus("start_session_success");
- // 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);
+ emit startSucceeded();
}
-void Session::stop_dbus_replied(QDBusPendingCallWatcher *call) {
- QString result = "";
-
- QDBusPendingReply<QString> 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");
+void Session::stop() {
+ if (started)
+ _dbus_api->stop_request(getHost(), getSessionID());
+}
+void Session::stop_response(QJsonDocument *doc) {
+ // Q_ASSERT lets the program crash immediatly after method call
+ // when the session service is not started.
+ // Don't use Q_ASSERT(doc != nullptr); instead use:
+ if (doc == nullptr) {
+ emit stopFailed(tr("Can't connect to underlying session service! "
+ "Is the session service started?"));
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() << "stop_dbus_replied(): Refreshed status:" << new_status;
+ qDebug() << "stop_response() retrieved json. Status now:" << new_status;
- // Clear current variables
- this->init_vars();
+ started = false;
- // But the status indicator should display that the Session has stopped
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 <QString> id to <long long>");
- 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*)));
+ emit stopSucceeded();
}
-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 <QString> id to <long long>");
- 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() {
+ _dbus_api->status_request(getHost(), this->getSessionID());
}
-void Session::status_dbus_replied(QDBusPendingCallWatcher *call) {
- QString result = "";
-
- QDBusPendingReply<QString> reply = *call;
- if (reply.isError()) {
- qDebug() << "D-Bus '(refresh_)status' request failed, this was the reply:";
- qDebug() << reply.error();
+void Session::refresh_status() {
+ _dbus_api->refresh_status_request(getHost(), this->getSessionID());
+}
- this->init_vars();
+void Session::status_response(QJsonDocument *doc) {
+ // Q_ASSERT lets the program crash immediatly after method call,
+ // when the session service is not started.
+ // Don't use Q_ASSERT(doc != nullptr); instead use:
+ if (doc == nullptr) {
+ if (!_emitted_status_error_already) {
+ emit statusFailed(tr("Can't connect to underlying session service! "
+ "Is the session service started?"));
- this->setStatus("status_session_error");
+ _emitted_status_error_already = true;
+ }
return;
- } else {
- result = reply.argumentAt<0>();
}
- call->deleteLater();
- // Get the QJsonObject
- QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8());
- QJsonObject jObject = doc.object();
+ _emitted_status_error_already = false;
+
+ QJsonObject jObject = doc->object();
QVariantMap mainMap = jObject.toVariantMap();
QString new_status = mainMap["status"].toString();
- qDebug() << "status_dbus_replied(): Refreshed status:" << new_status;
-
- // Enable (dis)connect button
- _main_gui->setConnectButtonEnabled(true);
-
- this->setStatus(new_status);
+ qDebug() << "status_response() retrieved json. Status:" << new_status;
- if (this->isSessionAliveOrRunning(new_status)) {
- // Ask status every 1000 millisecond
- QTimer::singleShot(1000, this, &Session::statusTimerEvent);
- }
-}
+ setStatus(new_status);
-void Session::onCloseHandler() {
- // To cleanup things here
- this->stop_request_dbus(this->getID());
+ emit statusSucceeded();
}