diff options
author | Sebastian | 2010-05-12 19:42:27 +0200 |
---|---|---|
committer | Sebastian | 2010-05-12 19:42:27 +0200 |
commit | ce3329047d378a14006ce74ec273ac59e3375303 (patch) | |
tree | 782430f270b4c7aca1b35d5b7813518e3797c555 /src/pvs.cpp | |
download | pvs-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.cpp | 629 |
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; + } + +} + |