summaryrefslogtreecommitdiffstats
path: root/src/pvs.cpp
diff options
context:
space:
mode:
authorSebastian2010-05-12 19:42:27 +0200
committerSebastian2010-05-12 19:42:27 +0200
commitce3329047d378a14006ce74ec273ac59e3375303 (patch)
tree782430f270b4c7aca1b35d5b7813518e3797c555 /src/pvs.cpp
downloadpvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip
initial import of latest svn version
Diffstat (limited to 'src/pvs.cpp')
-rw-r--r--src/pvs.cpp629
1 files changed, 629 insertions, 0 deletions
diff --git a/src/pvs.cpp b/src/pvs.cpp
new file mode 100644
index 0000000..2069e36
--- /dev/null
+++ b/src/pvs.cpp
@@ -0,0 +1,629 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ */
+
+#include "pvs.h"
+#include "src/util/dispatcher.h"
+#include "src/net/pvsMsg.h"
+#include "src/net/pvsServiceDiscovery.h"
+#include "src/net/pvsDiscoveredServer.h"
+
+// D-Bus
+#include "pvsadaptor.h"
+
+extern PVS *mainClient;
+
+// !!STATION LOCK TESTING!!
+//#define lock_test_unlock_time 3
+// uncomment the following line to test locking in a local context
+// it disables the lock of a station #(lock_test_unlock_time) seconds after it has been locked
+//#define lock_test
+
+PVS::PVS() :
+ QObject()
+{
+ _pvsServerConnection = new PVSServerConnection(this);
+ _locked = false;
+ _vncAllowed = false;
+ _vncRequested = false;
+ readPolicyFiles();
+ loadCommands();
+ _blankScreen = NULL;
+ _vncPort = -1;
+
+ // add a notify to the allow file, so we get informed when the file is changed
+ QString watchPath("/home/");
+ watchPath.append(getUserName().append(QString("/.pvs/.allow")));
+ _notify = new QFileSystemWatcher(this);
+ _notify->addPath(QString(watchPath.toUtf8().data()));
+
+ connect(_notify, SIGNAL(fileChanged(const QString &)), this,
+ SLOT(fileChanged(const QString &)));
+
+ // connect to D-Bus
+ new PvsAdaptor(this);
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/", this);
+ dbus.registerService("org.openslx.pvs");
+
+ _sdClient = new PVSServiceDiscovery(this);
+
+ _chat = new PVSChatClient();
+ _chat->setServerConnection(_pvsServerConnection);
+ _chat->getChatMsgHandler().addListener(this, &PVS::chat_receive);
+ _chat->getChatCommandHandler().addListener(this, &PVS::UpdateChatClients);
+
+ _timerLockTest = 0;
+ _timerLockDelay = 0;
+
+ //add signalhandling for sigterm signals
+ struct sigaction act;
+ act.sa_handler = &PVS::signalHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ //register signals with actions
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+
+}
+
+PVS::~PVS()
+{
+ // make sure we dont leave a locked computer
+ if (_notify)
+ disconnect(_notify, SIGNAL(fileChanged(const QString &)), this,
+ SLOT(fileChanged(const QString &)));
+ unlock();
+ delete _sdClient;
+}
+
+void PVS::connectToHost(PVSDiscoveredServer* server, QString passwd)
+{
+ _pvsServerConnection->connectToServer(server, passwd);
+}
+
+/**
+ * onCommand Callback method
+ * handles incoming commands
+ */
+void PVS::onCommand(PVSMsg cmdMessage)
+{
+ QString message = cmdMessage.getMessage();
+ QString ident = cmdMessage.getIdent();
+ if (ident.compare("LOCKSTATION") == 0)
+ {
+ if (_blankScreen)
+ {
+ return;
+ }
+ else
+ {
+ _lockMsg = message;
+ //TODO:@Javier: lock it eith message.
+ // Sent message.
+ if(message.size() > 0) // Lock client with message.
+ {
+ message = message + "\n \n WARNING: Your screen will be blocked in 10 seconds.";
+ emit showMessage("Lock Message", message, true);
+ _timerLockDelay = startTimer(10*1000); // 10 sec.
+ }
+ else // lock client without message.
+ {
+ lock();
+ }
+ }
+
+ return;
+ }
+ if (ident.compare("UNLOCKSTATION") == 0)
+ {
+ _timerLockDelay = 0;
+ if (!_blankScreen)
+ {
+ return;
+ }
+ else
+ {
+ ConsoleLog writeLine("Unlocked.");
+ unlock();
+ }
+ return;
+ }
+ if (ident.compare("VNCREQUEST") == 0)
+ {
+ // a vnc connection was requested, so lets check if this is against our policies
+ _vncRequested = (message.compare("YES") == 0);
+ if (!_vncRequested) return;
+ getVNCAllow();
+ return;
+ }
+ if (ident.compare("PROJECT") == 0)
+ {
+ std::vector<QString> connDetails;
+ std::string buf;
+ std::stringstream ss(message.toStdString());
+ while (ss >> buf)
+ connDetails.push_back(QString::fromStdString(buf));
+
+ if(connDetails.size() == 4) {
+ int port, quality;
+ bool fullscreen, smooth;
+ fullscreen = smooth = true;
+ port = connDetails[1].toInt();
+ quality = connDetails[3].toInt();
+ if(port > 0) {
+ emit project(connDetails[0], port, connDetails[2], fullscreen, smooth, quality);
+ lock_inputs();
+ ConsoleLog writeNetwork(QString("Received Projection Information: Projsrc: ").append(connDetails[0]).append( " port: ").append(connDetails[1]).append(" pass:").append(connDetails[2]));
+ }
+ ConsoleLog writeNetwork(QString("Received illegal port! (").append(port).append(")"));
+ }
+ }
+ if (ident.compare("UNPROJECT") == 0)
+ {
+ emit unproject();
+ unlock();
+ return;
+ }
+
+#ifdef never
+ // prototype
+ if (command.compare(<<string>>) == 0)
+ {
+ // do stuff
+ return;
+ }
+#endif
+}
+
+/**
+ * onLogin Callback method
+ * handles the servers login messages (see PVSListenServer)
+ */
+void PVS::onLogin(PVSMsg login)
+{
+ if (login.getIdent().compare(QString("ACCEPTED")) == 0)
+ {
+ ConsoleLog writeNetwork("Server accepted connection.");
+ login.getMessage();
+ }
+ else if (login.getIdent().compare(QString("DENIED")) == 0)
+ {
+
+ ConsoleLog writeNetwork(QString("Sent Username."));
+ }
+}
+
+void PVS::chat_send(QString nick_to, QString nick_from, QString msg)
+{
+ _chat->send(nick_to, msg);
+}
+
+void PVS::UpdateChatClients(PVSChatMsg chatCommand)
+{
+ if(chatCommand.getCommand().compare("clientToAdd") == 0)
+ {
+ _chat->addClient(chatCommand.getUsername(), chatCommand.getIp());
+ emit chat_client_add(chatCommand.getUsername());
+ }
+
+ if(chatCommand.getCommand().compare("clientToRemove") == 0)
+ {
+ _chat->removeClient(chatCommand.getUsername());
+ emit chat_client_remove(chatCommand.getUsername());
+ }
+
+ if(chatCommand.getCommand().compare("assignedName") == 0)
+ {
+ _chat->setSource(chatCommand.getUsername());
+ }
+}
+
+void PVS::chat_receive(PVSChatMsg msg)
+{
+ emit chat_receive(msg.getNickFrom(), msg.getNickTo(), msg.getMsg());
+}
+
+/**
+ * onDaemon Callback method
+ * handles incoming UDS Communicator messages
+ */
+void PVS::onDaemonCommand(PVSMsg msg)
+{
+ if (msg.getIdent().compare(QString("stop")) == 0)
+ {
+ stop();
+ unlock();
+ exit(0);
+ }
+}
+
+void PVS::onMessage(PVSMsg msg)
+{
+ QString ident = msg.getIdent();
+ QString message = msg.getMessage();
+
+ if (ident.compare("BROADCAST") == 0)
+ {
+ emit showMessage(tr("Message"), message, true);
+ }
+}
+
+/**
+ * load custom commands by adding callbacks to the dispatchers
+ */
+void PVS::loadCommands()
+{
+ if (_pvsServerConnection)
+ {
+ _pvsServerConnection->addCommandHandler("*", this, &PVS::onCommand);
+ _pvsServerConnection->addLoginHandler("*", this, &PVS::onLogin);
+ _pvsServerConnection->addChatHandler("*", this, &PVS::onMessage);
+ }
+}
+
+void PVS::quit()
+{
+ stop();
+ unlock();
+ exit(0);
+}
+
+/**
+ * stops the client
+ */
+void PVS::stop()
+{
+ _pvsServerConnection->disconnectFromServer();
+ stopVNCScript();
+}
+
+/**
+ * used to unlock the client after 3 seconds
+ * this a maintainance method
+ * uncomment the define to use it
+ */
+void PVS::timerEvent(QTimerEvent *event)
+{
+#ifdef lock_test
+ if (_locked && event->timerId()== _timerLockTest) unlock();
+#endif
+ if(_timerLockDelay == event->timerId())
+ {
+ if (lock()) ConsoleLog writeLine(QString("Locked."));
+ _timerLockDelay = 0;
+ }
+ killTimer(event->timerId());
+}
+
+bool PVS::allowExists()
+{
+ return policyFileExists(QString(".allow"));
+}
+
+/**
+ * check whether we want to allow vnc connections to this client
+ */
+bool PVS::getVNCAllow()
+{
+ if (allowExists())
+ {
+ if (getAllowed())
+ {
+ _vncAllowed = true;
+ }
+ else
+ {
+ _vncAllowed = false;
+ }
+ }
+ else
+ {
+ ConsoleLog writeError("No .allow file found.");
+ _vncAllowed = false;
+ //make sure the vncsever is off
+ ConsoleLog writeError("Shutting down vnc-server because we have no .allow file.");
+ }
+
+ if (_vncAllowed && _vncRequested)
+ {
+ // then boot up the vnc-server and set password and port
+ int result = bootVNC();
+ if (result == 0)
+ {
+ // now inform the server
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PORT", int2String(_vncPort)));
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PASSWORD", _vncPassword));
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "RWPASSWORD", _vncRwPassword));
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "VNC","YES"));
+ ConsoleLog writeNetwork(QString("Sent password, port and granted access."));
+ // show message on clientgui
+ emit showMessage(tr("VNC connection"), tr("The host ")
+ .append(_pvsServerConnection->getServerName()
+ .append(tr(" requested your screen!"))));
+ }
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "VNCSRVRESULT", int2String(result)));
+
+ }
+ else if (!_vncAllowed)
+ {
+ stopVNCScript();
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "VNC","NO"));
+ }
+ return _vncAllowed;
+}
+
+/**
+ * read the policy files
+ */
+void PVS::readPolicyFiles()
+{
+ getVNCAllow();
+ // Add more policyfiles here if any
+}
+
+/**
+ * callback which gets invoked when the watched file is changed
+ */
+void PVS::fileChanged(const QString& path)
+{
+ getVNCAllow();
+}
+
+/**
+ * lock the client
+ */
+bool PVS::lock()
+{
+
+#ifdef lock_test
+ _timerLockTest = startTimer(lock_test_unlock_time * 1000);
+ printf("will auto-unlock in %d secs\n", int(lock_test_unlock_time));
+#endif
+
+ if (!_blankScreen)
+ {
+ _blankScreen = new BlankScreen();
+ if (_blankScreen)
+ return _locked = _blankScreen->lock();
+ else
+ return false;
+ }
+ return true;
+}
+
+/**
+ * lock the client inputs only
+ */
+bool PVS::lock_inputs()
+{
+
+#ifdef lock_test
+ _timerLockTest = startTimer(lock_test_unlock_time * 1000);
+ printf("will auto-unlock in %d secs\n", int(lock_test_unlock_time));
+#endif
+
+ if (!_blankScreen)
+ {
+ _blankScreen = new BlankScreen();
+ if (_blankScreen)
+ return _locked = _blankScreen->lock_inputs();
+ else
+ return false;
+ }
+ return true;
+}
+
+/**
+ * unlock the client
+ */
+bool PVS::unlock()
+{
+ if (_blankScreen)
+ {
+ if (_blankScreen->unlock())
+ {
+ delete _blankScreen;
+ _blankScreen = NULL;
+ }
+ }
+ return false;
+}
+
+void PVS::setScriptPath(QString path)
+{
+ _vncScriptPath = path;
+ _vncScriptName = getFilenameFromPath(_vncScriptPath);
+}
+
+bool PVS::gotVNCScript()
+{
+ if (fileExists(_vncScriptPath))
+ return true;
+ if (policyFileExists(_vncScriptName))
+ return true;
+ return false;
+
+}
+/**
+ * setup password and port
+ * the local_test define is used to enable local testing modes without invoking the vnc-script
+ */
+int PVS::bootVNC()
+{
+ // #define local_test
+
+ stopVNCScript(); // just to be sure
+#ifndef local_test
+ _vncPassword = int2String(getRandom(0, 99999999));
+ do {
+ _vncRwPassword = int2String(getRandom(0, 99999999));
+ } while (_vncRwPassword == _vncPassword);
+
+ _vncPort = getRandom(5901, 6000);
+ return startVNCScript(_vncPort, _vncPassword, _vncRwPassword);
+#else
+ _vncPassword = QString("1234");
+ _vncPort = 5901;
+ return startVNCScript(_vncPort, _vncPassword);
+#endif
+ //#undef local_test
+}
+
+/**
+ * launch the vnc script (if present) to start the vnc-server
+ */
+int PVS::startVNCScript(int port, QString pass, QString rwpass)
+{
+ if (gotVNCScript())
+ {
+ ConsoleLog writeLine("Starting VNC-Script");
+ QString commandLine(_vncScriptPath);
+ commandLine.append(" ");
+ commandLine.append("start");
+ commandLine.append(" ");
+ commandLine.append(int2String(port));
+ commandLine.append(" ");
+ commandLine.append(pass);
+ commandLine.append(" ");
+ commandLine.append(rwpass);
+ if (!system(NULL))
+ ConsoleLog writeError("No Command processor available");
+
+ int result = system(commandLine.toUtf8().data());
+ result = WEXITSTATUS(result);
+ if (result != 0)
+ ConsoleLog writeError(QString("VNC-Server is not running, code: ") + int2String(result));
+ else
+ ConsoleLog writeLine("VNC-Server should be running");
+ return result;
+ }
+ else
+ {
+ ConsoleLog writeError("VNC-Script not found.");
+ return 3;
+ }
+}
+
+/**
+ * launch the vnc script (if present) to stop the vnc-server
+ */
+int PVS::stopVNCScript()
+{
+ if (gotVNCScript())
+ {
+ ConsoleLog writeLine("Stopping VNC-Script");
+ QString commandLine(_vncScriptPath);
+ commandLine.append(" ");
+ commandLine.append("stop");
+ commandLine.append(" ");
+ commandLine.append("dummy");
+ commandLine.append(" ");
+ commandLine.append("dummy");
+ ConsoleLog writeLine("VNC-Server should be stopped");
+ int result = system(commandLine.toUtf8().data());
+ return WEXITSTATUS(result);
+ }
+ else
+ {
+ return 3;
+ }
+}
+
+void PVS::start()
+{
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROJECTING", "YES"));
+}
+
+void PVS::onConnected(QString name)
+{
+ emit connected(name);
+}
+
+void PVS::onDisconnected()
+{
+ emit disconnected();
+ _chat->clearClients();
+ stopVNCScript();
+}
+
+QString PVS::isConnected()
+{
+ return _pvsServerConnection->getServerName();
+}
+
+QString PVS::chat_getNickname()
+{
+ return _chat->getSource();
+}
+
+QStringList PVS::chat_getNicknames()
+{
+ return _chat->getClients();
+}
+
+void PVS::pvsConnect(QString host, QString passwd)
+{
+ _pvsServerConnection->disconnectFromServer();
+ _sdClient->connectToSession(host, passwd);
+}
+void PVS::pvsDisconnect()
+{
+ _chat->clearClients();
+ _sdClient->connectToSession("", "");
+ stop();
+}
+
+
+QStringList PVS::getAvailableHosts()
+{
+ return _sdClient->getAllServers();
+}
+
+void PVS::guiAddHost(QString host)
+{
+ emit addHost(host);
+}
+
+void PVS::guiDelHost(QString host)
+{
+ emit delHost(host);
+}
+
+QString PVS::getIpByNick(QString nick)
+{
+ return _chat->getIPFromUsername(nick);
+}
+
+//Handles signals (SIGTERM and SIGHUP)
+void PVS::signalHandler(int signal)
+{
+ ConsoleLog writeLine(QString("Received Signal ").append (int2String(signal)));
+ switch (signal) {
+ case SIGHUP:
+ mainClient->quit();
+ break;
+ case SIGTERM:
+ mainClient->quit();
+ break;
+ case SIGINT:
+ mainClient->quit();
+ break;
+ case SIGQUIT:
+ mainClient->quit();
+ break;
+ }
+
+}
+